modernc.org/ccgo/v3@v3.16.14/lib/go.go (about)

     1  // Copyright 2020 The CCGO Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package ccgo // import "modernc.org/ccgo/v3/lib"
     6  
     7  import (
     8  	"bytes"
     9  	"fmt"
    10  	"go/scanner"
    11  	"go/token"
    12  	"hash/maphash"
    13  	"io/ioutil"
    14  	"math"
    15  	"math/big"
    16  	"os"
    17  	"os/exec"
    18  	"path/filepath"
    19  	"runtime"
    20  	"sort"
    21  	"strconv"
    22  	"strings"
    23  	"sync"
    24  	"time"
    25  
    26  	"modernc.org/cc/v3"
    27  	"modernc.org/mathutil"
    28  )
    29  
    30  var (
    31  	idAddOverflow          = cc.String("__builtin_add_overflow") // bool __builtin_add_overflow (type1 a, type2 b, type3 *res)
    32  	idAlias                = cc.String("alias")
    33  	idAligned              = cc.String("aligned")          // int __attribute__ ((aligned (8))) foo;
    34  	idAtomicLoadN          = cc.String("__atomic_load_n")  // type __atomic_load_n (type *ptr, int memorder)
    35  	idAtomicStoreN         = cc.String("__atomic_store_n") // void __atomic_store_n (type *ptr, type val, int memorder)
    36  	idBp                   = cc.String("bp")
    37  	idBuiltinConstantPImpl = cc.String("__builtin_constant_p_impl")
    38  	idCAPI                 = cc.String("CAPI")
    39  	idChooseExpr           = cc.String("__builtin_choose_expr")
    40  	idEnviron              = cc.String("environ")
    41  	idMain                 = cc.String("main")
    42  	idMulOverflow          = cc.String("__builtin_mul_overflow") // bool __builtin_mul_overflow (type1 a, type2 b, type3 *res)
    43  	idPacked               = cc.String("packed")                 // __attribute__((packed))
    44  	idSubOverflow          = cc.String("__builtin_sub_overflow") // bool __builtin_sub_overflow (type1 a, type2 b, type3 *res)
    45  	idTls                  = cc.String("tls")
    46  	idTransparentUnion     = cc.String("__transparent_union__")
    47  	idTs                   = cc.String("ts")
    48  	idVa                   = cc.String("va")
    49  	idVaArg                = cc.String("__ccgo_va_arg")
    50  	idVaEnd                = cc.String("__ccgo_va_end")
    51  	idVaList               = cc.String("va_list")
    52  	idVaStart              = cc.String("__ccgo_va_start")
    53  	idWcharT               = cc.String("wchar_t")
    54  	idWinWchar             = cc.String("WCHAR")
    55  	idWtext                = cc.String("wtext")
    56  
    57  	bytesBufferPool = sync.Pool{New: func() interface{} { return &bytes.Buffer{} }}
    58  
    59  	oTraceG   bool
    60  	oTraceW   bool
    61  	oTracePin bool
    62  )
    63  
    64  type exprMode int
    65  
    66  const (
    67  	doNotExport = iota
    68  	doNotChange
    69  	exportCapitalize
    70  	exportPrefix
    71  )
    72  
    73  const (
    74  	_              exprMode = iota
    75  	exprAddrOf              // &foo as uinptr (must be static/pinned)
    76  	exprBool                // foo in foo != 0
    77  	exprCondInit            // foo or bar in int i = x ? foo : bar;
    78  	exprCondReturn          // foo or bar in return x ? foo : bar;
    79  	exprDecay               // &foo[0] in foo for array foo.
    80  	exprFunc                // foo in foo(bar)
    81  	exprLValue              // foo in foo = bar
    82  	exprPSelect             // foo in foo->bar
    83  	exprSelect              // foo in foo.bar
    84  	exprValue               // foo in bar = foo
    85  	exprVoid                //
    86  	exprGoPtr
    87  )
    88  
    89  const (
    90  	tooManyErrors = "too many errors"
    91  )
    92  
    93  type opKind int
    94  
    95  const (
    96  	opNormal opKind = iota
    97  	opArray
    98  	opArrayParameter
    99  	opFunction
   100  	opUnion
   101  	opBitfield
   102  	opStruct
   103  )
   104  
   105  type flags byte
   106  
   107  const (
   108  	fForceConv flags = 1 << iota
   109  	fForceNoConv
   110  	fForceRuntimeConv
   111  	fNoCondAssignment
   112  	fAddrOfFuncPtrOk
   113  	fVolatileOk
   114  )
   115  
   116  type imported struct {
   117  	path      string              // Eg. "example.com/user/foo".
   118  	name      string              // Eg. "foo" from "package foo".
   119  	qualifier string              // Eg. "foo." or "foo2." if renamed due to name conflict.
   120  	exports   map[string]struct{} // Eg. {"New": {}, "Close": {}, ...}.
   121  
   122  	used bool
   123  }
   124  
   125  type taggedStruct struct {
   126  	ctyp  cc.Type
   127  	gotyp string
   128  	name  string
   129  	node  cc.Node
   130  
   131  	conflicts bool
   132  	emitted   bool
   133  }
   134  
   135  func (s *taggedStruct) emit(p *project, ds *cc.DeclarationSpecifiers) {
   136  	if s == nil || s.emitted {
   137  		return
   138  	}
   139  
   140  	s.emitted = true
   141  	p.w("%stype %s = %s; /* %v */\n\n", tidyComment("\n", ds), s.name, s.gotyp, p.pos(s.node))
   142  }
   143  
   144  // Return first non empty token separator within n or dflt otherwise.
   145  func comment(dflt string, n cc.Node) string {
   146  	if s := tokenSeparator(n); s != "" {
   147  		return s
   148  	}
   149  
   150  	return dflt
   151  }
   152  
   153  // tidyComment is like comment but makes comment more Go-like.
   154  func tidyComment(dflt string, n cc.Node) (r string) { return tidyCommentString(comment(dflt, n)) }
   155  
   156  func tidyCommentString(s string) (r string) {
   157  	defer func() {
   158  		if !strings.Contains(r, "// <blockquote><pre>") {
   159  			return
   160  		}
   161  
   162  		a := strings.Split(r, "\n")
   163  		in := false
   164  		for i, v := range a {
   165  			switch {
   166  			case in:
   167  				if strings.HasPrefix(v, "// </pre></blockquote>") {
   168  					in = false
   169  					a[i] = "//"
   170  					break
   171  				}
   172  
   173  				a[i] = fmt.Sprintf("//\t%s", v[3:])
   174  			default:
   175  				if strings.HasPrefix(v, "// <blockquote><pre>") {
   176  					a[i] = "//"
   177  					in = true
   178  				}
   179  			}
   180  		}
   181  		r = strings.Join(a, "\n")
   182  	}()
   183  
   184  	s = strings.ReplaceAll(s, "\f", "")
   185  	b := bytesBufferPool.Get().(*bytes.Buffer)
   186  	defer func() { b.Reset(); bytesBufferPool.Put(b) }()
   187  	for len(s) != 0 {
   188  		c := s[0]
   189  		s = s[1:]
   190  		if len(s) == 0 {
   191  			b.WriteByte(c)
   192  			break
   193  		}
   194  
   195  		if c != '/' {
   196  			b.WriteByte(c)
   197  			continue
   198  		}
   199  
   200  		c2 := s[0]
   201  		s = s[1:]
   202  		switch c2 {
   203  		case '/': // line comment start
   204  			b.WriteByte(c)
   205  			b.WriteByte(c2)
   206  			for {
   207  				c := s[0]
   208  				s = s[1:]
   209  				b.WriteByte(c)
   210  				if c == '\n' {
   211  					break
   212  				}
   213  			}
   214  		case '*': // block comment start
   215  			b2 := bytesBufferPool.Get().(*bytes.Buffer)
   216  			defer func() { b2.Reset(); bytesBufferPool.Put(b2) }()
   217  			for {
   218  				c := s[0]
   219  				s = s[1:]
   220  				if c != '*' {
   221  					b2.WriteByte(c)
   222  					continue
   223  				}
   224  
   225  			more:
   226  				c2 := s[0]
   227  				s = s[1:]
   228  				if c2 == '*' {
   229  					b2.WriteByte(c)
   230  					goto more
   231  				}
   232  
   233  				if c2 != '/' {
   234  					b2.WriteByte(c)
   235  					b2.WriteByte(c2)
   236  					continue
   237  				}
   238  
   239  				break
   240  			}
   241  			s2 := b2.String() // comment sans /* prefix and */ suffix
   242  			a := strings.Split(s2, "\n")
   243  			nl := len(s) != 0 && s[0] == '\n'
   244  			if len(a) == 1 { // /* foo */ form
   245  				if nl {
   246  					s = s[1:]
   247  					fmt.Fprintf(b, "//%s\n", s2)
   248  					break
   249  				}
   250  
   251  				fmt.Fprintf(b, "/*%s*/", s2)
   252  				break
   253  			}
   254  
   255  			if !nl {
   256  				fmt.Fprintf(b, "/*%s*/", s2)
   257  				break
   258  			}
   259  
   260  			// Block comment followed by a newline can be safely replaced by a sequence of
   261  			// line comments.  Try to enhance the comment.
   262  			if commentForm1(b, a) ||
   263  				commentForm2(b, a) ||
   264  				commentForm3(b, a) {
   265  				break
   266  			}
   267  
   268  			// No enhancement posibilities detected, use the default form.
   269  			if a[len(a)-1] == "" {
   270  				a = a[:len(a)-1]
   271  			}
   272  			fmt.Fprintf(b, "//%s", a[0])
   273  			for _, v := range a[1:] {
   274  				fmt.Fprintf(b, "\n// %s", v)
   275  			}
   276  		default:
   277  			b.WriteByte(c)
   278  			b.WriteByte(c2)
   279  		}
   280  	}
   281  	return b.String()
   282  }
   283  
   284  func commentForm1(b *bytes.Buffer, a []string) bool {
   285  	// Example
   286  	//
   287  	//	/*
   288  	//	** Initialize this module.
   289  	//	**
   290  	//	** This Tcl module contains only a single new Tcl command named "sqlite".
   291  	//	** (Hence there is no namespace.  There is no point in using a namespace
   292  	//	** if the extension only supplies one new name!)  The "sqlite" command is
   293  	//	** used to open a new SQLite database.  See the DbMain() routine above
   294  	//	** for additional information.
   295  	//	**
   296  	//	** The EXTERN macros are required by TCL in order to work on windows.
   297  	//	*/
   298  	if strings.TrimSpace(a[0]) != "" {
   299  		return false
   300  	}
   301  
   302  	if strings.TrimSpace(a[len(a)-1]) != "" {
   303  		return false
   304  	}
   305  
   306  	a = a[1 : len(a)-1]
   307  	if len(a) == 0 {
   308  		return false
   309  	}
   310  
   311  	for i, v := range a {
   312  		v = strings.TrimSpace(v)
   313  		if !strings.HasPrefix(v, "*") {
   314  			return false
   315  		}
   316  
   317  		a[i] = strings.TrimLeft(v, "*")
   318  	}
   319  
   320  	fmt.Fprintf(b, "//%s", a[0])
   321  	for _, v := range a[1:] {
   322  		fmt.Fprintf(b, "\n//%s", v)
   323  	}
   324  	return true
   325  }
   326  
   327  func commentForm2(b *bytes.Buffer, a []string) bool {
   328  	// Example
   329  	//
   330  	//	/**************************** sqlite3_column_  *******************************
   331  	//	** The following routines are used to access elements of the current row
   332  	//	** in the result set.
   333  	//	*/
   334  	if strings.TrimSpace(a[len(a)-1]) != "" {
   335  		return false
   336  	}
   337  
   338  	a = a[:len(a)-1]
   339  	if len(a) == 0 {
   340  		return false
   341  	}
   342  
   343  	for i, v := range a[1:] {
   344  		v = strings.TrimSpace(v)
   345  		if !strings.HasPrefix(v, "*") {
   346  			return false
   347  		}
   348  
   349  		a[i+1] = strings.TrimLeft(v, "*")
   350  	}
   351  
   352  	fmt.Fprintf(b, "// %s", strings.TrimSpace(a[0]))
   353  	if strings.HasPrefix(a[0], "**") && strings.HasSuffix(a[0], "**") {
   354  		fmt.Fprintf(b, "\n//")
   355  	}
   356  	for _, v := range a[1:] {
   357  		fmt.Fprintf(b, "\n//%s", v)
   358  	}
   359  	return true
   360  }
   361  
   362  func commentForm3(b *bytes.Buffer, a []string) bool {
   363  	// Example
   364  	//
   365  	//	/* Call sqlite3_shutdown() once before doing anything else. This is to
   366  	//	** test that sqlite3_shutdown() can be safely called by a process before
   367  	//	** sqlite3_initialize() is. */
   368  	for i, v := range a[1:] {
   369  		v = strings.TrimSpace(v)
   370  		if !strings.HasPrefix(v, "*") {
   371  			return false
   372  		}
   373  
   374  		a[i+1] = strings.TrimLeft(v, "*")
   375  	}
   376  
   377  	fmt.Fprintf(b, "// %s", strings.TrimSpace(a[0]))
   378  	if strings.HasPrefix(a[0], "**") && strings.HasSuffix(a[0], "**") {
   379  		fmt.Fprintf(b, "\n//")
   380  	}
   381  	for _, v := range a[1:] {
   382  		fmt.Fprintf(b, "\n//%s", v)
   383  	}
   384  	return true
   385  }
   386  
   387  // Return the preceding white space, including any comments, of the first token
   388  // of n.
   389  func tokenSeparator(n cc.Node) (r string) {
   390  	if n == nil {
   391  		return ""
   392  	}
   393  
   394  	var tok cc.Token
   395  	cc.Inspect(n, func(n cc.Node, _ bool) bool {
   396  		if x, ok := n.(*cc.Token); ok {
   397  			if a, b := tok.Seq(), x.Seq(); a == 0 || a > x.Seq() && b != 0 {
   398  				tok = *x
   399  			}
   400  		}
   401  		return true
   402  	})
   403  	return tok.Sep.String()
   404  }
   405  
   406  func source(n ...cc.Node) (r string) {
   407  	if len(n) == 0 {
   408  		return "<nil>"
   409  	}
   410  
   411  	var a []*cc.Token
   412  	for _, v := range n {
   413  		cc.Inspect(v, func(n cc.Node, _ bool) bool {
   414  			if x, ok := n.(*cc.Token); ok && x.Seq() != 0 {
   415  				a = append(a, x)
   416  			}
   417  			return true
   418  		})
   419  	}
   420  	sort.Slice(a, func(i, j int) bool {
   421  		return a[i].Seq() < a[j].Seq()
   422  	})
   423  	w := 0
   424  	seq := -1
   425  	for _, v := range a {
   426  		if n := v.Seq(); n != seq {
   427  			seq = n
   428  			a[w] = v
   429  			w++
   430  		}
   431  	}
   432  	a = a[:w]
   433  	var b strings.Builder
   434  	for _, v := range a {
   435  		b.WriteString(v.Sep.String())
   436  		b.WriteString(v.Src.String())
   437  	}
   438  	return b.String()
   439  }
   440  
   441  type initPatch struct {
   442  	t    cc.Type
   443  	init *cc.Initializer
   444  	fld  cc.Field
   445  }
   446  
   447  type tld struct {
   448  	name    string // Can differ from the original one.
   449  	patches []initPatch
   450  }
   451  
   452  type block struct {
   453  	block  *cc.CompoundStatement
   454  	decls  []*cc.Declaration // What to declare in this block.
   455  	params []*cc.Parameter
   456  	parent *block
   457  	scope  scope
   458  
   459  	noDecl  bool // Locals declared in one of the parent scopes.
   460  	topDecl bool // Declare locals at block start to avoid "jumps over declaration".
   461  }
   462  
   463  func newBlock(parent *block, n *cc.CompoundStatement, decls []*cc.Declaration, params []*cc.Parameter, scope scope, topDecl bool) *block {
   464  	return &block{
   465  		block:   n,
   466  		decls:   decls,
   467  		params:  params,
   468  		parent:  parent,
   469  		scope:   scope,
   470  		topDecl: topDecl,
   471  	}
   472  }
   473  
   474  type local struct {
   475  	name string
   476  	off  uintptr // If isPinned: bp+off
   477  
   478  	forceRead bool // Possibly never read.
   479  	isPinned  bool // Prevent this local from being placed in Go movable stack.
   480  }
   481  
   482  type switchState int
   483  
   484  const (
   485  	_                 switchState = iota // Not in switch.
   486  	inSwitchFirst                        // Before seeing "case/default".
   487  	inSwitchCase                         // Seen "case/default".
   488  	inSwitchSeenBreak                    // In switch "case/default" and seen "break/return".
   489  	inSwitchFlat
   490  )
   491  
   492  type function struct {
   493  	block            *block
   494  	blocks           map[*cc.CompoundStatement]*block
   495  	bpName           string
   496  	breakCtx         int //TODO merge with continueCtx
   497  	complits         map[*cc.PostfixExpression]uintptr
   498  	condInitPrefix   func()
   499  	continueCtx      int
   500  	flatLabels       int
   501  	flatSwitchLabels map[*cc.LabeledStatement]int
   502  	fndef            *cc.FunctionDefinition
   503  	gen              *project
   504  	ifCtx            cc.Node
   505  	ignore           map[*cc.Declarator]bool // Pseudo declarators
   506  	labelNames       map[cc.StringID]string
   507  	labels           scope
   508  	locals           map[*cc.Declarator]*local
   509  	off              uintptr         // bp+off allocs
   510  	params           []*cc.Parameter // May differ from what fndef says
   511  	project          *project
   512  	rt               cc.Type // May differ from what fndef says
   513  	scope            scope
   514  	switchCtx        switchState
   515  	tlsName          string
   516  	top              *block
   517  	unusedLabels     map[cc.StringID]struct{}
   518  	vaLists          map[*cc.PostfixExpression]uintptr
   519  	vaName           string
   520  	vaType           cc.Type
   521  	vlas             map[*cc.Declarator]struct{}
   522  
   523  	hasJumps            bool
   524  	mainSignatureForced bool
   525  }
   526  
   527  func newFunction(p *project, n *cc.FunctionDefinition) *function {
   528  	d := n.Declarator
   529  	t := d.Type()
   530  	rt := t.Result()
   531  	params := t.Parameters()
   532  	var mainSignatureForced bool
   533  	var ignore map[*cc.Declarator]bool
   534  	if d.Name() == idMain && d.Linkage == cc.External {
   535  		if rt.Kind() != cc.Int {
   536  			rt = p.task.cfg.ABI.Type(cc.Int)
   537  		}
   538  		if len(params) != 2 {
   539  			mainSignatureForced = true
   540  			d1 := newDeclarator("argc")
   541  			t1 := p.task.cfg.ABI.Type(cc.Int)
   542  			d2 := newDeclarator("argv")
   543  			t2 := p.task.cfg.ABI.Ptr(n, p.task.cfg.ABI.Type(cc.Void))
   544  			params = []*cc.Parameter{
   545  				cc.NewParameter(d1, t1),
   546  				cc.NewParameter(d2, t2),
   547  			}
   548  			ignore = map[*cc.Declarator]bool{d1: true, d2: true}
   549  		}
   550  	}
   551  	f := &function{
   552  		blocks:              map[*cc.CompoundStatement]*block{},
   553  		complits:            map[*cc.PostfixExpression]uintptr{},
   554  		fndef:               n,
   555  		gen:                 p,
   556  		hasJumps:            n.CompoundStatement.IsJumpTarget(),
   557  		ignore:              ignore,
   558  		locals:              map[*cc.Declarator]*local{},
   559  		mainSignatureForced: mainSignatureForced,
   560  		params:              params,
   561  		project:             p,
   562  		rt:                  rt,
   563  		scope:               p.newScope(),
   564  		unusedLabels:        map[cc.StringID]struct{}{},
   565  		vaLists:             map[*cc.PostfixExpression]uintptr{},
   566  		vlas:                map[*cc.Declarator]struct{}{},
   567  	}
   568  	f.tlsName = f.scope.take(idTls)
   569  	if t.IsVariadic() {
   570  		f.vaName = f.scope.take(idVa)
   571  	}
   572  	f.layoutLocals(nil, n.CompoundStatement, params)
   573  	var extern []cc.StringID
   574  	for _, v := range n.CompoundStatements() { // testdata/gcc-9.1.0/gcc/testsuite/gcc.c-torture/execute/scope-1.c
   575  		for _, v := range v.Declarations() {
   576  			for list := v.InitDeclaratorList; list != nil; list = list.InitDeclaratorList {
   577  				if d := list.InitDeclarator.Declarator; d != nil && d.IsExtern() {
   578  					extern = append(extern, d.Name())
   579  				}
   580  			}
   581  		}
   582  	}
   583  	for _, v := range n.CompoundStatements() {
   584  		block := f.blocks[v]
   585  		for _, v := range extern {
   586  			if tld := f.project.externs[v]; tld != nil {
   587  				block.scope.take(cc.String(tld.name))
   588  			}
   589  		}
   590  	}
   591  	for _, v := range n.CompoundStatements() {
   592  		f.layoutBlocks(v)
   593  	}
   594  	f.renameLabels()
   595  	f.staticAllocsAndPinned(n.CompoundStatement)
   596  	return f
   597  }
   598  
   599  func (f *function) flatLabel() int {
   600  	if f.project.pass1 {
   601  		return 1
   602  	}
   603  
   604  	f.flatLabels++
   605  	return f.flatLabels
   606  }
   607  
   608  func (f *function) renameLabels() {
   609  	var a []cc.StringID
   610  	for _, v := range f.fndef.Labels {
   611  		if v.Case != cc.LabeledStatementLabel {
   612  			continue
   613  		}
   614  
   615  		a = append(a, v.Token.Value)
   616  		f.unusedLabels[v.Token.Value] = struct{}{}
   617  	}
   618  	for _, v := range f.fndef.Gotos {
   619  		delete(f.unusedLabels, v.Token2.Value)
   620  	}
   621  	if len(a) == 0 {
   622  		return
   623  	}
   624  	sort.Slice(a, func(i, j int) bool { return a[i].String() < a[j].String() })
   625  	f.labels = newScope()
   626  	f.labelNames = map[cc.StringID]string{}
   627  	for _, id := range a {
   628  		f.labelNames[id] = f.labels.take(id)
   629  	}
   630  }
   631  
   632  func (f *function) staticAllocsAndPinned(n *cc.CompoundStatement) {
   633  	for _, v := range f.params {
   634  		switch {
   635  		case v.Type().Kind() == cc.Array && v.Type().IsVLA():
   636  			// trc("VLA")
   637  			f.project.err(f.fndef, "variable length arrays not supported")
   638  		}
   639  	}
   640  
   641  	//TODO use pass1 for this
   642  	cc.Inspect(n, func(n cc.Node, entry bool) bool {
   643  		if !entry {
   644  			return true
   645  		}
   646  
   647  		switch x := n.(type) {
   648  		case *cc.CastExpression:
   649  			switch x.Case {
   650  			case cc.CastExpressionCast: // '(' TypeName ')' CastExpression
   651  				if t := x.TypeName.Type(); t != nil && t.Kind() != cc.Void {
   652  					break
   653  				}
   654  
   655  				if d := x.CastExpression.Declarator(); d != nil {
   656  					if local := f.locals[d]; local != nil {
   657  						local.forceRead = true
   658  					}
   659  				}
   660  			}
   661  		}
   662  
   663  		x, ok := n.(*cc.PostfixExpression)
   664  		if !ok || x.Case != cc.PostfixExpressionCall {
   665  			return true
   666  		}
   667  
   668  		if x.PostfixExpression == nil || x.PostfixExpression.Operand == nil || x.PostfixExpression.Operand.Type() == nil {
   669  			return true
   670  		}
   671  
   672  		ft := funcType(x.PostfixExpression.Operand.Type())
   673  		if ft.Kind() != cc.Function {
   674  			return true
   675  		}
   676  
   677  		if !ft.IsVariadic() {
   678  			return true
   679  		}
   680  
   681  		fixedParams := len(ft.Parameters())
   682  		iArg := 0
   683  		var need uintptr
   684  		for list := x.ArgumentExpressionList; list != nil; list, iArg = list.ArgumentExpressionList, iArg+1 {
   685  			if iArg < fixedParams {
   686  				continue
   687  			}
   688  
   689  			t := list.AssignmentExpression.Operand.Type()
   690  			if t.IsIntegerType() {
   691  				need += 8
   692  				continue
   693  			}
   694  
   695  			switch t.Kind() {
   696  			case cc.Array, cc.Ptr, cc.Double, cc.Float, cc.Function:
   697  				need += 8
   698  			default:
   699  				panic(todo("", f.project.pos(x), t, t.Kind()))
   700  			}
   701  		}
   702  		if need != 0 {
   703  			//TODO- if f.project.task.mingw {
   704  			//TODO- 	need += 8 // On windows the va list is prefixed with its length
   705  			//TODO- }
   706  			va := roundup(f.off, 8)
   707  			f.vaLists[x] = va
   708  			f.off = va + need
   709  		}
   710  		return true
   711  	})
   712  }
   713  
   714  func funcType(t cc.Type) cc.Type {
   715  	if t.Kind() == cc.Ptr {
   716  		t = t.Elem()
   717  	}
   718  	return t
   719  }
   720  
   721  type declarator interface {
   722  	Declarator() *cc.Declarator
   723  	cc.Node
   724  }
   725  
   726  func (p *project) isArrayParameterDeclarator(d *cc.Declarator) bool {
   727  	if d.Type().Kind() == cc.Array {
   728  		if d.Type().IsVLA() {
   729  			return false
   730  		}
   731  
   732  		return d.IsParameter
   733  	}
   734  
   735  	return false
   736  }
   737  
   738  func (p *project) isArrayDeclarator(d *cc.Declarator) bool {
   739  	if d.Type().Kind() == cc.Array {
   740  		if d.Type().IsVLA() {
   741  			return false
   742  		}
   743  
   744  		return !d.IsParameter
   745  	}
   746  
   747  	return false
   748  }
   749  
   750  func (p *project) isArrayParameter(n declarator, t cc.Type) bool {
   751  	if t.Kind() != cc.Array {
   752  		return false
   753  	}
   754  
   755  	if t.IsVLA() {
   756  		return false
   757  	}
   758  
   759  	if d := n.Declarator(); d != nil {
   760  		return d.IsParameter
   761  	}
   762  
   763  	return false
   764  }
   765  
   766  func (p *project) isArrayOrPinnedArray(f *function, n declarator, t cc.Type) (r bool) {
   767  	if t.Kind() != cc.Array {
   768  		return false
   769  	}
   770  
   771  	if t.IsVLA() {
   772  		return false
   773  	}
   774  
   775  	if d := n.Declarator(); d != nil {
   776  		return !d.IsParameter
   777  	}
   778  
   779  	return p.detectArray(f, n.(cc.Node), true, true, nil)
   780  }
   781  
   782  func (p *project) detectArray(f *function, n cc.Node, pinnedOk, recursiveOk bool, out **cc.Declarator) bool {
   783  	switch x := n.(type) {
   784  	case *cc.AssignmentExpression:
   785  		switch x.Case {
   786  		case cc.AssignmentExpressionCond: // ConditionalExpression
   787  			return p.detectArray(f, x.ConditionalExpression, pinnedOk, recursiveOk, out)
   788  		case cc.AssignmentExpressionAssign: // UnaryExpression '=' AssignmentExpression
   789  			return p.detectArray(f, x.UnaryExpression, pinnedOk, recursiveOk, out)
   790  		default:
   791  			return false
   792  		}
   793  	case *cc.ConditionalExpression:
   794  		switch x.Case {
   795  		case cc.ConditionalExpressionLOr: // LogicalOrExpression
   796  			return p.detectArray(f, x.LogicalOrExpression, pinnedOk, recursiveOk, out)
   797  		case cc.ConditionalExpressionCond: // LogicalOrExpression '?' Expression ':' ConditionalExpression
   798  			return p.detectArray(f, x.LogicalOrExpression, pinnedOk, recursiveOk, out) ||
   799  				p.detectArray(f, x.Expression, pinnedOk, recursiveOk, out) ||
   800  				p.detectArray(f, x.ConditionalExpression, pinnedOk, recursiveOk, out)
   801  		default:
   802  			panic(todo("", p.pos(x), x.Case))
   803  		}
   804  	case *cc.LogicalOrExpression:
   805  		switch x.Case {
   806  		case cc.LogicalOrExpressionLAnd: // LogicalAndExpression
   807  			return p.detectArray(f, x.LogicalAndExpression, pinnedOk, recursiveOk, out)
   808  		default:
   809  			return false
   810  		}
   811  	case *cc.LogicalAndExpression:
   812  		switch x.Case {
   813  		case cc.LogicalAndExpressionOr: // InclusiveOrExpression
   814  			return p.detectArray(f, x.InclusiveOrExpression, pinnedOk, recursiveOk, out)
   815  		default:
   816  			return false
   817  		}
   818  	case *cc.InclusiveOrExpression:
   819  		switch x.Case {
   820  		case cc.InclusiveOrExpressionXor: // ExclusiveOrExpression
   821  			return p.detectArray(f, x.ExclusiveOrExpression, pinnedOk, recursiveOk, out)
   822  		default:
   823  			return false
   824  		}
   825  	case *cc.ExclusiveOrExpression:
   826  		switch x.Case {
   827  		case cc.ExclusiveOrExpressionAnd: // AndExpression
   828  			return p.detectArray(f, x.AndExpression, pinnedOk, recursiveOk, out)
   829  		default:
   830  			return false
   831  		}
   832  	case *cc.AndExpression:
   833  		switch x.Case {
   834  		case cc.AndExpressionEq: // EqualityExpression
   835  			return p.detectArray(f, x.EqualityExpression, pinnedOk, recursiveOk, out)
   836  		default:
   837  			return false
   838  		}
   839  	case *cc.EqualityExpression:
   840  		switch x.Case {
   841  		case cc.EqualityExpressionRel: // RelationalExpression
   842  			return p.detectArray(f, x.RelationalExpression, pinnedOk, recursiveOk, out)
   843  		default:
   844  			return false
   845  		}
   846  	case *cc.RelationalExpression:
   847  		switch x.Case {
   848  		case cc.RelationalExpressionShift: // ShiftExpression
   849  			return p.detectArray(f, x.ShiftExpression, pinnedOk, recursiveOk, out)
   850  		default:
   851  			return false
   852  		}
   853  	case *cc.ShiftExpression:
   854  		switch x.Case {
   855  		case cc.ShiftExpressionAdd: // AdditiveExpression
   856  			return p.detectArray(f, x.AdditiveExpression, pinnedOk, recursiveOk, out)
   857  		default:
   858  			return false
   859  		}
   860  	case *cc.AdditiveExpression:
   861  		switch x.Case {
   862  		case cc.AdditiveExpressionMul: // MultiplicativeExpression
   863  			return p.detectArray(f, x.MultiplicativeExpression, pinnedOk, recursiveOk, out)
   864  		case
   865  			cc.AdditiveExpressionSub, // AdditiveExpression '-' MultiplicativeExpression
   866  			cc.AdditiveExpressionAdd: // AdditiveExpression '+' MultiplicativeExpression
   867  
   868  			return p.detectArray(f, x.AdditiveExpression, pinnedOk, recursiveOk, out) || p.detectArray(f, x.MultiplicativeExpression, pinnedOk, recursiveOk, out)
   869  		default:
   870  			panic(todo("", p.pos(x), x.Case))
   871  		}
   872  	case *cc.MultiplicativeExpression:
   873  		switch x.Case {
   874  		case cc.MultiplicativeExpressionCast: // CastExpression
   875  			return p.detectArray(f, x.CastExpression, pinnedOk, recursiveOk, out)
   876  		default:
   877  			return false
   878  		}
   879  	case *cc.CastExpression:
   880  		switch x.Case {
   881  		case cc.CastExpressionUnary: // UnaryExpression
   882  			return p.detectArray(f, x.UnaryExpression, pinnedOk, recursiveOk, out)
   883  		case cc.CastExpressionCast: // '(' TypeName ')' CastExpression
   884  			return p.detectArray(f, x.CastExpression, pinnedOk, recursiveOk, out)
   885  		default:
   886  			panic(todo("", p.pos(x), x.Case))
   887  		}
   888  	case *cc.UnaryExpression:
   889  		switch x.Case {
   890  		case cc.UnaryExpressionPostfix: // PostfixExpression
   891  			return p.detectArray(f, x.PostfixExpression, pinnedOk, recursiveOk, out)
   892  		case
   893  			cc.UnaryExpressionDeref,  // '*' CastExpression
   894  			cc.UnaryExpressionAddrof: // '&' CastExpression
   895  
   896  			return p.detectArray(f, x.CastExpression, pinnedOk, recursiveOk, out)
   897  		case
   898  			cc.UnaryExpressionSizeofExpr,  // "sizeof" UnaryExpression
   899  			cc.UnaryExpressionSizeofType,  // "sizeof" '(' TypeName ')'
   900  			cc.UnaryExpressionMinus,       // '-' CastExpression
   901  			cc.UnaryExpressionCpl,         // '~' CastExpression
   902  			cc.UnaryExpressionAlignofExpr, // "_Alignof" UnaryExpression
   903  			cc.UnaryExpressionAlignofType, // "_Alignof" '(' TypeName ')'
   904  			cc.UnaryExpressionNot,         // '!' CastExpression
   905  			cc.UnaryExpressionInc,         // "++" UnaryExpression
   906  			cc.UnaryExpressionDec,         // "--" UnaryExpression
   907  			cc.UnaryExpressionPlus:        // '+' CastExpression
   908  
   909  			return false
   910  		default:
   911  			panic(todo("", p.pos(x), x.Case))
   912  		}
   913  	case *cc.PostfixExpression:
   914  		switch x.Case {
   915  		case cc.PostfixExpressionPrimary: // PrimaryExpression
   916  			return p.detectArray(f, x.PrimaryExpression, pinnedOk, recursiveOk, out)
   917  		case cc.PostfixExpressionIndex: // PostfixExpression '[' Expression ']'
   918  			return recursiveOk && p.detectArray(f, x.PostfixExpression, pinnedOk, recursiveOk, out)
   919  		case
   920  			cc.PostfixExpressionSelect,  // PostfixExpression '.' IDENTIFIER
   921  			cc.PostfixExpressionDec,     // PostfixExpression "--"
   922  			cc.PostfixExpressionInc,     // PostfixExpression "++"
   923  			cc.PostfixExpressionCall,    // PostfixExpression '(' ArgumentExpressionList ')'
   924  			cc.PostfixExpressionComplit, // '(' TypeName ')' '{' InitializerList ',' '}'
   925  			cc.PostfixExpressionPSelect: // PostfixExpression "->" IDENTIFIER
   926  
   927  			return false
   928  		default:
   929  			panic(todo("", p.pos(x), x.Case))
   930  		}
   931  	case *cc.PrimaryExpression:
   932  		switch x.Case {
   933  		case
   934  			cc.PrimaryExpressionString,  // STRINGLITERAL
   935  			cc.PrimaryExpressionEnum,    // ENUMCONST
   936  			cc.PrimaryExpressionChar,    // CHARCONST
   937  			cc.PrimaryExpressionLChar,   // LONGCHARCONST
   938  			cc.PrimaryExpressionLString, // LONGSTRINGLITERAL
   939  			cc.PrimaryExpressionFloat,   // FLOATCONST
   940  			cc.PrimaryExpressionInt:     // INTCONST
   941  
   942  			return false
   943  		case cc.PrimaryExpressionIdent: // IDENTIFIER
   944  			d := x.Declarator()
   945  			if d == nil || d.IsParameter {
   946  				return false
   947  			}
   948  
   949  			if d.Type().Kind() != cc.Array {
   950  				return false
   951  			}
   952  
   953  			if d.Type().IsVLA() {
   954  				return false
   955  			}
   956  
   957  			if pinnedOk {
   958  				if out != nil {
   959  					*out = d
   960  				}
   961  				return true
   962  			}
   963  
   964  			local := f.locals[d]
   965  			if local == nil || local.isPinned {
   966  				return false
   967  			}
   968  
   969  			if out != nil {
   970  				*out = d
   971  			}
   972  			return true
   973  		case cc.PrimaryExpressionExpr: // '(' Expression ')'
   974  			return p.detectArray(f, x.Expression, pinnedOk, recursiveOk, out)
   975  		case cc.PrimaryExpressionStmt: // '(' CompoundStatement ')'
   976  			p.err(x, "statement expressions not supported")
   977  			return false
   978  		default:
   979  			panic(todo("", p.pos(x), x.Case))
   980  		}
   981  	case *cc.Expression:
   982  		switch x.Case {
   983  		case cc.ExpressionAssign: // AssignmentExpression
   984  			return p.detectArray(f, x.AssignmentExpression, pinnedOk, recursiveOk, out)
   985  		case cc.ExpressionComma: // Expression ',' AssignmentExpression
   986  			return p.detectArray(f, x.Expression, pinnedOk, recursiveOk, out) || p.detectArray(f, x.AssignmentExpression, pinnedOk, recursiveOk, out)
   987  		default:
   988  			panic(todo("", p.pos(x), x.Case))
   989  		}
   990  	default:
   991  		panic(todo("%T", x))
   992  	}
   993  }
   994  
   995  func (p *project) isArray(f *function, n declarator, t cc.Type) (r bool) {
   996  	if t.Kind() != cc.Array {
   997  		return false
   998  	}
   999  
  1000  	if t.IsVLA() {
  1001  		return false
  1002  	}
  1003  
  1004  	if f == nil {
  1005  		return true
  1006  	}
  1007  
  1008  	if d := n.Declarator(); d != nil {
  1009  		local := f.locals[d]
  1010  		return !d.IsParameter && (local == nil || !local.isPinned)
  1011  	}
  1012  
  1013  	return p.detectArray(f, n.(cc.Node), false, true, nil)
  1014  }
  1015  
  1016  var home = os.Getenv("HOME")
  1017  
  1018  // Return n's position with path reduced to baseName(path) unless
  1019  // p.task.fullPathComments is true.
  1020  func (p *project) pos(n cc.Node) (r token.Position) {
  1021  	if n == nil {
  1022  		return r
  1023  	}
  1024  
  1025  	if r = token.Position(n.Position()); r.IsValid() {
  1026  		switch {
  1027  		case p.task.fullPathComments:
  1028  			if strings.HasPrefix(r.Filename, home) {
  1029  				r.Filename = "$HOME" + r.Filename[len(home):]
  1030  			}
  1031  		default:
  1032  			r.Filename = filepath.Base(r.Filename)
  1033  		}
  1034  	}
  1035  	return r
  1036  }
  1037  
  1038  // Return n's position with path reduced to baseName(path).
  1039  func pos(n cc.Node) (r token.Position) {
  1040  	if n == nil {
  1041  		return r
  1042  	}
  1043  
  1044  	r = token.Position(n.Position())
  1045  	if r.IsValid() {
  1046  		r.Filename = filepath.Base(r.Filename)
  1047  	}
  1048  	return r
  1049  }
  1050  
  1051  func roundup(n, to uintptr) uintptr {
  1052  	if r := n % to; r != 0 {
  1053  		return n + to - r
  1054  	}
  1055  
  1056  	return n
  1057  }
  1058  
  1059  func (f *function) pin(n cc.Node, d *cc.Declarator) {
  1060  	local := f.locals[d]
  1061  	if local == nil || local.isPinned {
  1062  		return
  1063  	}
  1064  
  1065  	local.isPinned = true
  1066  	if oTracePin || f.project.task.tracePinning {
  1067  		fmt.Printf("%v: %s at %v: is pinned (%v)\n", n.Position(), d.Name(), d.Position(), origin(2))
  1068  	}
  1069  	local.off = roundup(f.off, uintptr(d.Type().Align()))
  1070  	f.off = local.off + paramTypeDecay(d).Size()
  1071  }
  1072  
  1073  func paramTypeDecay(d *cc.Declarator) (r cc.Type) {
  1074  	r = d.Type()
  1075  	if d.IsParameter && r.Kind() == cc.Array {
  1076  		r = r.Decay()
  1077  	}
  1078  	return r
  1079  }
  1080  
  1081  func (f *function) layoutBlocks(n *cc.CompoundStatement) {
  1082  	block := f.blocks[n]
  1083  	type item struct {
  1084  		ds *cc.DeclarationSpecifiers
  1085  		d  *cc.Declarator
  1086  	}
  1087  	var work []item
  1088  	for _, v := range block.params {
  1089  		if v.Type().Kind() == cc.Void {
  1090  			break
  1091  		}
  1092  
  1093  		work = append(work, item{nil, v.Declarator()})
  1094  	}
  1095  	for _, decl := range block.decls {
  1096  		ds := decl.DeclarationSpecifiers
  1097  		for list := decl.InitDeclaratorList; list != nil; list = list.InitDeclaratorList {
  1098  			work = append(work, item{ds, list.InitDeclarator.Declarator})
  1099  		}
  1100  	}
  1101  	block.scope.take(cc.String(f.tlsName))
  1102  	if f.vaName != "" {
  1103  		block.scope.take(cc.String(f.vaName))
  1104  	}
  1105  	for _, item := range work {
  1106  		d := item.d
  1107  		if f.ignore[d] {
  1108  			continue
  1109  		}
  1110  
  1111  		if !f.ignore[d] && d.IsStatic() {
  1112  			continue
  1113  		}
  1114  
  1115  		if d.IsFunctionPrototype() || d.IsExtern() {
  1116  			continue
  1117  		}
  1118  
  1119  		local := &local{forceRead: d.Read == 0}
  1120  		if t := d.Type(); t != nil && t.Name() == idVaList {
  1121  			local.forceRead = true
  1122  		}
  1123  		f.locals[d] = local
  1124  		local.name = block.scope.take(d.Name())
  1125  	}
  1126  }
  1127  
  1128  func (f *function) layoutLocals(parent *block, n *cc.CompoundStatement, params []*cc.Parameter) {
  1129  	block := newBlock(parent, n, n.Declarations(), params, f.project.newScope(), n.IsJumpTarget())
  1130  	f.blocks[n] = block
  1131  	if parent == nil {
  1132  		f.top = block
  1133  		f.top.topDecl = f.hasJumps
  1134  	}
  1135  	for _, ch := range n.Children() {
  1136  		f.layoutLocals(block, ch, nil)
  1137  		if f.hasJumps {
  1138  			chb := f.blocks[ch]
  1139  			chb.noDecl = true
  1140  			f.top.decls = append(f.top.decls, chb.decls...)
  1141  			chb.decls = nil
  1142  		}
  1143  	}
  1144  }
  1145  
  1146  func newDeclarator(name string) *cc.Declarator {
  1147  	return &cc.Declarator{
  1148  		DirectDeclarator: &cc.DirectDeclarator{
  1149  			Case:  cc.DirectDeclaratorIdent,
  1150  			Token: cc.Token{Rune: cc.IDENTIFIER, Value: cc.String(name)},
  1151  		},
  1152  	}
  1153  }
  1154  
  1155  type enumSpec struct {
  1156  	decl *cc.Declaration
  1157  	spec *cc.EnumSpecifier
  1158  
  1159  	emitted bool
  1160  }
  1161  
  1162  func (n *enumSpec) emit(p *project) {
  1163  	if n == nil || p.pass1 || n.emitted {
  1164  		return
  1165  	}
  1166  
  1167  	n.emitted = true
  1168  	ok := false
  1169  	for list := n.spec.EnumeratorList; list != nil; list = list.EnumeratorList {
  1170  		nm := list.Enumerator.Token.Value
  1171  		if _, ok2 := p.emitedEnums[nm]; !ok2 && p.enumConsts[nm] != "" {
  1172  			ok = true
  1173  			break
  1174  		}
  1175  	}
  1176  	if !ok {
  1177  		return
  1178  	}
  1179  
  1180  	p.w("%s", tidyComment("\n", n.decl))
  1181  	p.w("const ( /* %v: */", p.pos(n.decl))
  1182  	for list := n.spec.EnumeratorList; list != nil; list = list.EnumeratorList {
  1183  		en := list.Enumerator
  1184  		nm := en.Token.Value
  1185  		if _, ok := p.emitedEnums[nm]; ok || p.enumConsts[nm] == "" {
  1186  			continue
  1187  		}
  1188  
  1189  		p.emitedEnums[nm] = struct{}{}
  1190  		p.w("%s%s = ", tidyComment("\n", en), p.enumConsts[nm])
  1191  		p.intConst(en, "", en.Operand, en.Operand.Type(), fForceNoConv)
  1192  		p.w(";")
  1193  	}
  1194  	p.w(");")
  1195  }
  1196  
  1197  type typedef struct {
  1198  	sig uint64
  1199  	tld *tld
  1200  }
  1201  
  1202  type define struct {
  1203  	name  string
  1204  	value cc.Value
  1205  }
  1206  
  1207  type project struct {
  1208  	ast                *cc.AST
  1209  	buf                bytes.Buffer
  1210  	capi               []string
  1211  	defines            map[cc.StringID]define
  1212  	defineLines        []string
  1213  	emitedEnums        map[cc.StringID]struct{}
  1214  	enumConsts         map[cc.StringID]string
  1215  	enumSpecs          map[*cc.EnumSpecifier]*enumSpec
  1216  	errors             scanner.ErrorList
  1217  	externs            map[cc.StringID]*tld
  1218  	fn                 string
  1219  	imports            map[string]*imported // C name: import info
  1220  	intType            cc.Type
  1221  	localTaggedStructs []func()
  1222  	mainName           string
  1223  	ptrSize            uintptr
  1224  	ptrType            cc.Type
  1225  	scope              scope
  1226  	sharedFns          map[*cc.FunctionDefinition]struct{}
  1227  	sharedFnsEmitted   map[*cc.FunctionDefinition]struct{}
  1228  	staticQueue        []*cc.InitDeclarator
  1229  	structs            map[cc.StringID]*taggedStruct // key: C tag
  1230  	symtab             map[string]interface{}        // *tld or *imported
  1231  	task               *Task
  1232  	tldScope           scope
  1233  	tlds               map[*cc.Declarator]*tld
  1234  	ts                 bytes.Buffer // Text segment
  1235  	tsName             string
  1236  	tsNameP            string
  1237  	tsOffs             map[cc.StringID]uintptr
  1238  	tsW                []rune // Text segment, wchar_t
  1239  	tsWName            string
  1240  	tsWNameP           string
  1241  	tsWOffs            map[cc.StringID]uintptr
  1242  	typeSigHash        maphash.Hash
  1243  	typedefTypes       map[cc.StringID]*typedef
  1244  	typedefsEmited     map[string]struct{}
  1245  	verifyStructs      map[string]cc.Type
  1246  	wanted             map[*cc.Declarator]struct{}
  1247  	wcharSize          uintptr
  1248  
  1249  	isMain       bool
  1250  	pass1        bool
  1251  	pauseCodegen bool
  1252  }
  1253  
  1254  func newProject(t *Task) (*project, error) {
  1255  	voidType := t.cfg.ABI.Type(cc.Void)
  1256  	ptrType := t.cfg.ABI.Ptr(nil, voidType)
  1257  	intType := t.cfg.ABI.Type(cc.Int)
  1258  	if intType.Size() != 4 { // We're assuming wchar_t is int32.
  1259  		return nil, fmt.Errorf("unsupported C int size: %d", intType.Size())
  1260  	}
  1261  
  1262  	if n := t.cfg.ABI.Types[cc.UChar].Size; n != 1 {
  1263  		return nil, fmt.Errorf("unsupported C unsigned char size: %d", n)
  1264  	}
  1265  
  1266  	if n := t.cfg.ABI.Types[cc.UShort].Size; n != 2 {
  1267  		return nil, fmt.Errorf("unsupported C unsigned short size: %d", n)
  1268  	}
  1269  
  1270  	if n := t.cfg.ABI.Types[cc.UInt].Size; n != 4 {
  1271  		return nil, fmt.Errorf("unsupported C unsigned int size: %d", n)
  1272  	}
  1273  
  1274  	if n := t.cfg.ABI.Types[cc.ULongLong].Size; n != 8 {
  1275  		return nil, fmt.Errorf("unsupported C unsigned long long size: %d", n)
  1276  	}
  1277  
  1278  	p := &project{
  1279  		defines:          map[cc.StringID]define{},
  1280  		emitedEnums:      map[cc.StringID]struct{}{},
  1281  		enumConsts:       map[cc.StringID]string{},
  1282  		enumSpecs:        map[*cc.EnumSpecifier]*enumSpec{},
  1283  		externs:          map[cc.StringID]*tld{},
  1284  		imports:          map[string]*imported{},
  1285  		intType:          intType,
  1286  		ptrSize:          t.cfg.ABI.Types[cc.Ptr].Size,
  1287  		ptrType:          ptrType,
  1288  		scope:            newScope(),
  1289  		sharedFns:        t.cfg.SharedFunctionDefinitions.M,
  1290  		sharedFnsEmitted: map[*cc.FunctionDefinition]struct{}{},
  1291  		symtab:           map[string]interface{}{},
  1292  		task:             t,
  1293  		tlds:             map[*cc.Declarator]*tld{},
  1294  		tsWOffs:          map[cc.StringID]uintptr{},
  1295  		tsOffs:           map[cc.StringID]uintptr{},
  1296  		typedefTypes:     map[cc.StringID]*typedef{},
  1297  		typedefsEmited:   map[string]struct{}{},
  1298  		verifyStructs:    map[string]cc.Type{},
  1299  		wanted:           map[*cc.Declarator]struct{}{},
  1300  		wcharSize:        t.asts[0].WideCharType.Size(),
  1301  	}
  1302  	p.tldScope = p.scope
  1303  	p.scope.take(idCAPI)
  1304  	for _, v := range t.imported {
  1305  		var err error
  1306  		if v.name, v.exports, err = t.capi(v.path); err != nil {
  1307  			return nil, err
  1308  		}
  1309  
  1310  		v.qualifier = p.scope.take(cc.String(v.name)) + "."
  1311  		for k := range v.exports {
  1312  			if p.imports[k] == nil {
  1313  				p.imports[k] = v
  1314  			}
  1315  		}
  1316  	}
  1317  	p.tsNameP = p.scope.take(idTs)
  1318  	p.tsName = p.scope.take(idTs)
  1319  	p.tsWNameP = p.scope.take(idWtext)
  1320  	p.tsWName = p.scope.take(idWtext)
  1321  	if err := p.layout(); err != nil {
  1322  		return nil, err
  1323  	}
  1324  
  1325  	return p, nil
  1326  }
  1327  
  1328  func (p *project) newScope() scope {
  1329  	s := newScope()
  1330  	var a []cc.StringID
  1331  	for k := range p.structs {
  1332  		a = append(a, k)
  1333  	}
  1334  	sort.Slice(a, func(i, j int) bool { return a[i].String() < a[j].String() })
  1335  	for _, k := range a {
  1336  		s.take(cc.String(p.structs[k].name))
  1337  	}
  1338  	return s
  1339  }
  1340  
  1341  func (p *project) err(n cc.Node, s string, args ...interface{}) {
  1342  	if p.task.errTrace || strings.Contains(s, "internal error") {
  1343  		s = s + "(" + origin(2) + ")"
  1344  	}
  1345  	if p.task.traceTranslationUnits {
  1346  		trc("%v: error: %s (%v)", pos(n), fmt.Sprintf(s, args...), origin(2))
  1347  	}
  1348  	if !p.task.allErrors && len(p.errors) >= 10 {
  1349  		return
  1350  	}
  1351  
  1352  	switch {
  1353  	case n == nil:
  1354  		p.errors.Add(token.Position{}, fmt.Sprintf(s, args...))
  1355  	default:
  1356  		p.errors.Add(token.Position(n.Position()), fmt.Sprintf(s, args...))
  1357  		if !p.task.allErrors && len(p.errors) == 10 {
  1358  			p.errors.Add(token.Position(n.Position()), tooManyErrors)
  1359  		}
  1360  	}
  1361  }
  1362  
  1363  func (p *project) o(s string, args ...interface{}) {
  1364  	if oTraceG {
  1365  		fmt.Printf(s, args...)
  1366  	}
  1367  	fmt.Fprintf(p.task.out, s, args...)
  1368  }
  1369  
  1370  func (p *project) w(s string, args ...interface{}) {
  1371  	if p.pass1 || p.pauseCodegen {
  1372  		return
  1373  	}
  1374  
  1375  	if coverExperiment {
  1376  		pc, _, _, ok := runtime.Caller(1)
  1377  		if ok {
  1378  			coverMap[pc] = struct{}{}
  1379  		}
  1380  	}
  1381  	if oTraceW {
  1382  		fmt.Printf(s, args...)
  1383  	}
  1384  	//fmt.Fprintf(&p.buf, "/* %s */", origin(2)) //TODO-
  1385  	fmt.Fprintf(&p.buf, s, args...)
  1386  }
  1387  
  1388  func (p *project) layout() error {
  1389  	if err := p.layoutTLDs(); err != nil {
  1390  		return err
  1391  	}
  1392  
  1393  	if err := p.layoutSymtab(); err != nil {
  1394  		return err
  1395  	}
  1396  
  1397  	if err := p.layoutStructs(); err != nil {
  1398  		return err
  1399  	}
  1400  
  1401  	if err := p.layoutEnums(); err != nil {
  1402  		return err
  1403  	}
  1404  
  1405  	if err := p.layoutDefines(); err != nil {
  1406  		return err
  1407  	}
  1408  
  1409  	return p.layoutStaticLocals()
  1410  }
  1411  
  1412  func (p *project) layoutSymtab() error {
  1413  	var t0 time.Time
  1414  	if p.task.traceTranslationUnits {
  1415  		fmt.Printf("processing symbol table ... ")
  1416  		t0 = time.Now()
  1417  		defer func() { fmt.Println(time.Since(t0)) }()
  1418  	}
  1419  
  1420  	for _, i := range p.task.symSearchOrder {
  1421  		switch {
  1422  		case i < 0:
  1423  			imported := p.task.imported[-i-1]
  1424  			for nm := range imported.exports {
  1425  				if _, ok := p.symtab[nm]; !ok {
  1426  					p.symtab[nm] = imported
  1427  				}
  1428  			}
  1429  		default:
  1430  			ast := p.task.asts[i]
  1431  			for d := range ast.TLD {
  1432  				if d.IsFunctionPrototype() || d.Linkage != cc.External {
  1433  					continue
  1434  				}
  1435  
  1436  				nm := d.Name()
  1437  				name := nm.String()
  1438  				if _, ok := p.symtab[name]; !ok {
  1439  					tld := p.externs[nm]
  1440  					if tld == nil {
  1441  						if d.Type().Kind() != cc.Function && !p.task.header {
  1442  							p.err(d, "back-end: undefined: %s %v %v", d.Name(), d.Type(), d.Type().Kind())
  1443  						}
  1444  						continue
  1445  					}
  1446  
  1447  					p.symtab[name] = tld
  1448  				}
  1449  			}
  1450  		}
  1451  	}
  1452  	return nil
  1453  }
  1454  
  1455  func (p *project) layoutDefines() error {
  1456  	if !p.task.exportDefinesValid {
  1457  		return nil
  1458  	}
  1459  
  1460  	var t0 time.Time
  1461  	if p.task.traceTranslationUnits {
  1462  		fmt.Printf("processing #defines ... ")
  1463  		t0 = time.Now()
  1464  		defer func() { fmt.Println(time.Since(t0)) }()
  1465  	}
  1466  
  1467  	var prefix = p.task.exportDefines
  1468  	taken := map[cc.StringID]struct{}{}
  1469  	for _, ast := range p.task.asts {
  1470  		var a []cc.StringID
  1471  		for nm, m := range ast.Macros {
  1472  			if m.IsFnLike() {
  1473  				continue
  1474  			}
  1475  
  1476  			if strings.HasPrefix(nm.String(), "__") {
  1477  				continue
  1478  			}
  1479  
  1480  			if _, ok := taken[nm]; ok {
  1481  				continue
  1482  			}
  1483  
  1484  			taken[nm] = struct{}{}
  1485  			a = append(a, nm)
  1486  		}
  1487  		sort.Slice(a, func(i, j int) bool { return a[i].String() < a[j].String() })
  1488  		for _, nm := range a {
  1489  			m := ast.Macros[nm]
  1490  			val, src := evalMacro(m, ast)
  1491  			if src == "" {
  1492  				continue
  1493  			}
  1494  
  1495  			name := nm.String()
  1496  			switch {
  1497  			case prefix == "":
  1498  				name = capitalize(name)
  1499  			default:
  1500  				name = prefix + name
  1501  			}
  1502  			name = p.scope.take(cc.String(name))
  1503  			p.defines[nm] = define{name, val}
  1504  			p.defineLines = append(p.defineLines, fmt.Sprintf("%s = %s // %v:", name, src, p.pos(m)))
  1505  		}
  1506  	}
  1507  	return nil
  1508  }
  1509  
  1510  func evalMacro(m *cc.Macro, ast *cc.AST) (cc.Value, string) {
  1511  	toks := m.ReplacementTokens()
  1512  	if len(toks) != 1 {
  1513  		return evalMacro2(m, ast)
  1514  	}
  1515  
  1516  	src := strings.TrimSpace(toks[0].Src.String())
  1517  	if len(src) == 0 {
  1518  		return nil, ""
  1519  	}
  1520  
  1521  	neg := ""
  1522  	switch src[0] {
  1523  	case '"':
  1524  		if _, err := strconv.Unquote(src); err == nil {
  1525  			return cc.StringValue(cc.String(src)), src
  1526  		}
  1527  	case '-':
  1528  		neg = "-"
  1529  		src = src[1:]
  1530  		fallthrough
  1531  	default:
  1532  		src = strings.TrimRight(src, "lLuU")
  1533  		if u64, err := strconv.ParseUint(src, 0, 64); err == nil {
  1534  			switch {
  1535  			case neg == "":
  1536  				return cc.Uint64Value(u64), src
  1537  			default:
  1538  				return cc.Int64Value(-u64), neg + src
  1539  			}
  1540  		}
  1541  
  1542  		src = strings.TrimRight(src, "fF")
  1543  		if f64, err := strconv.ParseFloat(src, 64); err == nil {
  1544  			return cc.Float64Value(f64), neg + src
  1545  		}
  1546  	}
  1547  
  1548  	return evalMacro2(m, ast)
  1549  }
  1550  
  1551  func evalMacro2(m *cc.Macro, ast *cc.AST) (cc.Value, string) {
  1552  	op, err := ast.Eval(m)
  1553  	if err != nil {
  1554  		return nil, ""
  1555  	}
  1556  
  1557  	switch x := op.Value().(type) {
  1558  	case cc.Int64Value:
  1559  		return op.Value(), fmt.Sprintf("%d", int64(x))
  1560  	case cc.Uint64Value:
  1561  		return op.Value(), fmt.Sprintf("%d", uint64(x))
  1562  	default:
  1563  		panic(todo("", pos(m)))
  1564  	}
  1565  }
  1566  
  1567  func (p *project) layoutEnums() error {
  1568  	var t0 time.Time
  1569  	if p.task.traceTranslationUnits {
  1570  		fmt.Printf("processing enum values ... ")
  1571  		t0 = time.Now()
  1572  		defer func() { fmt.Println(time.Since(t0)) }()
  1573  	}
  1574  
  1575  	export := doNotChange
  1576  	if p.task.exportEnumsValid {
  1577  		switch {
  1578  		case p.task.exportEnums != "":
  1579  			export = exportPrefix
  1580  		default:
  1581  			export = exportCapitalize
  1582  		}
  1583  	} else if p.task.defaultUnExport {
  1584  		export = doNotExport
  1585  	}
  1586  
  1587  	var enumList []*cc.EnumSpecifier
  1588  	for _, v := range p.task.asts {
  1589  		for list := v.TranslationUnit; list != nil; list = list.TranslationUnit {
  1590  			decl := list.ExternalDeclaration
  1591  			switch decl.Case {
  1592  			case cc.ExternalDeclarationDecl: // Declaration
  1593  				// ok
  1594  			default:
  1595  				continue
  1596  			}
  1597  
  1598  			cc.Inspect(decl.Declaration.DeclarationSpecifiers, func(n cc.Node, entry bool) bool {
  1599  				if !entry {
  1600  					return true
  1601  				}
  1602  
  1603  				x, ok := n.(*cc.EnumSpecifier)
  1604  				if !ok || x.Case != cc.EnumSpecifierDef {
  1605  					return true
  1606  				}
  1607  
  1608  				if _, ok := p.enumSpecs[x]; !ok {
  1609  					enumList = append(enumList, x)
  1610  					p.enumSpecs[x] = &enumSpec{decl: decl.Declaration, spec: x}
  1611  				}
  1612  				return true
  1613  			})
  1614  		}
  1615  	}
  1616  
  1617  	vals := map[cc.StringID]interface{}{}
  1618  	for _, v := range enumList {
  1619  		for list := v.EnumeratorList; list != nil; list = list.EnumeratorList {
  1620  			en := list.Enumerator
  1621  			nm := en.Token.Value
  1622  			var val int64
  1623  			switch x := en.Operand.Value().(type) {
  1624  			case cc.Int64Value:
  1625  				val = int64(x)
  1626  			case cc.Uint64Value:
  1627  				val = int64(x)
  1628  			default:
  1629  				panic(todo(""))
  1630  			}
  1631  			switch ex, ok := vals[nm]; {
  1632  			case ok:
  1633  				switch {
  1634  				case ex == nil: //
  1635  					continue
  1636  				case ex == val: // same name and same value
  1637  					continue
  1638  				default: // same name, different value
  1639  					vals[nm] = nil
  1640  				}
  1641  			default:
  1642  				vals[nm] = val
  1643  			}
  1644  			p.enumConsts[nm] = ""
  1645  		}
  1646  	}
  1647  	var a []cc.StringID
  1648  	for nm := range p.enumConsts {
  1649  		if val, ok := vals[nm]; ok && val == nil {
  1650  			delete(p.enumConsts, nm)
  1651  			continue
  1652  		}
  1653  
  1654  		a = append(a, nm)
  1655  	}
  1656  	sort.Slice(a, func(i, j int) bool { return a[i].String() < a[j].String() })
  1657  	for _, nm := range a {
  1658  		name := nm.String()
  1659  		switch export {
  1660  		case doNotExport:
  1661  			name = unCapitalize(name)
  1662  		case doNotChange:
  1663  			// nop
  1664  		case exportCapitalize:
  1665  			name = capitalize(name)
  1666  		case exportPrefix:
  1667  			name = p.task.exportEnums + name
  1668  		}
  1669  		name = p.scope.take(cc.String(name))
  1670  		p.enumConsts[nm] = name
  1671  	}
  1672  	return nil
  1673  }
  1674  
  1675  func (p *project) layoutStaticLocals() error {
  1676  	var t0 time.Time
  1677  	if p.task.traceTranslationUnits {
  1678  		fmt.Printf("processing static local declarations ... ")
  1679  		t0 = time.Now()
  1680  		defer func() { fmt.Println(time.Since(t0)) }()
  1681  	}
  1682  	for _, v := range p.task.asts {
  1683  		for list := v.TranslationUnit; list != nil; list = list.TranslationUnit {
  1684  			decl := list.ExternalDeclaration
  1685  			switch decl.Case {
  1686  			case cc.ExternalDeclarationFuncDef: // FunctionDefinition
  1687  				// ok
  1688  			default:
  1689  				continue
  1690  			}
  1691  
  1692  			cc.Inspect(decl.FunctionDefinition.CompoundStatement, func(n cc.Node, entry bool) bool {
  1693  				switch x := n.(type) {
  1694  				case *cc.Declarator:
  1695  					if !entry || !x.IsStatic() || x.Read == 0 || x.IsParameter {
  1696  						break
  1697  					}
  1698  
  1699  					nm := x.Name()
  1700  					if s := p.task.staticLocalsPrefix; s != "" {
  1701  						nm = cc.String(s + nm.String())
  1702  					}
  1703  					p.tlds[x] = &tld{name: p.scope.take(nm)}
  1704  				}
  1705  				return true
  1706  			})
  1707  		}
  1708  	}
  1709  	return nil
  1710  }
  1711  
  1712  func (p *project) layoutStructs() error {
  1713  	var t0 time.Time
  1714  	if p.task.traceTranslationUnits {
  1715  		fmt.Printf("processing struct/union types ... ")
  1716  		t0 = time.Now()
  1717  		defer func() { fmt.Println(time.Since(t0)) }()
  1718  	}
  1719  
  1720  	export := doNotChange
  1721  	if p.task.exportStructsValid {
  1722  		switch {
  1723  		case p.task.exportStructs != "":
  1724  			export = exportPrefix
  1725  		default:
  1726  			export = exportCapitalize
  1727  		}
  1728  	} else if p.task.defaultUnExport {
  1729  		export = doNotExport
  1730  	}
  1731  
  1732  	m := map[cc.StringID]*taggedStruct{}
  1733  	var tags []cc.StringID
  1734  	for _, v := range p.task.asts {
  1735  		cc.Inspect(v.TranslationUnit, func(n cc.Node, entry bool) bool {
  1736  			if entry {
  1737  				switch x := n.(type) {
  1738  				case *cc.Declarator:
  1739  					if nm := x.Name().String(); strings.HasPrefix(nm, "_") {
  1740  						break
  1741  					}
  1742  
  1743  					p.captureStructTags(x, x.Type(), m, &tags)
  1744  				case *cc.Declaration:
  1745  					cc.Inspect(x.DeclarationSpecifiers, func(nn cc.Node, entry bool) bool {
  1746  						switch y := nn.(type) {
  1747  						case *cc.StructOrUnionSpecifier:
  1748  							if tag := y.Token.Value; tag != 0 {
  1749  								p.captureStructTags(y, y.Type(), m, &tags)
  1750  							}
  1751  						}
  1752  						return true
  1753  					})
  1754  				}
  1755  			}
  1756  			return true
  1757  		})
  1758  	}
  1759  	sort.Slice(tags, func(i, j int) bool { return tags[i].String() < tags[j].String() })
  1760  	for _, k := range tags {
  1761  		v := m[k]
  1762  		//TODO rename conflicts
  1763  		if v.conflicts {
  1764  			delete(m, k)
  1765  			continue
  1766  		}
  1767  
  1768  		name := k.String()
  1769  		switch export {
  1770  		case doNotExport:
  1771  			name = unCapitalize(name)
  1772  		case doNotChange:
  1773  			// nop
  1774  		case exportCapitalize:
  1775  			name = capitalize(name)
  1776  		case exportPrefix:
  1777  			name = p.task.exportStructs + name
  1778  		}
  1779  		v.name = p.scope.take(cc.String(name))
  1780  	}
  1781  	for _, k := range tags {
  1782  		v := m[k]
  1783  		if v != nil {
  1784  			v.gotyp = p.structType(nil, v.ctyp)
  1785  		}
  1786  	}
  1787  	p.structs = m
  1788  	return nil
  1789  }
  1790  
  1791  func (p *project) captureStructTags(n cc.Node, t cc.Type, m map[cc.StringID]*taggedStruct, tags *[]cc.StringID) {
  1792  	if t == nil {
  1793  		return
  1794  	}
  1795  
  1796  	t = t.Alias()
  1797  	for t.Kind() == cc.Ptr {
  1798  		t = t.Alias().Elem().Alias()
  1799  	}
  1800  	if t.Kind() == cc.Invalid || t.IsIncomplete() {
  1801  		return
  1802  	}
  1803  
  1804  	switch t.Kind() {
  1805  	case cc.Struct, cc.Union:
  1806  		tag := t.Tag()
  1807  		if tag == 0 {
  1808  			return
  1809  		}
  1810  
  1811  		ex := m[tag]
  1812  		if ex != nil {
  1813  			ts := p.typeSignature(n, t)
  1814  			exs := p.typeSignature(n, ex.ctyp)
  1815  			if ts != exs {
  1816  				ex.conflicts = true
  1817  			}
  1818  			return
  1819  		}
  1820  
  1821  		nf := t.NumField()
  1822  		m[tag] = &taggedStruct{ctyp: t, node: n}
  1823  		for idx := []int{0}; idx[0] < nf; idx[0]++ {
  1824  			p.captureStructTags(n, t.FieldByIndex(idx).Type(), m, tags)
  1825  		}
  1826  		*tags = append(*tags, tag)
  1827  	case cc.Array:
  1828  		p.captureStructTags(n, t.Elem(), m, tags)
  1829  	}
  1830  }
  1831  
  1832  func (p *project) typeSignature(n cc.Node, t cc.Type) (r uint64) {
  1833  	p.typeSigHash.Reset()
  1834  	p.typeSignature2(n, &p.typeSigHash, t)
  1835  	return p.typeSigHash.Sum64()
  1836  }
  1837  
  1838  func (p *project) typeSignature2(n cc.Node, b *maphash.Hash, t cc.Type) {
  1839  	t = t.Alias()
  1840  	if t.IsIntegerType() {
  1841  		if !t.IsSignedType() {
  1842  			b.WriteByte('u')
  1843  		}
  1844  		fmt.Fprintf(b, "int%d", t.Size()*8)
  1845  		return
  1846  	}
  1847  
  1848  	if t.IsArithmeticType() {
  1849  		b.WriteString(t.Kind().String())
  1850  		return
  1851  	}
  1852  
  1853  	structOrUnion := "struct"
  1854  	switch t.Kind() {
  1855  	case cc.Ptr:
  1856  		fmt.Fprintf(b, "*%s", t.Elem())
  1857  	case cc.Array:
  1858  		if t.IsVLA() {
  1859  			// trc("VLA")
  1860  			p.err(n, "variable length arrays not supported: %v", t)
  1861  		}
  1862  
  1863  		fmt.Fprintf(b, "[%d]%s", t.Len(), t.Elem())
  1864  	case cc.Vector:
  1865  		fmt.Fprintf(b, "[%d]%s", t.Len(), t.Elem())
  1866  	case cc.Union:
  1867  		structOrUnion = "union"
  1868  		fallthrough
  1869  	case cc.Struct:
  1870  		b.WriteString(structOrUnion)
  1871  		nf := t.NumField()
  1872  		fmt.Fprintf(b, " %d{", nf)
  1873  		b.WriteByte('{')
  1874  		for idx := []int{0}; idx[0] < nf; idx[0]++ {
  1875  			f := t.FieldByIndex(idx)
  1876  			fmt.Fprintf(b, "%s:%d:%d:%v:%d:%d:",
  1877  				f.Name(), f.BitFieldOffset(), f.BitFieldWidth(), f.IsBitField(), f.Offset(), f.Padding(),
  1878  			)
  1879  			p.typeSignature2(f.Declarator(), b, f.Type())
  1880  			b.WriteByte(';')
  1881  		}
  1882  		b.WriteByte('}')
  1883  	case cc.Void:
  1884  		b.WriteString("void")
  1885  	case cc.Invalid:
  1886  		b.WriteString("invalid") //TODO fix cc/v3
  1887  	default:
  1888  		panic(todo("", p.pos(n), t, t.Kind()))
  1889  	}
  1890  }
  1891  
  1892  func (p *project) structType(n cc.Node, t cc.Type) string {
  1893  	switch t.Kind() {
  1894  	case cc.Struct, cc.Union:
  1895  		tag := t.Tag()
  1896  		if tag != 0 && p.structs != nil {
  1897  			s := p.structs[tag]
  1898  			if s == nil {
  1899  				return p.structLiteral(n, t)
  1900  			}
  1901  
  1902  			if s.gotyp == "" {
  1903  				s.gotyp = p.structLiteral(n, t)
  1904  			}
  1905  			return s.gotyp
  1906  		}
  1907  
  1908  		return p.structLiteral(n, t)
  1909  	default:
  1910  		panic(todo("internal error: %v", t.Kind()))
  1911  	}
  1912  }
  1913  
  1914  func (p *project) padName(n *int) string {
  1915  	if !p.task.exportFieldsValid {
  1916  		return "_"
  1917  	}
  1918  
  1919  	*n++
  1920  	return fmt.Sprintf("%s__ccgo_pad%d", p.task.exportFields, *n)
  1921  }
  1922  
  1923  func (p *project) structLiteral(n cc.Node, t cc.Type) string {
  1924  	var npad int
  1925  	b := bytesBufferPool.Get().(*bytes.Buffer)
  1926  	defer func() { b.Reset(); bytesBufferPool.Put(b) }()
  1927  	switch t.Kind() {
  1928  	case cc.Struct:
  1929  		info := cc.NewStructLayout(t)
  1930  		// trc("%v: %q\n%s", p.pos(n), t.Tag(), info)
  1931  		b.WriteString("struct {")
  1932  		if info.NeedExplicitAlign {
  1933  			fmt.Fprintf(b, "%s [0]uint%d;", p.padName(&npad), 8*p.align(n, t))
  1934  		}
  1935  		var max uintptr
  1936  		for _, off := range info.Offsets {
  1937  			flds := info.OffsetToFields[off]
  1938  			if off < max {
  1939  				var a []string
  1940  				var nmf cc.Field
  1941  				for _, f := range flds {
  1942  					if f.Name() != 0 && nmf == nil {
  1943  						nmf = f
  1944  					}
  1945  					if !f.IsBitField() {
  1946  						panic(todo("internal error %q, off %v max %v\n%s", f.Name(), off, max, info))
  1947  					}
  1948  					a = append(a, fmt.Sprintf("%s %s: %d", f.Type(), f.Name(), f.BitFieldWidth()))
  1949  				}
  1950  				fmt.Fprintf(b, "/* %s */", strings.Join(a, ", "))
  1951  				continue
  1952  			}
  1953  
  1954  			f := flds[0]
  1955  			switch pad := info.PaddingsBefore[f]; {
  1956  			case pad < 0:
  1957  				continue
  1958  			case pad > 0:
  1959  				fmt.Fprintf(b, "%s [%d]byte;", p.padName(&npad), pad)
  1960  			}
  1961  			switch {
  1962  			case f.IsBitField():
  1963  				max += uintptr(f.BitFieldBlockWidth()) >> 3
  1964  				var a []string
  1965  				var nmf cc.Field
  1966  				for _, f := range flds {
  1967  					if f.Name() != 0 && nmf == nil {
  1968  						nmf = f
  1969  					}
  1970  					if !f.IsBitField() {
  1971  						panic(todo("internal error %q\n%s", f.Name(), info))
  1972  					}
  1973  					a = append(a, fmt.Sprintf("%s %s: %d", f.Type(), f.Name(), f.BitFieldWidth()))
  1974  				}
  1975  				if nmf == nil {
  1976  					nmf = f
  1977  				}
  1978  				fmt.Fprintf(b, "%s uint%d /* %s */;", p.bitFieldName(n, nmf), f.BitFieldBlockWidth(), strings.Join(a, ", "))
  1979  			default:
  1980  				ft := f.Type()
  1981  				if ft.Kind() == cc.Array && ft.IsIncomplete() || ft.Size() == 0 {
  1982  					break
  1983  				}
  1984  
  1985  				max += ft.Size()
  1986  				fmt.Fprintf(b, "%s %s;", p.fieldName2(n, f), p.typ(n, ft))
  1987  			}
  1988  		}
  1989  		if info.PaddingAfter != 0 {
  1990  			fmt.Fprintf(b, "%s [%d]byte;", p.padName(&npad), info.PaddingAfter)
  1991  		}
  1992  		b.WriteByte('}')
  1993  	case cc.Union:
  1994  		b.WriteString("struct {")
  1995  		info := cc.NewStructLayout(t)
  1996  		if info.NeedExplicitAlign {
  1997  			fmt.Fprintf(b, "%s [0]uint%d;", p.padName(&npad), 8*p.align(n, t))
  1998  		}
  1999  		al := uintptr(t.Align())
  2000  		sz := t.Size()
  2001  		if al > sz {
  2002  			panic(todo("", p.pos(n)))
  2003  		}
  2004  
  2005  		f := t.FieldByIndex([]int{0})
  2006  		ft := f.Type()
  2007  		al0 := ft.Align()
  2008  		if f.IsBitField() {
  2009  			al0 = f.BitFieldBlockWidth() >> 3
  2010  		}
  2011  		if al != uintptr(al0) {
  2012  			fmt.Fprintf(b, "%s [0]uint%d;", p.padName(&npad), 8*al)
  2013  		}
  2014  		fsz := ft.Size()
  2015  		switch {
  2016  		case f.IsBitField():
  2017  			fmt.Fprintf(b, "%s ", p.fieldName2(n, f))
  2018  			fmt.Fprintf(b, "uint%d;", f.BitFieldBlockWidth())
  2019  			fsz = uintptr(f.BitFieldBlockWidth()) >> 3
  2020  		default:
  2021  			fmt.Fprintf(b, "%s %s;", p.fieldName2(n, f), p.typ(n, ft))
  2022  		}
  2023  		if pad := sz - fsz; pad != 0 {
  2024  			fmt.Fprintf(b, "%s [%d]byte;", p.padName(&npad), pad)
  2025  		}
  2026  		b.WriteByte('}')
  2027  	default:
  2028  		panic(todo("internal error: %v", t.Kind()))
  2029  	}
  2030  	r := b.String()
  2031  	if p.task.verifyStructs {
  2032  		if _, ok := p.verifyStructs[r]; !ok {
  2033  			p.verifyStructs[r] = t
  2034  		}
  2035  	}
  2036  	return r
  2037  }
  2038  
  2039  func (p *project) align(nd cc.Node, t cc.Type) int {
  2040  	switch n := t.Align(); {
  2041  	case n <= 1:
  2042  		return 1
  2043  	case n <= 2:
  2044  		return 2
  2045  	case n <= 4:
  2046  		return 4
  2047  	case n <= 8:
  2048  		return 8
  2049  	default:
  2050  		if !p.task.ignoreUnsupportedAligment {
  2051  			p.err(nd, "unsupported alignment of type %s: %v", t, n)
  2052  		}
  2053  		return 8
  2054  	}
  2055  }
  2056  
  2057  func (p *project) bitFieldName(n cc.Node, f cc.Field) string {
  2058  	if id := f.Name(); id != 0 {
  2059  		return p.fieldName(n, id)
  2060  	}
  2061  
  2062  	return fmt.Sprintf("__%d", f.Offset())
  2063  }
  2064  
  2065  func (p *project) fieldName2(n cc.Node, f cc.Field) string {
  2066  	if f.Name() != 0 {
  2067  		return p.fieldName(n, f.Name())
  2068  	}
  2069  
  2070  	return p.fieldName(n, cc.String(fmt.Sprintf("__%d", f.Offset())))
  2071  }
  2072  
  2073  func (p *project) fieldName(n cc.Node, id cc.StringID) string {
  2074  	if id == 0 {
  2075  		panic(todo("", p.pos(n)))
  2076  	}
  2077  
  2078  	if !p.task.exportFieldsValid {
  2079  		s := id.String()
  2080  		if p.task.defaultUnExport {
  2081  			s = unCapitalize(s)
  2082  		}
  2083  
  2084  		if !reservedNames[s] {
  2085  			return s
  2086  		}
  2087  
  2088  		return "__" + s
  2089  	}
  2090  
  2091  	if s := p.task.exportFields; s != "" {
  2092  		return s + id.String()
  2093  	}
  2094  
  2095  	return capitalize(id.String())
  2096  }
  2097  
  2098  func (p *project) dtyp(d *cc.Declarator) (r string) {
  2099  	t := d.Type()
  2100  	if t.IsIncomplete() {
  2101  		if t.Kind() == cc.Array && d.IsParameter {
  2102  			return "uintptr"
  2103  		}
  2104  
  2105  		panic(todo(""))
  2106  	}
  2107  
  2108  	return p.typ(d, t)
  2109  }
  2110  
  2111  func (p *project) typ(nd cc.Node, t cc.Type) (r string) {
  2112  	if t.IsIncomplete() {
  2113  		panic(todo("", p.pos(nd), t))
  2114  	}
  2115  
  2116  	if t.IsAliasType() && !t.IsScalarType() {
  2117  		if tld := p.tlds[t.AliasDeclarator()]; tld != nil {
  2118  			return tld.name
  2119  		}
  2120  	}
  2121  
  2122  	b := bytesBufferPool.Get().(*bytes.Buffer)
  2123  	defer func() { b.Reset(); bytesBufferPool.Put(b) }()
  2124  	if t.IsIntegerType() {
  2125  		switch t.Kind() {
  2126  		case cc.Int128:
  2127  			fmt.Fprintf(b, "%sInt128", p.task.crt)
  2128  			return b.String()
  2129  		case cc.UInt128:
  2130  			fmt.Fprintf(b, "%sUint128", p.task.crt)
  2131  			return b.String()
  2132  		}
  2133  
  2134  		if !t.IsSignedType() {
  2135  			b.WriteByte('u')
  2136  		}
  2137  		if t.Size() > 8 {
  2138  			p.err(nd, "unsupported C type: %v", t)
  2139  		}
  2140  		fmt.Fprintf(b, "int%d", 8*t.Size())
  2141  		return b.String()
  2142  	}
  2143  
  2144  	switch t.Kind() {
  2145  	case cc.Ptr, cc.Function:
  2146  		return "uintptr"
  2147  	case cc.Double:
  2148  		return "float64"
  2149  	case cc.Float:
  2150  		return "float32"
  2151  	case cc.Array:
  2152  		n := t.Len()
  2153  		switch {
  2154  		case t.IsVLA():
  2155  			fmt.Fprintf(b, "uintptr")
  2156  		default:
  2157  			fmt.Fprintf(b, "[%d]%s", n, p.typ(nd, t.Elem()))
  2158  		}
  2159  		return b.String()
  2160  	case cc.Vector:
  2161  		n := t.Len()
  2162  		fmt.Fprintf(b, "[%d]%s", n, p.typ(nd, t.Elem()))
  2163  		return b.String()
  2164  	case cc.Struct, cc.Union:
  2165  		if tag := t.Tag(); tag != 0 {
  2166  			if s := p.structs[tag]; s != nil {
  2167  				if s.name == "" {
  2168  					panic(todo("internal error %q", tag))
  2169  				}
  2170  
  2171  				return s.name
  2172  			}
  2173  		}
  2174  
  2175  		return p.structType(nd, t)
  2176  	}
  2177  
  2178  	panic(todo("", p.pos(nd), t.Kind(), t))
  2179  }
  2180  
  2181  func isScalarKind(k cc.Kind) bool {
  2182  	switch k {
  2183  	case
  2184  		cc.Char, cc.SChar, cc.UChar,
  2185  		cc.Short, cc.UShort,
  2186  		cc.Int, cc.UInt,
  2187  		cc.Long, cc.ULong,
  2188  		cc.LongLong, cc.ULongLong,
  2189  		cc.Float, cc.Double,
  2190  		cc.Ptr:
  2191  
  2192  		return true
  2193  	}
  2194  
  2195  	return false
  2196  }
  2197  
  2198  func (p *project) layoutTLDs() error {
  2199  	var t0 time.Time
  2200  	if p.task.traceTranslationUnits {
  2201  		fmt.Printf("processing file scope declarations ... ")
  2202  		t0 = time.Now()
  2203  		defer func() { fmt.Println(time.Since(t0)) }()
  2204  	}
  2205  
  2206  	exportExtern, exportTypedef := doNotChange, doNotChange
  2207  	if p.task.exportExternsValid {
  2208  		switch {
  2209  		case p.task.exportExterns != "":
  2210  			exportExtern = exportPrefix
  2211  		default:
  2212  			exportExtern = exportCapitalize
  2213  		}
  2214  	} else if p.task.defaultUnExport {
  2215  		exportExtern = doNotExport
  2216  	}
  2217  
  2218  	if p.task.exportTypedefsValid {
  2219  		switch {
  2220  		case p.task.exportTypedefs != "":
  2221  			exportTypedef = exportPrefix
  2222  		default:
  2223  			exportTypedef = exportCapitalize
  2224  		}
  2225  	} else if p.task.defaultUnExport {
  2226  		exportTypedef = doNotExport
  2227  	}
  2228  
  2229  	var a []*cc.Declarator
  2230  	if p.task.pkgName == "" || p.task.pkgName == "main" {
  2231  	out:
  2232  		for _, ast := range p.task.asts {
  2233  			if a := ast.Scope[idMain]; len(a) != 0 {
  2234  				switch x := a[0].(type) {
  2235  				case *cc.Declarator:
  2236  					if x.Linkage == cc.External {
  2237  						p.isMain = true
  2238  						p.scope.take(idMain)
  2239  						break out
  2240  					}
  2241  				}
  2242  			}
  2243  		}
  2244  	}
  2245  	sharedFns := map[*cc.FunctionDefinition]struct{}{}
  2246  	for _, ast := range p.task.asts {
  2247  		a = a[:0]
  2248  		for d := range ast.TLD {
  2249  			if d.IsFunctionPrototype() {
  2250  				continue
  2251  			}
  2252  
  2253  			// https://gcc.gnu.org/onlinedocs/gcc/Inline.html
  2254  			//
  2255  			// If you specify both inline and extern in the function definition, then the
  2256  			// definition is used only for inlining. In no case is the function compiled on
  2257  			// its own, not even if you refer to its address explicitly. Such an address
  2258  			// becomes an external reference, as if you had only declared the function, and
  2259  			// had not defined it.
  2260  			//
  2261  			// This combination of inline and extern has almost the effect of a macro. The
  2262  			// way to use it is to put a function definition in a header file with these
  2263  			// keywords, and put another copy of the definition (lacking inline and extern)
  2264  			// in a library file. The definition in the header file causes most calls to
  2265  			// the function to be inlined. If any uses of the function remain, they refer
  2266  			// to the single copy in the library.
  2267  			if d.IsExtern() && d.Type().Inline() {
  2268  				continue
  2269  			}
  2270  
  2271  			if fn := d.FunctionDefinition(); fn != nil {
  2272  				if _, ok := p.sharedFns[fn]; ok {
  2273  					if _, ok := sharedFns[fn]; ok {
  2274  						continue
  2275  					}
  2276  
  2277  					sharedFns[fn] = struct{}{}
  2278  				}
  2279  			}
  2280  
  2281  			a = append(a, d)
  2282  			p.wanted[d] = struct{}{}
  2283  		}
  2284  		sort.Slice(a, func(i, j int) bool {
  2285  			return a[i].NameTok().Seq() < a[j].NameTok().Seq()
  2286  		})
  2287  		for _, d := range a {
  2288  			switch d.Type().Kind() {
  2289  			case cc.Struct, cc.Union:
  2290  				p.checkAttributes(d.Type())
  2291  			}
  2292  			nm := d.Name()
  2293  			name := nm.String()
  2294  
  2295  			switch d.Linkage {
  2296  			case cc.External:
  2297  				if ex := p.externs[nm]; ex != nil {
  2298  					if _, ok := p.task.hide[name]; ok {
  2299  						break
  2300  					}
  2301  
  2302  					if d.Type().Kind() != cc.Function {
  2303  						break
  2304  					}
  2305  
  2306  					p.err(d, "redeclared: %s", d.Name())
  2307  					break
  2308  				}
  2309  
  2310  				isMain := p.isMain && nm == idMain
  2311  				switch exportExtern {
  2312  				case doNotExport:
  2313  					name = unCapitalize(name)
  2314  				case doNotChange:
  2315  					// nop
  2316  				case exportCapitalize:
  2317  					name = capitalize(name)
  2318  				case exportPrefix:
  2319  					name = p.task.exportExterns + name
  2320  				}
  2321  				name = p.scope.take(cc.String(name))
  2322  				if isMain {
  2323  					p.mainName = name
  2324  					d.Read++
  2325  				}
  2326  				tld := &tld{name: name}
  2327  				p.externs[nm] = tld
  2328  				for _, v := range ast.Scope[nm] {
  2329  					if d, ok := v.(*cc.Declarator); ok {
  2330  						p.tlds[d] = tld
  2331  					}
  2332  				}
  2333  				if !isMain {
  2334  					p.capi = append(p.capi, d.Name().String())
  2335  				}
  2336  			case cc.Internal:
  2337  				if token.IsExported(name) && !p.isMain && p.task.exportExternsValid {
  2338  					name = "s" + name
  2339  				}
  2340  				tld := &tld{name: p.scope.take(cc.String(name))}
  2341  				for _, v := range ast.Scope[nm] {
  2342  					if d, ok := v.(*cc.Declarator); ok {
  2343  						p.tlds[d] = tld
  2344  					}
  2345  				}
  2346  			case cc.None:
  2347  				if d.IsTypedefName {
  2348  					if d.Type().IsIncomplete() {
  2349  						break
  2350  					}
  2351  
  2352  					if exportTypedef == doNotChange && strings.HasPrefix(name, "__") {
  2353  						break
  2354  					}
  2355  
  2356  					ex, ok := p.typedefTypes[d.Name()]
  2357  					if ok {
  2358  						sig := p.typeSignature(d, d.Type())
  2359  						if ex.sig == sig {
  2360  							tld := ex.tld
  2361  							for _, v := range ast.Scope[nm] {
  2362  								if d, ok := v.(*cc.Declarator); ok {
  2363  									p.tlds[d] = tld
  2364  								}
  2365  							}
  2366  							break
  2367  						}
  2368  					}
  2369  
  2370  					switch exportTypedef {
  2371  					case doNotExport:
  2372  						name = unCapitalize(name)
  2373  					case doNotChange:
  2374  						// nop
  2375  					case exportCapitalize:
  2376  						name = capitalize(name)
  2377  					case exportPrefix:
  2378  						name = p.task.exportTypedefs + name
  2379  					}
  2380  
  2381  					tld := &tld{name: p.scope.take(cc.String(name))}
  2382  					p.typedefTypes[d.Name()] = &typedef{p.typeSignature(d, d.Type()), tld}
  2383  					for _, v := range ast.Scope[nm] {
  2384  						if d, ok := v.(*cc.Declarator); ok {
  2385  							p.tlds[d] = tld
  2386  						}
  2387  					}
  2388  				}
  2389  			default:
  2390  				panic(todo("", p.pos(d), nm, d.Linkage))
  2391  			}
  2392  		}
  2393  	}
  2394  	for _, ast := range p.task.asts {
  2395  		for list := ast.TranslationUnit; list != nil; list = list.TranslationUnit {
  2396  			decl := list.ExternalDeclaration
  2397  			switch decl.Case {
  2398  			case cc.ExternalDeclarationFuncDef: // FunctionDefinition
  2399  				// ok
  2400  			default:
  2401  				continue
  2402  			}
  2403  
  2404  			cc.Inspect(decl.FunctionDefinition.CompoundStatement, func(n cc.Node, entry bool) bool {
  2405  				switch x := n.(type) {
  2406  				case *cc.Declarator:
  2407  					if x.IsFunctionPrototype() {
  2408  						nm := x.Name()
  2409  						if extern := p.externs[nm]; extern != nil {
  2410  							break
  2411  						}
  2412  
  2413  						tld := &tld{name: nm.String()}
  2414  						for _, nd := range ast.Scope[nm] {
  2415  							if d, ok := nd.(*cc.Declarator); ok {
  2416  								p.tlds[d] = tld
  2417  							}
  2418  						}
  2419  					}
  2420  
  2421  				}
  2422  				return true
  2423  			})
  2424  		}
  2425  	}
  2426  	return nil
  2427  }
  2428  
  2429  func (p *project) checkAttributes(t cc.Type) (r bool) {
  2430  	r = true
  2431  	for _, v := range t.Attributes() {
  2432  		cc.Inspect(v, func(n cc.Node, entry bool) bool {
  2433  			if !entry {
  2434  				return true
  2435  			}
  2436  
  2437  			switch x := n.(type) {
  2438  			case *cc.AttributeValue:
  2439  				if x.Token.Value != idAligned {
  2440  					break
  2441  				}
  2442  
  2443  				//TODO switch v := x.ExpressionList.AssignmentExpression.Operand.Value().(type) {
  2444  				//TODO default:
  2445  				//TODO 	panic(todo("%T(%v)", v, v))
  2446  				//TODO }
  2447  			}
  2448  			return true
  2449  		})
  2450  	}
  2451  	switch t.Kind() {
  2452  	case cc.Struct, cc.Union:
  2453  		for i := []int{0}; i[0] < t.NumField(); i[0]++ {
  2454  			f := t.FieldByIndex(i)
  2455  			if !p.checkAttributes(f.Type()) {
  2456  				return false
  2457  			}
  2458  
  2459  			sd := f.Declarator()
  2460  			if sd == nil {
  2461  				continue
  2462  			}
  2463  
  2464  			cc.Inspect(sd.StructDeclaration().SpecifierQualifierList, func(n cc.Node, entry bool) bool {
  2465  				if !entry {
  2466  					return true
  2467  				}
  2468  
  2469  				switch x := n.(type) {
  2470  				case *cc.AttributeValue:
  2471  					if x.Token.Value == idPacked {
  2472  						p.err(sd, "unsupported attribute: packed")
  2473  						r = false
  2474  						return false
  2475  					}
  2476  
  2477  					if x.Token.Value != idAligned {
  2478  						break
  2479  					}
  2480  
  2481  					switch v := x.ExpressionList.AssignmentExpression.Operand.Value().(type) {
  2482  					case cc.Int64Value:
  2483  						if int(v) != t.Align() {
  2484  							p.err(sd, "unsupported attribute: alignment")
  2485  							r = false
  2486  							return false
  2487  						}
  2488  					default:
  2489  						panic(todo("%T(%v)", v, v))
  2490  					}
  2491  				}
  2492  				return true
  2493  			})
  2494  			if !r {
  2495  				return false
  2496  			}
  2497  		}
  2498  	}
  2499  	return r
  2500  }
  2501  
  2502  func unCapitalize(s string) string {
  2503  	if strings.HasPrefix(s, "_") {
  2504  		return s
  2505  	}
  2506  	a := []rune(s)
  2507  	return strings.ToLower(string(a[0])) + string(a[1:])
  2508  }
  2509  
  2510  func capitalize(s string) string {
  2511  	if strings.HasPrefix(s, "_") {
  2512  		s = "X" + s
  2513  	}
  2514  	a := []rune(s)
  2515  	return strings.ToUpper(string(a[0])) + string(a[1:])
  2516  }
  2517  
  2518  func (p *project) main() error {
  2519  	targs := append([]string(nil), p.task.args...)
  2520  	for i, v := range targs {
  2521  		if v == "" {
  2522  			targs[i] = `""`
  2523  		}
  2524  	}
  2525  	p.o(`// Code generated by '%s %s', DO NOT EDIT.
  2526  
  2527  package %s
  2528  
  2529  `,
  2530  		filepath.Base(p.task.args[0]),
  2531  		strings.Join(targs[1:], " "),
  2532  		p.task.pkgName,
  2533  	)
  2534  	if len(p.defineLines) != 0 {
  2535  		p.w("\nconst (")
  2536  		p.w("%s", strings.Join(p.defineLines, "\n"))
  2537  		p.w("\n)\n\n")
  2538  	}
  2539  	var a []*enumSpec
  2540  	for _, es := range p.enumSpecs {
  2541  		if es.spec.LexicalScope().Parent() == nil && !es.emitted {
  2542  			a = append(a, es)
  2543  		}
  2544  	}
  2545  	sort.Slice(a, func(i, j int) bool {
  2546  		return a[i].decl.Position().String() < a[j].decl.Position().String()
  2547  	})
  2548  	for _, es := range a {
  2549  		es.emit(p)
  2550  	}
  2551  	for i, v := range p.task.asts {
  2552  		var t0 time.Time
  2553  		if p.task.traceTranslationUnits {
  2554  			fmt.Printf("Go back end %v/%v: %s ... ", i+1, len(p.task.asts), filepath.Base(p.task.sources[i].Name))
  2555  			t0 = time.Now()
  2556  		}
  2557  		p.oneAST(v)
  2558  		if p.task.traceTranslationUnits {
  2559  			fmt.Println(time.Since(t0))
  2560  		}
  2561  		p.task.asts[i] = nil
  2562  		memGuard(i, p.task.isScripted)
  2563  	}
  2564  	sort.Slice(p.task.imported, func(i, j int) bool { return p.task.imported[i].path < p.task.imported[j].path })
  2565  	p.o(`import (
  2566  	"math"
  2567  	"reflect"
  2568  	"sync/atomic"
  2569  	"unsafe"
  2570  `)
  2571  	if len(p.verifyStructs) != 0 {
  2572  		p.o("\t\"fmt\"\n")
  2573  	}
  2574  	first := true
  2575  	libc := false
  2576  	for _, v := range p.task.imported {
  2577  		if v.used {
  2578  			if v.path == p.task.crtImportPath {
  2579  				libc = true
  2580  			}
  2581  			if first {
  2582  				p.o("\n")
  2583  				first = false
  2584  			}
  2585  			p.o("\t%q\n", v.path)
  2586  		}
  2587  	}
  2588  	if p.task.crtImportPath != "" {
  2589  		if !libc {
  2590  			p.o("\t%q\n", p.task.crtImportPath)
  2591  		}
  2592  		p.o("\t%q\n", p.task.crtImportPath+"/sys/types")
  2593  	}
  2594  	p.o(`)
  2595  
  2596  var _ = math.Pi
  2597  var _ reflect.Kind
  2598  var _ atomic.Value
  2599  var _ unsafe.Pointer
  2600  `)
  2601  	if p.task.crtImportPath != "" {
  2602  		if libc {
  2603  			p.o("var _ *libc.TLS\n")
  2604  		}
  2605  		p.o("var _ types.Size_t\n")
  2606  	}
  2607  	if p.isMain {
  2608  		p.o(`
  2609  func main() { %sStart(%s) }`, p.task.crt, p.mainName)
  2610  	}
  2611  	p.flushStructs()
  2612  	p.initPatches()
  2613  	p.flushTS()
  2614  	if !p.task.noCapi {
  2615  		p.flushCAPI()
  2616  	}
  2617  	p.doVerifyStructs()
  2618  	if err := p.Err(); err != nil {
  2619  		return err
  2620  	}
  2621  
  2622  	if _, err := p.buf.WriteTo(p.task.out); err != nil {
  2623  		return err
  2624  	}
  2625  
  2626  	return p.Err()
  2627  }
  2628  
  2629  func (p *project) doVerifyStructs() {
  2630  	if len(p.verifyStructs) == 0 {
  2631  		return
  2632  	}
  2633  
  2634  	var a []string
  2635  	for k := range p.verifyStructs {
  2636  		a = append(a, k)
  2637  	}
  2638  	sort.Strings(a)
  2639  	p.w("\n\nfunc init() {")
  2640  	n := 0
  2641  	for _, k := range a {
  2642  		t := p.verifyStructs[k]
  2643  		p.w("\nvar v%d %s", n, k)
  2644  		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())
  2645  		nf := t.NumField()
  2646  		for idx := []int{0}; idx[0] < nf; idx[0]++ {
  2647  			f := t.FieldByIndex(idx)
  2648  			if f.IsFlexible() {
  2649  				break
  2650  			}
  2651  
  2652  			if f.IsBitField() || f.Type().Size() == 0 {
  2653  				continue
  2654  			}
  2655  
  2656  			nm := p.fieldName2(f.Declarator(), f)
  2657  			switch {
  2658  			case t.Kind() == cc.Union:
  2659  				if f.Offset() != 0 {
  2660  					panic(todo(""))
  2661  				}
  2662  
  2663  				if idx[0] != 0 {
  2664  					break
  2665  				}
  2666  
  2667  				fallthrough
  2668  			default:
  2669  				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())
  2670  				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())
  2671  			}
  2672  		}
  2673  		n++
  2674  	}
  2675  	p.w("\n}\n")
  2676  }
  2677  
  2678  func (p *project) flushCAPI() {
  2679  	if p.isMain {
  2680  		return
  2681  	}
  2682  
  2683  	b := bytes.NewBuffer(nil)
  2684  	fmt.Fprintf(b, `// Code generated by '%s %s', DO NOT EDIT.
  2685  
  2686  package %s
  2687  
  2688  `,
  2689  		filepath.Base(p.task.args[0]),
  2690  		strings.Join(p.task.args[1:], " "),
  2691  		p.task.pkgName,
  2692  	)
  2693  	fmt.Fprintf(b, "\n\nvar CAPI = map[string]struct{}{")
  2694  	sort.Strings(p.capi)
  2695  	for _, nm := range p.capi {
  2696  		fmt.Fprintf(b, "\n%q: {},", nm)
  2697  	}
  2698  	fmt.Fprintf(b, "\n}\n")
  2699  	if err := ioutil.WriteFile(p.task.capif, b.Bytes(), 0644); err != nil {
  2700  		p.err(nil, "%v", err)
  2701  		return
  2702  	}
  2703  
  2704  	if out, err := exec.Command("gofmt", "-r", "(x) -> x", "-l", "-s", "-w", p.task.capif).CombinedOutput(); err != nil {
  2705  		p.err(nil, "%s: %v", out, err)
  2706  	}
  2707  
  2708  	if out, err := exec.Command("gofmt", "-l", "-s", "-w", p.task.capif).CombinedOutput(); err != nil {
  2709  		p.err(nil, "%s: %v", out, err)
  2710  	}
  2711  }
  2712  
  2713  func (p *project) initPatches() {
  2714  	var tlds []*tld
  2715  	for _, tld := range p.tlds {
  2716  		if len(tld.patches) != 0 {
  2717  			tlds = append(tlds, tld)
  2718  		}
  2719  	}
  2720  	if len(tlds) == 0 {
  2721  		return
  2722  	}
  2723  
  2724  	sort.Slice(tlds, func(i, j int) bool { return tlds[i].name < tlds[j].name })
  2725  	p.w("\n\nfunc init() {")
  2726  	for _, tld := range tlds {
  2727  		for _, patch := range tld.patches {
  2728  			var fld string
  2729  			if patch.fld != nil {
  2730  				fld = fmt.Sprintf("/* .%s */", patch.fld.Name())
  2731  			}
  2732  			init := patch.init
  2733  			expr := init.AssignmentExpression
  2734  			d := expr.Declarator()
  2735  			switch {
  2736  			case d != nil && d.Type().Kind() == cc.Function:
  2737  				p.w("\n*(*")
  2738  				p.functionSignature(d, nil, d.Type(), "")
  2739  				p.w(")(unsafe.Pointer(uintptr(unsafe.Pointer(&%s))+%d%s)) = ", tld.name, init.Offset, fld)
  2740  				p.declarator(init, nil, d, d.Type(), exprFunc, 0)
  2741  			default:
  2742  				p.w("\n*(*%s)(unsafe.Pointer(uintptr(unsafe.Pointer(&%s))+%d%s)) = ", p.typ(init, patch.t), tld.name, init.Offset, fld)
  2743  				p.assignmentExpression(nil, expr, patch.t, exprValue, 0)
  2744  			}
  2745  			p.w("// %s:", p.pos(init))
  2746  		}
  2747  	}
  2748  	p.w("\n}\n")
  2749  }
  2750  
  2751  func (p *project) Err() error {
  2752  	if len(p.errors) == 0 {
  2753  		return nil
  2754  	}
  2755  
  2756  	var lpos token.Position
  2757  	w := 0
  2758  	for _, v := range p.errors {
  2759  		if lpos.Filename != "" {
  2760  			if v.Pos.Filename == lpos.Filename && v.Pos.Line == lpos.Line && !strings.HasPrefix(v.Msg, tooManyErrors) {
  2761  				continue
  2762  			}
  2763  		}
  2764  
  2765  		p.errors[w] = v
  2766  		w++
  2767  		lpos = v.Pos
  2768  	}
  2769  	p.errors = p.errors[:w]
  2770  	sort.Slice(p.errors, func(i, j int) bool {
  2771  		a := p.errors[i]
  2772  		if a.Msg == tooManyErrors {
  2773  			return false
  2774  		}
  2775  
  2776  		b := p.errors[j]
  2777  		if b.Msg == tooManyErrors {
  2778  			return true
  2779  		}
  2780  
  2781  		if !a.Pos.IsValid() && b.Pos.IsValid() {
  2782  			return true
  2783  		}
  2784  
  2785  		if a.Pos.IsValid() && !b.Pos.IsValid() {
  2786  			return false
  2787  		}
  2788  
  2789  		if a.Pos.Filename < b.Pos.Filename {
  2790  			return true
  2791  		}
  2792  
  2793  		if a.Pos.Filename > b.Pos.Filename {
  2794  			return false
  2795  		}
  2796  
  2797  		if a.Pos.Line < b.Pos.Line {
  2798  			return true
  2799  		}
  2800  
  2801  		if a.Pos.Line > b.Pos.Line {
  2802  			return false
  2803  		}
  2804  
  2805  		return a.Pos.Column < b.Pos.Column
  2806  	})
  2807  	a := make([]string, 0, len(p.errors))
  2808  	for _, v := range p.errors {
  2809  		a = append(a, v.Error())
  2810  	}
  2811  	return fmt.Errorf("%s", strings.Join(a, "\n"))
  2812  }
  2813  
  2814  func (p *project) flushTS() {
  2815  	b := p.ts.Bytes()
  2816  	if len(b) != 0 {
  2817  		p.w("\n\n")
  2818  		//TODO add cmd line option for this
  2819  		//TODO s := strings.TrimSpace(hex.Dump(b))
  2820  		//TODO a := strings.Split(s, "\n")
  2821  		//TODO p.w("//  %s\n", strings.Join(a, "\n//  "))
  2822  		p.w("var %s = %q\n", p.tsName, b)
  2823  		p.w("var %s = (*reflect.StringHeader)(unsafe.Pointer(&%s)).Data\n", p.tsNameP, p.tsName)
  2824  	}
  2825  	if len(p.tsW) != 0 {
  2826  		p.w("var %s = [...]%s{", p.tsWName, p.typ(nil, p.ast.WideCharType))
  2827  		for _, v := range p.tsW {
  2828  			p.w("%d, ", v)
  2829  		}
  2830  		p.w("}\n")
  2831  		p.w("var %s = uintptr(unsafe.Pointer(&%s[0]))\n", p.tsWNameP, p.tsWName)
  2832  	}
  2833  }
  2834  
  2835  func (p *project) flushStructs() {
  2836  	var a []*taggedStruct
  2837  	for _, v := range p.structs {
  2838  		if !v.emitted {
  2839  			a = append(a, v)
  2840  		}
  2841  	}
  2842  	sort.Slice(a, func(i, j int) bool { return a[i].name < a[j].name })
  2843  	for _, v := range a {
  2844  		v.emit(p, nil)
  2845  	}
  2846  }
  2847  
  2848  func (p *project) oneAST(ast *cc.AST) {
  2849  	p.ast = ast
  2850  	for list := ast.TranslationUnit; list != nil; list = list.TranslationUnit {
  2851  		p.externalDeclaration(list.ExternalDeclaration)
  2852  	}
  2853  	p.w("%s", tidyCommentString(ast.TrailingSeperator.String()))
  2854  }
  2855  
  2856  func (p *project) externalDeclaration(n *cc.ExternalDeclaration) {
  2857  	switch n.Case {
  2858  	case cc.ExternalDeclarationFuncDef: // FunctionDefinition
  2859  		p.functionDefinition(n.FunctionDefinition)
  2860  	case cc.ExternalDeclarationDecl: // Declaration
  2861  		p.declaration(nil, n.Declaration, false)
  2862  	case cc.ExternalDeclarationAsm: // AsmFunctionDefinition
  2863  		// nop
  2864  	case cc.ExternalDeclarationAsmStmt: // AsmStatement
  2865  		panic(todo("", p.pos(n)))
  2866  	case cc.ExternalDeclarationEmpty: // ';'
  2867  		// nop
  2868  	case cc.ExternalDeclarationPragma: // PragmaSTDC
  2869  		panic(todo("", p.pos(n)))
  2870  	default:
  2871  		panic(todo("%v: internal error: %v", n.Position(), n.Case))
  2872  	}
  2873  }
  2874  
  2875  func (p *project) declaration(f *function, n *cc.Declaration, topDecl bool) {
  2876  	cc.Inspect(n.DeclarationSpecifiers, func(m cc.Node, entry bool) bool {
  2877  		switch x := m.(type) {
  2878  		case *cc.EnumSpecifier:
  2879  			if f == nil {
  2880  				p.enumSpecs[x].emit(p)
  2881  			}
  2882  		case *cc.StructOrUnionSpecifier:
  2883  			if tag := x.Token.Value; tag != 0 {
  2884  				switch {
  2885  				case f == nil:
  2886  					p.structs[tag].emit(p, n.DeclarationSpecifiers)
  2887  				default:
  2888  					p.localTaggedStructs = append(p.localTaggedStructs, func() {
  2889  						p.structs[tag].emit(p, n.DeclarationSpecifiers)
  2890  					})
  2891  				}
  2892  			}
  2893  		}
  2894  		return true
  2895  	})
  2896  
  2897  	if n.InitDeclaratorList == nil {
  2898  		return
  2899  	}
  2900  
  2901  	// DeclarationSpecifiers InitDeclaratorList ';'
  2902  	sep := tidyComment("\n", n) //TODO repeats
  2903  	for list := n.InitDeclaratorList; list != nil; list = list.InitDeclaratorList {
  2904  		p.initDeclarator(f, list.InitDeclarator, sep, topDecl)
  2905  		sep = "\n"
  2906  	}
  2907  }
  2908  
  2909  func (p *project) initDeclarator(f *function, n *cc.InitDeclarator, sep string, topDecl bool) {
  2910  	if f == nil {
  2911  		p.tld(f, n, sep, false)
  2912  		return
  2913  	}
  2914  
  2915  	d := n.Declarator
  2916  	if d.IsExtern() || d.IsTypedefName {
  2917  		return
  2918  	}
  2919  
  2920  	if tld := p.tlds[d]; tld != nil && !topDecl { // static local
  2921  		if !p.pass1 {
  2922  			p.staticQueue = append(p.staticQueue, n)
  2923  		}
  2924  		return
  2925  	}
  2926  
  2927  	local := f.locals[d]
  2928  	if local == nil { // Dead declaration.
  2929  		return
  2930  	}
  2931  
  2932  	block := f.block
  2933  	t := d.Type()
  2934  	vla := t.Kind() == cc.Array && t.IsVLA()
  2935  	if vla && p.pass1 {
  2936  		f.vlas[d] = struct{}{}
  2937  		return
  2938  	}
  2939  
  2940  	switch n.Case {
  2941  	case cc.InitDeclaratorDecl: // Declarator AttributeSpecifierList
  2942  		if block.noDecl || block.topDecl && !topDecl {
  2943  			return
  2944  		}
  2945  
  2946  		switch {
  2947  		case vla:
  2948  			p.initDeclaratorDeclVLA(f, n, sep)
  2949  		default:
  2950  			p.initDeclaratorDecl(f, n, sep)
  2951  		}
  2952  	case cc.InitDeclaratorInit: // Declarator AttributeSpecifierList '=' Initializer
  2953  		if vla {
  2954  			panic(todo(""))
  2955  		}
  2956  
  2957  		if f.block.topDecl {
  2958  			switch {
  2959  			case topDecl:
  2960  				p.initDeclaratorDecl(f, n, sep)
  2961  				if local.forceRead && !local.isPinned {
  2962  					p.w("_ = %s;", local.name)
  2963  				}
  2964  			default:
  2965  				sv := f.condInitPrefix
  2966  				f.condInitPrefix = func() {
  2967  					p.declarator(d, f, d, d.Type(), exprLValue, 0)
  2968  					p.w(" = ")
  2969  				}
  2970  				switch {
  2971  				case p.isConditionalInitializer(n.Initializer):
  2972  					p.assignmentExpression(f, n.Initializer.AssignmentExpression, d.Type(), exprCondInit, 0)
  2973  				default:
  2974  					f.condInitPrefix()
  2975  					p.initializer(f, n.Initializer, d.Type(), d.StorageClass, nil)
  2976  				}
  2977  				f.condInitPrefix = sv
  2978  				p.w(";")
  2979  			}
  2980  			return
  2981  		}
  2982  
  2983  		p.w("%s", sep)
  2984  		switch {
  2985  		case local.isPinned:
  2986  			sv := f.condInitPrefix
  2987  			f.condInitPrefix = func() {
  2988  				//TODO- p.declarator(d, f, d, d.Type(), exprLValue, 0)
  2989  				//TODO- p.w(" = ")
  2990  				p.w("*(*%s)(unsafe.Pointer(%s%s/* %s */)) = ", p.typ(n, d.Type()), f.bpName, nonZeroUintptr(local.off), local.name)
  2991  			}
  2992  			switch {
  2993  			case p.isConditionalInitializer(n.Initializer):
  2994  				p.assignmentExpression(f, n.Initializer.AssignmentExpression, d.Type(), exprCondInit, 0)
  2995  			default:
  2996  				f.condInitPrefix()
  2997  				p.initializer(f, n.Initializer, d.Type(), d.StorageClass, nil)
  2998  				p.w(";")
  2999  			}
  3000  			f.condInitPrefix = sv
  3001  			p.w(";")
  3002  		default:
  3003  			var semi string
  3004  			switch {
  3005  			case block.noDecl:
  3006  				semi = ""
  3007  			default:
  3008  				p.w("var %s ", local.name)
  3009  				if !isAggregateTypeOrUnion(d.Type()) {
  3010  					p.w("%s ", p.typ(n, d.Type()))
  3011  				}
  3012  				semi = ";"
  3013  			}
  3014  			switch {
  3015  			case p.isConditionalInitializer(n.Initializer):
  3016  				p.w("%s", semi)
  3017  				sv := f.condInitPrefix
  3018  				f.condInitPrefix = func() { p.w("%s = ", local.name) }
  3019  				p.assignmentExpression(f, n.Initializer.AssignmentExpression, d.Type(), exprCondInit, 0)
  3020  				f.condInitPrefix = sv
  3021  			default:
  3022  				if block.noDecl {
  3023  					p.w("%s", local.name)
  3024  				}
  3025  				p.w(" = ")
  3026  				p.initializer(f, n.Initializer, d.Type(), d.StorageClass, nil)
  3027  			}
  3028  			p.w(";")
  3029  		}
  3030  	default:
  3031  		panic(todo("%v: internal error: %v", n.Position(), n.Case))
  3032  	}
  3033  	if !block.noDecl && local.forceRead && !local.isPinned {
  3034  		p.w("_ = %s;", local.name)
  3035  	}
  3036  }
  3037  
  3038  func (p *project) isConditionalInitializer(n *cc.Initializer) bool {
  3039  	return n.Case == cc.InitializerExpr && p.isConditionalAssignmentExpr(n.AssignmentExpression)
  3040  }
  3041  
  3042  func (p *project) isConditionalAssignmentExpr(n *cc.AssignmentExpression) bool {
  3043  	return n.Case == cc.AssignmentExpressionCond &&
  3044  		n.ConditionalExpression.Case == cc.ConditionalExpressionCond
  3045  }
  3046  
  3047  func (p *project) initDeclaratorDeclVLA(f *function, n *cc.InitDeclarator, sep string) {
  3048  	d := n.Declarator
  3049  	local := f.locals[d]
  3050  	if strings.TrimSpace(sep) == "" {
  3051  		sep = "\n"
  3052  	}
  3053  	if local.isPinned {
  3054  		panic(todo(""))
  3055  		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())
  3056  		return
  3057  	}
  3058  
  3059  	p.w("%s%s = %sXrealloc(%s, %s, types.Size_t(", sep, local.name, p.task.crt, f.tlsName, local.name)
  3060  	e := d.Type().LenExpr()
  3061  	p.assignmentExpression(f, e, e.Operand.Type(), exprValue, 0)
  3062  	if sz := d.Type().Elem().Size(); sz != 1 {
  3063  		p.w("*%d", sz)
  3064  	}
  3065  	p.w("));")
  3066  }
  3067  
  3068  func (p *project) initDeclaratorDecl(f *function, n *cc.InitDeclarator, sep string) {
  3069  	d := n.Declarator
  3070  	local := f.locals[d]
  3071  	if strings.TrimSpace(sep) == "" {
  3072  		sep = "\n"
  3073  	}
  3074  	if local.isPinned {
  3075  		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())
  3076  		return
  3077  	}
  3078  
  3079  	p.w("%svar %s %s;", sep, local.name, p.typ(n, d.Type()))
  3080  }
  3081  
  3082  func (p *project) declarator(n cc.Node, f *function, d *cc.Declarator, t cc.Type, mode exprMode, flags flags) {
  3083  	switch mode {
  3084  	case exprLValue:
  3085  		p.declaratorLValue(n, f, d, t, mode, flags)
  3086  	case exprFunc:
  3087  		p.declaratorFunc(n, f, d, t, mode, flags)
  3088  	case exprValue:
  3089  		p.declaratorValue(n, f, d, t, mode, flags)
  3090  	case exprAddrOf:
  3091  		p.declaratorAddrOf(n, f, d, t, flags)
  3092  	case exprSelect:
  3093  		p.declaratorSelect(n, f, d)
  3094  	case exprDecay:
  3095  		p.declaratorDecay(n, f, d, t, mode, flags)
  3096  	default:
  3097  		panic(todo("", mode))
  3098  	}
  3099  }
  3100  
  3101  func (p *project) declaratorDecay(n cc.Node, f *function, d *cc.Declarator, t cc.Type, mode exprMode, flags flags) {
  3102  	if d.Type().Kind() != cc.Array {
  3103  		panic(todo("", n.Position(), p.pos(d)))
  3104  	}
  3105  
  3106  	if f != nil {
  3107  		if local := f.locals[d]; local != nil {
  3108  			if d.Type().IsVLA() {
  3109  				switch {
  3110  				case local.isPinned:
  3111  					panic(todo(""))
  3112  				default:
  3113  					p.w("%s", local.name)
  3114  					return
  3115  				}
  3116  			}
  3117  
  3118  			if d.IsParameter {
  3119  				p.w("%s", local.name)
  3120  				return
  3121  			}
  3122  
  3123  			if p.pass1 {
  3124  				if !d.Type().IsVLA() {
  3125  					f.pin(n, d)
  3126  				}
  3127  				return
  3128  			}
  3129  
  3130  			if !local.isPinned {
  3131  				p.err(n, "%v: %v: missed pinning", n.Position(), d.Position(), d.Name())
  3132  			}
  3133  			p.w("(%s%s)/* &%s[0] */", f.bpName, nonZeroUintptr(local.off), local.name)
  3134  			return
  3135  		}
  3136  	}
  3137  
  3138  	if x := p.tlds[d]; x != nil && d.IsStatic() {
  3139  		p.w("uintptr(unsafe.Pointer(&%s))", x.name)
  3140  		return
  3141  	}
  3142  
  3143  	switch x := p.symtab[d.Name().String()].(type) {
  3144  	case *tld:
  3145  		p.w("uintptr(unsafe.Pointer(&%s))", x.name)
  3146  	case *imported:
  3147  		x.used = true
  3148  		p.w("uintptr(unsafe.Pointer(&%sX%s))", x.qualifier, d.Name())
  3149  	default:
  3150  		panic(todo("%v: %v: %q %T", n.Position(), p.pos(d), d.Name(), x))
  3151  	}
  3152  }
  3153  
  3154  func (p *project) declaratorValue(n cc.Node, f *function, d *cc.Declarator, t cc.Type, mode exprMode, flags flags) {
  3155  	switch k := p.declaratorKind(d); k {
  3156  	case opNormal:
  3157  		p.declaratorValueNormal(n, f, d, t, mode, flags)
  3158  	case opArray:
  3159  		p.declaratorValueArray(n, f, d, t, mode, flags)
  3160  	case opFunction:
  3161  		p.declarator(n, f, d, t, exprAddrOf, flags)
  3162  	case opUnion:
  3163  		p.declaratorValueUnion(n, f, d, t, mode, flags)
  3164  	case opArrayParameter:
  3165  		p.declaratorValueArrayParameter(n, f, d, t, mode, flags)
  3166  	default:
  3167  		panic(todo("", d.Position(), k))
  3168  	}
  3169  }
  3170  
  3171  func (p *project) declaratorValueArrayParameter(n cc.Node, f *function, d *cc.Declarator, t cc.Type, mode exprMode, flags flags) {
  3172  	if d.Type().IsScalarType() {
  3173  		defer p.w("%s", p.convertType(n, d.Type(), t, flags))
  3174  	}
  3175  	local := f.locals[d]
  3176  	if local.isPinned {
  3177  		p.w("*(*%s)(unsafe.Pointer(%s%s/* %s */))", p.typ(n, paramTypeDecay(d)), f.bpName, nonZeroUintptr(local.off), local.name)
  3178  		return
  3179  	}
  3180  
  3181  	p.w("%s", local.name)
  3182  }
  3183  
  3184  func (p *project) declaratorValueUnion(n cc.Node, f *function, d *cc.Declarator, t cc.Type, mode exprMode, flags flags) {
  3185  	if d.Type().IsScalarType() {
  3186  		defer p.w("%s", p.convertType(n, d.Type(), t, flags))
  3187  	}
  3188  	if f != nil {
  3189  		if local := f.locals[d]; local != nil {
  3190  			if local.isPinned {
  3191  				p.w("*(*%s)(unsafe.Pointer(%s%s/* %s */))", p.typ(d, d.Type()), f.bpName, nonZeroUintptr(local.off), local.name)
  3192  				return
  3193  			}
  3194  
  3195  			p.w("%s", local.name)
  3196  			return
  3197  		}
  3198  	}
  3199  
  3200  	p.declaratorDefault(n, d)
  3201  }
  3202  
  3203  func (p *project) isVolatileOrAtomic(d *cc.Declarator) bool {
  3204  	if d.Type().IsVolatile() || d.Type().IsAtomic() {
  3205  		return true
  3206  	}
  3207  
  3208  	_, ok := p.task.volatiles[d.Name()]
  3209  	return ok
  3210  }
  3211  
  3212  func (p *project) declaratorDefault(n cc.Node, d *cc.Declarator) {
  3213  	if x := p.tlds[d]; x != nil && d.IsStatic() {
  3214  		if p.isVolatileOrAtomic(d) {
  3215  			p.atomicLoadNamedAddr(n, d.Type(), x.name)
  3216  			return
  3217  		}
  3218  
  3219  		p.w("%s", x.name)
  3220  		return
  3221  	}
  3222  
  3223  	switch x := p.symtab[d.Name().String()].(type) {
  3224  	case *tld:
  3225  		if p.isVolatileOrAtomic(d) {
  3226  			p.atomicLoadNamedAddr(n, d.Type(), x.name)
  3227  			return
  3228  		}
  3229  
  3230  		p.w("%s", x.name)
  3231  	case *imported:
  3232  		x.used = true
  3233  		if p.isVolatileOrAtomic(d) {
  3234  			p.atomicLoadNamedAddr(n, d.Type(), fmt.Sprintf("%sX%s", x.qualifier, d.Name()))
  3235  			return
  3236  		}
  3237  
  3238  		p.w("%sX%s", x.qualifier, d.Name())
  3239  	default:
  3240  		if d.IsExtern() {
  3241  			switch d.Name() {
  3242  			case idEnviron:
  3243  				if d.Type().String() == "pointer to pointer to char" {
  3244  					p.w("%sEnviron()", p.task.crt)
  3245  					return
  3246  				}
  3247  			}
  3248  		}
  3249  
  3250  		if d.Linkage == cc.External && p.task.nostdlib {
  3251  			p.w("X%s", d.Name())
  3252  			return
  3253  		}
  3254  
  3255  		id := fmt.Sprintf("__builtin_%s", d.Name())
  3256  		switch x := p.symtab[id].(type) {
  3257  		case *imported:
  3258  			x.used = true
  3259  			p.w("%sX%s", x.qualifier, d.Name())
  3260  			return
  3261  		}
  3262  
  3263  		if !d.IsImplicit() {
  3264  			nm := d.Name()
  3265  			name := nm.String()
  3266  			switch d.Linkage {
  3267  			case cc.External:
  3268  				name = p.task.exportExterns + name
  3269  				tld := &tld{name: name}
  3270  				p.externs[nm] = tld
  3271  				p.w("%s", name)
  3272  				return
  3273  			case cc.Internal:
  3274  				if token.IsExported(name) {
  3275  					name = "s" + name
  3276  				}
  3277  				tld := &tld{name: p.scope.take(cc.String(name))}
  3278  				for _, v := range p.ast.Scope[nm] {
  3279  					if d, ok := v.(*cc.Declarator); ok {
  3280  						p.tlds[d] = tld
  3281  					}
  3282  				}
  3283  				p.w("%s", name)
  3284  				return
  3285  			}
  3286  		}
  3287  
  3288  		p.err(n, "back-end: undefined: %s", d.Name())
  3289  	}
  3290  }
  3291  
  3292  func (p *project) declaratorValueArray(n cc.Node, f *function, d *cc.Declarator, t cc.Type, mode exprMode, flags flags) {
  3293  	if t.IsIntegerType() {
  3294  		defer p.w("%s", p.convertType(n, nil, t, flags))
  3295  	}
  3296  	if f != nil {
  3297  		if local := f.locals[d]; local != nil {
  3298  			if local.isPinned {
  3299  				p.w("(%s%s)/* %s */", f.bpName, nonZeroUintptr(local.off), local.name)
  3300  				return
  3301  			}
  3302  
  3303  			p.w("%s", local.name)
  3304  			return
  3305  		}
  3306  	}
  3307  
  3308  	p.declaratorDefault(n, d)
  3309  }
  3310  
  3311  func (p *project) declaratorValueNormal(n cc.Node, f *function, d *cc.Declarator, t cc.Type, mode exprMode, flags flags) {
  3312  	if d.Type().IsScalarType() {
  3313  		defer p.w("%s", p.convertType(n, d.Type(), t, flags))
  3314  	}
  3315  	if f != nil {
  3316  		if local := f.locals[d]; local != nil {
  3317  			if local.isPinned {
  3318  				if p.isVolatileOrAtomic(d) && d.IsParameter && d.Write != 0 {
  3319  					p.w("%sAtomicLoadP%s(%s%s/* %s */)", p.task.crt, p.helperType(n, d.Type()), f.bpName, nonZeroUintptr(local.off), local.name)
  3320  					return
  3321  				}
  3322  
  3323  				p.w("*(*%s)(unsafe.Pointer(%s%s/* %s */))", p.typ(d, d.Type()), f.bpName, nonZeroUintptr(local.off), local.name)
  3324  				return
  3325  			}
  3326  
  3327  			if p.isVolatileOrAtomic(d) && d.IsParameter && d.Write != 0 {
  3328  				p.atomicLoadNamedAddr(n, d.Type(), local.name)
  3329  				return
  3330  			}
  3331  
  3332  			p.w("%s", local.name)
  3333  			return
  3334  		}
  3335  	}
  3336  
  3337  	p.declaratorDefault(n, d)
  3338  }
  3339  
  3340  func (p *project) declaratorFunc(n cc.Node, f *function, d *cc.Declarator, t cc.Type, mode exprMode, flags flags) {
  3341  	switch k := p.declaratorKind(d); k {
  3342  	case opFunction:
  3343  		p.declaratorFuncFunc(n, f, d, t, exprValue, flags)
  3344  	case opNormal:
  3345  		p.declaratorFuncNormal(n, f, d, t, exprValue, flags)
  3346  	default:
  3347  		panic(todo("", d.Position(), k))
  3348  	}
  3349  }
  3350  
  3351  func (p *project) declaratorFuncNormal(n cc.Node, f *function, d *cc.Declarator, t cc.Type, mode exprMode, flags flags) {
  3352  	u := d.Type()
  3353  	if u.Kind() == cc.Ptr {
  3354  		u = u.Elem()
  3355  	}
  3356  	switch u.Kind() {
  3357  	case cc.Function:
  3358  		if local := f.locals[d]; local != nil {
  3359  			if local.isPinned {
  3360  				p.w("(*(*")
  3361  				p.functionSignature(n, f, u, "")
  3362  				p.w(")(unsafe.Pointer(%s%s)))", f.bpName, nonZeroUintptr(local.off))
  3363  				return
  3364  			}
  3365  
  3366  			if d.IsParameter {
  3367  				p.w("(*(*")
  3368  				p.functionSignature(n, f, u, "")
  3369  				p.w(")(unsafe.Pointer(&%s)))", local.name)
  3370  				return
  3371  			}
  3372  
  3373  			panic(todo("", p.pos(d)))
  3374  		}
  3375  
  3376  		if x := p.tlds[d]; x != nil && d.IsStatic() {
  3377  			p.w("(*(*")
  3378  			p.functionSignature(n, f, u, "")
  3379  			p.w(")(unsafe.Pointer(&%s)))", x.name)
  3380  			return
  3381  		}
  3382  
  3383  		switch x := p.symtab[d.Name().String()].(type) {
  3384  		case *tld:
  3385  			p.w("(*(*")
  3386  			p.functionSignature(n, f, u, "")
  3387  			p.w(")(unsafe.Pointer(&%s)))", x.name)
  3388  		case *imported:
  3389  			x.used = true
  3390  			p.w("uintptr(unsafe.Pointer(&%sX%s))", x.qualifier, d.Name())
  3391  		default:
  3392  			panic(todo("%v: %v: %q", n.Position(), p.pos(d), d.Name()))
  3393  		}
  3394  	default:
  3395  		panic(todo("", p.pos(d), u))
  3396  	}
  3397  }
  3398  
  3399  func (p *project) declaratorFuncFunc(n cc.Node, f *function, d *cc.Declarator, t cc.Type, mode exprMode, flags flags) {
  3400  	switch d.Type().Kind() {
  3401  	case cc.Function:
  3402  		// ok
  3403  	default:
  3404  		panic(todo("", p.pos(d), d.Type(), d.Type().Kind()))
  3405  	}
  3406  
  3407  	if f != nil {
  3408  		if local := f.locals[d]; local != nil {
  3409  			if local.isPinned {
  3410  				panic(todo(""))
  3411  			}
  3412  
  3413  			p.w(" %s", local.name)
  3414  			return
  3415  		}
  3416  	}
  3417  
  3418  	p.declaratorDefault(n, d)
  3419  }
  3420  
  3421  func (p *project) declaratorLValue(n cc.Node, f *function, d *cc.Declarator, t cc.Type, mode exprMode, flags flags) {
  3422  	switch k := p.declaratorKind(d); k {
  3423  	case opNormal, opArrayParameter, opUnion:
  3424  		p.declaratorLValueNormal(n, f, d, t, mode, flags)
  3425  	case opArray:
  3426  		p.declaratorLValueArray(n, f, d, t, mode, flags)
  3427  	default:
  3428  		panic(todo("", d.Position(), k))
  3429  	}
  3430  }
  3431  
  3432  func (p *project) declaratorLValueArray(n cc.Node, f *function, d *cc.Declarator, t cc.Type, mode exprMode, flags flags) {
  3433  	if f != nil {
  3434  		if local := f.locals[d]; local != nil {
  3435  			if local.isPinned {
  3436  				p.w("*(*%s)(unsafe.Pointer(%s%s/* %s */))", p.typ(d, d.Type()), f.bpName, nonZeroUintptr(local.off), local.name)
  3437  				return
  3438  			}
  3439  
  3440  			p.w("%s", local.name)
  3441  			return
  3442  		}
  3443  	}
  3444  
  3445  	p.declaratorDefault(n, d)
  3446  }
  3447  
  3448  func (p *project) declaratorLValueNormal(n cc.Node, f *function, d *cc.Declarator, t cc.Type, mode exprMode, flags flags) {
  3449  	if p.isVolatileOrAtomic(d) && flags&fVolatileOk == 0 {
  3450  		panic(todo("", n.Position(), d.Position()))
  3451  	}
  3452  
  3453  	if d.Type().IsScalarType() {
  3454  		defer p.w("%s", p.convertType(n, d.Type(), t, flags))
  3455  	}
  3456  	if f != nil {
  3457  		if local := f.locals[d]; local != nil {
  3458  			if local.isPinned {
  3459  				p.w("*(*%s)(unsafe.Pointer(%s%s/* %s */))", p.dtyp(d), f.bpName, nonZeroUintptr(local.off), local.name)
  3460  				return
  3461  			}
  3462  
  3463  			p.w("%s", local.name)
  3464  			return
  3465  		}
  3466  	}
  3467  
  3468  	p.declaratorLValueDefault(n, d)
  3469  }
  3470  
  3471  func (p *project) declaratorLValueDefault(n cc.Node, d *cc.Declarator) {
  3472  	if x := p.tlds[d]; x != nil && d.IsStatic() {
  3473  		p.w("%s", x.name)
  3474  		return
  3475  	}
  3476  
  3477  	switch x := p.symtab[d.Name().String()].(type) {
  3478  	case *tld:
  3479  		p.w("%s", x.name)
  3480  	case *imported:
  3481  		x.used = true
  3482  		p.w("%sX%s", x.qualifier, d.Name())
  3483  	default:
  3484  		if d.IsExtern() {
  3485  			switch d.Name() {
  3486  			case idEnviron:
  3487  				if d.Type().String() == "pointer to pointer to char" {
  3488  					p.w("*(*uintptr)(unsafe.Pointer(%sEnvironP()))", p.task.crt)
  3489  					return
  3490  				}
  3491  			}
  3492  		}
  3493  
  3494  		panic(todo("%v: %v: %q", n.Position(), p.pos(d), d.Name()))
  3495  	}
  3496  }
  3497  
  3498  func (p *project) declaratorKind(d *cc.Declarator) opKind {
  3499  	switch {
  3500  	case p.isArrayParameterDeclarator(d):
  3501  		return opArrayParameter
  3502  	case !p.pass1 && p.isArrayDeclarator(d):
  3503  		return opArray
  3504  	case d.Type().Kind() == cc.Function && !d.IsParameter:
  3505  		return opFunction
  3506  	case d.Type().Kind() == cc.Union:
  3507  		return opUnion
  3508  	default:
  3509  		return opNormal
  3510  	}
  3511  }
  3512  
  3513  func (p *project) declaratorSelect(n cc.Node, f *function, d *cc.Declarator) {
  3514  	switch k := p.declaratorKind(d); k {
  3515  	case opNormal:
  3516  		p.declaratorSelectNormal(n, f, d)
  3517  	case opArray:
  3518  		p.declaratorSelectArray(n, f, d)
  3519  	default:
  3520  		panic(todo("", d.Position(), k))
  3521  	}
  3522  }
  3523  
  3524  func (p *project) declaratorSelectArray(n cc.Node, f *function, d *cc.Declarator) {
  3525  	if local := f.locals[d]; local != nil {
  3526  		if local.isPinned {
  3527  			panic(todo("", p.pos(n)))
  3528  			//TODO type error
  3529  			p.w("(*%s)(unsafe.Pointer(%s%s/* &%s */))", p.typ(d, d.Type()), f.bpName, nonZeroUintptr(local.off), local.name)
  3530  			return
  3531  		}
  3532  
  3533  		p.w("%s", local.name)
  3534  		return
  3535  	}
  3536  
  3537  	p.declaratorDefault(n, d)
  3538  }
  3539  
  3540  func (p *project) declaratorSelectNormal(n cc.Node, f *function, d *cc.Declarator) {
  3541  	if local := f.locals[d]; local != nil {
  3542  		if local.isPinned {
  3543  			p.w("(*%s)(unsafe.Pointer(%s%s/* &%s */))", p.typ(d, d.Type()), f.bpName, nonZeroUintptr(local.off), local.name)
  3544  			return
  3545  		}
  3546  
  3547  		p.w("%s", local.name)
  3548  		return
  3549  	}
  3550  
  3551  	p.declaratorDefault(n, d)
  3552  }
  3553  
  3554  func (p *project) declaratorAddrOf(n cc.Node, f *function, d *cc.Declarator, t cc.Type, flags flags) {
  3555  	switch k := p.declaratorKind(d); k {
  3556  	case opArray:
  3557  		p.declaratorAddrOfArray(n, f, d)
  3558  	case opNormal:
  3559  		p.declaratorAddrOfNormal(n, f, d, flags)
  3560  	case opUnion:
  3561  		p.declaratorAddrOfUnion(n, f, d)
  3562  	case opFunction:
  3563  		p.declaratorAddrOfFunction(n, f, d)
  3564  	case opArrayParameter:
  3565  		p.declaratorAddrOfArrayParameter(n, f, d)
  3566  	default:
  3567  		panic(todo("", d.Position(), k))
  3568  	}
  3569  }
  3570  
  3571  func (p *project) declaratorAddrOfArrayParameter(n cc.Node, f *function, d *cc.Declarator) {
  3572  	if p.pass1 {
  3573  		f.pin(n, d)
  3574  		return
  3575  	}
  3576  
  3577  	local := f.locals[d]
  3578  	p.w("(%s%s)/* &%s */", f.bpName, nonZeroUintptr(local.off), local.name)
  3579  }
  3580  
  3581  func (p *project) declaratorAddrOfFunction(n cc.Node, f *function, d *cc.Declarator) {
  3582  	if d.Type().Kind() != cc.Function {
  3583  		panic(todo("", p.pos(n)))
  3584  	}
  3585  
  3586  	if x := p.tlds[d]; x != nil && d.IsStatic() {
  3587  		p.w("*(*uintptr)(unsafe.Pointer(&struct{f ")
  3588  		p.functionSignature(n, f, d.Type(), "")
  3589  		p.w("}{%s}))", x.name)
  3590  		return
  3591  	}
  3592  
  3593  	switch x := p.symtab[d.Name().String()].(type) {
  3594  	case *tld:
  3595  		p.w("*(*uintptr)(unsafe.Pointer(&struct{f ")
  3596  		p.functionSignature(n, f, d.Type(), "")
  3597  		p.w("}{%s}))", x.name)
  3598  	case *imported:
  3599  		x.used = true
  3600  		p.w("*(*uintptr)(unsafe.Pointer(&struct{f ")
  3601  		p.functionSignature(n, f, d.Type(), "")
  3602  		p.w("}{%sX%s}))", x.qualifier, d.Name())
  3603  	default:
  3604  		p.err(d, "back-end: undefined: %s", d.Name())
  3605  	}
  3606  }
  3607  
  3608  func (p *project) declaratorAddrOfUnion(n cc.Node, f *function, d *cc.Declarator) {
  3609  	if f != nil {
  3610  		if local := f.locals[d]; local != nil {
  3611  			if p.pass1 {
  3612  				f.pin(n, d)
  3613  				return
  3614  			}
  3615  
  3616  			if local.isPinned {
  3617  				p.w("(%s%s)/* &%s */", f.bpName, nonZeroUintptr(local.off), local.name)
  3618  				return
  3619  			}
  3620  
  3621  			panic(todo("", p.pos(n)))
  3622  		}
  3623  	}
  3624  
  3625  	if x := p.tlds[d]; x != nil && d.IsStatic() {
  3626  		p.w("uintptr(unsafe.Pointer(&%s))", x.name)
  3627  		return
  3628  	}
  3629  
  3630  	switch x := p.symtab[d.Name().String()].(type) {
  3631  	case *tld:
  3632  		p.w("uintptr(unsafe.Pointer(&%s))", x.name)
  3633  	case *imported:
  3634  		x.used = true
  3635  		p.w("uintptr(unsafe.Pointer(&%sX%s))", x.qualifier, d.Name())
  3636  	default:
  3637  		panic(todo("%v: %v: %q", n.Position(), p.pos(d), d.Name()))
  3638  	}
  3639  }
  3640  
  3641  func (p *project) declaratorAddrOfNormal(n cc.Node, f *function, d *cc.Declarator, flags flags) {
  3642  	if f != nil {
  3643  		if local := f.locals[d]; local != nil {
  3644  			if p.pass1 && flags&fAddrOfFuncPtrOk == 0 {
  3645  				f.pin(n, d)
  3646  				return
  3647  			}
  3648  
  3649  			if local.isPinned {
  3650  				p.w("(%s%s)/* &%s */", f.bpName, nonZeroUintptr(local.off), local.name)
  3651  				return
  3652  			}
  3653  
  3654  			if flags&fAddrOfFuncPtrOk != 0 {
  3655  				if dt := d.Type(); dt.Kind() == cc.Ptr {
  3656  					if elem := dt.Elem(); elem.Kind() == cc.Function || elem.Kind() == cc.Ptr && elem.Elem().Kind() == cc.Function {
  3657  						p.w("&%s", local.name)
  3658  						return
  3659  					}
  3660  				}
  3661  			}
  3662  
  3663  			panic(todo("", p.pos(n), p.pos(d), d.Name(), d.Type(), d.IsParameter, d.AddressTaken, flags&fAddrOfFuncPtrOk != 0))
  3664  		}
  3665  	}
  3666  
  3667  	if x := p.tlds[d]; x != nil && d.IsStatic() {
  3668  		p.w("uintptr(unsafe.Pointer(&%s))", x.name)
  3669  		return
  3670  	}
  3671  
  3672  	switch x := p.symtab[d.Name().String()].(type) {
  3673  	case *tld:
  3674  		p.w("uintptr(unsafe.Pointer(&%s))", x.name)
  3675  	case *imported:
  3676  		x.used = true
  3677  		p.w("uintptr(unsafe.Pointer(&%sX%s))", x.qualifier, d.Name())
  3678  	default:
  3679  		p.err(n, "undefined: %s", d.Name())
  3680  	}
  3681  }
  3682  
  3683  func (p *project) declaratorAddrOfArray(n cc.Node, f *function, d *cc.Declarator) {
  3684  	if f != nil {
  3685  		if local := f.locals[d]; local != nil {
  3686  			if p.pass1 {
  3687  				f.pin(n, d)
  3688  				return
  3689  			}
  3690  
  3691  			if local.isPinned {
  3692  				p.w("(%s%s)/* &%s */", f.bpName, nonZeroUintptr(local.off), local.name)
  3693  				return
  3694  			}
  3695  
  3696  			panic(todo("", p.pos(d), d.Name(), d.Type(), d.IsParameter))
  3697  		}
  3698  	}
  3699  
  3700  	if x := p.tlds[d]; x != nil && d.IsStatic() {
  3701  		p.w("uintptr(unsafe.Pointer(&%s))", x.name)
  3702  		return
  3703  	}
  3704  
  3705  	switch x := p.symtab[d.Name().String()].(type) {
  3706  	case *tld:
  3707  		p.w("uintptr(unsafe.Pointer(&%s))", x.name)
  3708  	case *imported:
  3709  		x.used = true
  3710  		p.w("uintptr(unsafe.Pointer(&%sX%s))", x.qualifier, d.Name())
  3711  	default:
  3712  		panic(todo("%v: %v: %q", n.Position(), p.pos(d), d.Name()))
  3713  	}
  3714  }
  3715  
  3716  func (p *project) convertType(n cc.Node, from, to cc.Type, flags flags) string {
  3717  	// trc("%v: %v: %v -> %v %v", n.Position(), origin(1), from, to, flags) //TODO- DBG
  3718  	if from != nil {
  3719  		switch from.Kind() {
  3720  		case cc.Int128:
  3721  			return p.convertTypeFromInt128(n, to, flags)
  3722  		case cc.UInt128:
  3723  			return p.convertTypeFromUint128(n, to, flags)
  3724  		}
  3725  	}
  3726  
  3727  	switch to.Kind() {
  3728  	case cc.Int128:
  3729  		return p.convertTypeToInt128(n, from, flags)
  3730  	case cc.UInt128:
  3731  		return p.convertTypeToUint128(n, from, flags)
  3732  	}
  3733  
  3734  	// trc("%v: %v -> %v\n%s", p.pos(n), from, to, debug.Stack()[:600]) //TODO-
  3735  	force := flags&fForceConv != 0
  3736  	if from == nil {
  3737  		p.w("%s(", p.typ(n, to))
  3738  		return ")"
  3739  	}
  3740  
  3741  	if from.IsScalarType() {
  3742  		switch {
  3743  		case force:
  3744  			p.w("%s(", p.helperType2(n, from, to))
  3745  			return ")"
  3746  		case from.Kind() == to.Kind():
  3747  			return ""
  3748  		default:
  3749  			p.w("%s(", p.typ(n, to))
  3750  			return ")"
  3751  		}
  3752  	}
  3753  
  3754  	switch from.Kind() {
  3755  	case cc.Function, cc.Struct, cc.Union, cc.Ptr, cc.Array:
  3756  		if from.Kind() == to.Kind() {
  3757  			return ""
  3758  		}
  3759  
  3760  		panic(todo("", n.Position(), from, to, from.Alias(), to.Alias()))
  3761  	case cc.Double, cc.Float:
  3762  		p.w("%s(", p.typ(n, to))
  3763  		return ")"
  3764  	}
  3765  
  3766  	panic(todo("", n.Position(), from, to, from.Alias(), to.Alias()))
  3767  }
  3768  
  3769  func (p *project) convertTypeFromInt128(n cc.Node, to cc.Type, flags flags) string {
  3770  	switch k := to.Kind(); {
  3771  	case k == cc.Float, k == cc.Double:
  3772  		p.w("(")
  3773  		return fmt.Sprintf(").Float%d()", to.Size()*8)
  3774  	case k == cc.Int128:
  3775  		return ""
  3776  	case k == cc.UInt128:
  3777  		p.w("%sUint128FromInt128(", p.task.crt)
  3778  		return ")"
  3779  	case to.IsIntegerType() && to.IsSignedType():
  3780  		p.w("int%d((", to.Size()*8)
  3781  		return ").Lo)"
  3782  	case to.IsIntegerType() && !to.IsSignedType():
  3783  		p.w("uint%d((", to.Size()*8)
  3784  		return ").Lo)"
  3785  	default:
  3786  		panic(todo("", n.Position(), to, to.Alias()))
  3787  	}
  3788  }
  3789  
  3790  func (p *project) convertTypeFromUint128(n cc.Node, to cc.Type, flags flags) string {
  3791  	switch k := to.Kind(); {
  3792  	case k == cc.Float, k == cc.Double:
  3793  		p.w("(")
  3794  		return fmt.Sprintf(").Float%d()", to.Size()*8)
  3795  	case k == cc.Int128:
  3796  		p.w("(")
  3797  		return ").Int128()"
  3798  	case k == cc.UInt128:
  3799  		return ""
  3800  	case to.IsIntegerType() && to.IsSignedType():
  3801  		p.w("int%d((", to.Size()*8)
  3802  		return ").Lo)"
  3803  	case to.IsIntegerType() && !to.IsSignedType():
  3804  		p.w("uint%d((", to.Size()*8)
  3805  		return ").Lo)"
  3806  	default:
  3807  		panic(todo("", n.Position(), to, to.Alias()))
  3808  	}
  3809  }
  3810  
  3811  func (p *project) convertTypeToInt128(n cc.Node, from cc.Type, flags flags) string {
  3812  	switch k := from.Kind(); {
  3813  	case k == cc.Float, k == cc.Double:
  3814  		p.w("%sInt128FromFloat%d(", p.task.crt, from.Size()*8)
  3815  		return ")"
  3816  	case k == cc.Int128:
  3817  		return ""
  3818  	case k == cc.UInt128:
  3819  		p.w("%sInt128FromUint128(", p.task.crt)
  3820  		return ")"
  3821  	case from.IsIntegerType() && from.IsSignedType():
  3822  		p.w("%sInt128FromInt%d(", p.task.crt, from.Size()*8)
  3823  		return ")"
  3824  	case from.IsIntegerType() && !from.IsSignedType():
  3825  		p.w("%sInt128FromUint%d(", p.task.crt, from.Size()*8)
  3826  		return ")"
  3827  	default:
  3828  		panic(todo("", n.Position(), from, from.Alias()))
  3829  	}
  3830  }
  3831  
  3832  func (p *project) convertTypeToUint128(n cc.Node, from cc.Type, flags flags) string {
  3833  	switch k := from.Kind(); {
  3834  	case k == cc.Float, k == cc.Double:
  3835  		p.w("%sUint128FromFloat%d(", p.task.crt, from.Size()*8)
  3836  		return ")"
  3837  	case k == cc.Int128:
  3838  		p.w("(")
  3839  		return ").Uint128()"
  3840  	case k == cc.UInt128:
  3841  		return ""
  3842  	case from.IsIntegerType() && from.IsSignedType():
  3843  		p.w("%sUint128FromInt%d(", p.task.crt, from.Size()*8)
  3844  		return ")"
  3845  	case from.IsIntegerType() && !from.IsSignedType():
  3846  		p.w("%sUint128FromUint%d(", p.task.crt, from.Size()*8)
  3847  		return ")"
  3848  	default:
  3849  		panic(todo("", n.Position(), from, from.Alias()))
  3850  	}
  3851  }
  3852  
  3853  func (p *project) convertFromInt128(n cc.Node, op cc.Operand, to cc.Type, flags flags) string {
  3854  	switch k := to.Kind(); {
  3855  	case k == cc.Float, k == cc.Double:
  3856  		p.w("(")
  3857  		return fmt.Sprintf(").Float%d()", to.Size()*8)
  3858  	case k == cc.Int128:
  3859  		return ""
  3860  	case k == cc.UInt128:
  3861  		p.w("(")
  3862  		return ").Uint128()"
  3863  	case to.IsIntegerType() && to.IsSignedType():
  3864  		p.w("%sInt%d(", p.task.crt, to.Size()*8)
  3865  		return ")"
  3866  	case to.IsIntegerType() && !to.IsSignedType():
  3867  		p.w("%sUint%d(", p.task.crt, to.Size()*8)
  3868  		return ")"
  3869  	default:
  3870  		panic(todo("", n.Position(), to, to.Alias()))
  3871  	}
  3872  }
  3873  
  3874  func (p *project) convertFromUint128(n cc.Node, op cc.Operand, to cc.Type, flags flags) string {
  3875  	switch k := to.Kind(); {
  3876  	case k == cc.Float, k == cc.Double:
  3877  		p.w("%sUint128FromFloat%d(", p.task.crt, to.Size()*8)
  3878  		return ")"
  3879  	case k == cc.Int128:
  3880  		p.w("(")
  3881  		return ").Int128()"
  3882  	case k == cc.UInt128:
  3883  		return ""
  3884  	case to.IsIntegerType() && to.IsSignedType():
  3885  		p.w("%sInt%d(", p.task.crt, to.Size()*8)
  3886  		return ")"
  3887  	case to.IsIntegerType() && !to.IsSignedType():
  3888  		p.w("%sUint%d(", p.task.crt, to.Size()*8)
  3889  		return ")"
  3890  	default:
  3891  		panic(todo("", n.Position(), to, to.Alias()))
  3892  	}
  3893  }
  3894  
  3895  func (p *project) convertToInt128(n cc.Node, op cc.Operand, to cc.Type, flags flags) string {
  3896  	from := op.Type()
  3897  	switch k := from.Kind(); {
  3898  	case k == cc.Float, k == cc.Double:
  3899  		p.w("%sInt128FromFloat%d(", p.task.crt, from.Size()*8)
  3900  		return ")"
  3901  	case k == cc.Int128:
  3902  		return ""
  3903  	case k == cc.UInt128:
  3904  		p.w("(")
  3905  		return ").Int128()"
  3906  	case from.IsIntegerType() && from.IsSignedType():
  3907  		p.w("%sInt128FromInt%d(", p.task.crt, from.Size()*8)
  3908  		return ")"
  3909  	case from.IsIntegerType() && !from.IsSignedType():
  3910  		p.w("%sInt128FromUint%d(", p.task.crt, from.Size()*8)
  3911  		return ")"
  3912  	default:
  3913  		panic(todo("", n.Position(), from, from.Alias()))
  3914  	}
  3915  }
  3916  
  3917  func (p *project) convertToUint128(n cc.Node, op cc.Operand, to cc.Type, flags flags) string {
  3918  	from := op.Type()
  3919  	switch k := from.Kind(); {
  3920  	case k == cc.Float, k == cc.Double:
  3921  		p.w("%sUint128FromFloat%d(", p.task.crt, from.Size()*8)
  3922  		return ")"
  3923  	case k == cc.Int128:
  3924  		p.w("(")
  3925  		return ").Uint128()"
  3926  	case k == cc.UInt128:
  3927  		return ""
  3928  	case from.IsIntegerType() && from.IsSignedType():
  3929  		p.w("%sUint128FromInt%d(", p.task.crt, from.Size()*8)
  3930  		return ")"
  3931  	case from.IsIntegerType() && !from.IsSignedType():
  3932  		p.w("%sUint128FromUint%d(", p.task.crt, from.Size()*8)
  3933  		return ")"
  3934  	default:
  3935  		panic(todo("", n.Position(), from, from.Alias()))
  3936  	}
  3937  }
  3938  
  3939  func (p *project) convertNil(n cc.Node, to cc.Type, flags flags) string {
  3940  	switch to.Kind() {
  3941  	case cc.Int128:
  3942  		panic(todo("", p.pos(n)))
  3943  	case cc.UInt128:
  3944  		panic(todo("", p.pos(n)))
  3945  	}
  3946  
  3947  	p.w("%s(", p.typ(n, to))
  3948  	return ")"
  3949  }
  3950  
  3951  func (p *project) convert(n cc.Node, op cc.Operand, to cc.Type, flags flags) string {
  3952  	if op == nil {
  3953  		panic(todo("internal error"))
  3954  	}
  3955  
  3956  	from := op.Type()
  3957  	switch from.Kind() {
  3958  	case cc.Int128:
  3959  		return p.convertFromInt128(n, op, to, flags)
  3960  	case cc.UInt128:
  3961  		return p.convertFromUint128(n, op, to, flags)
  3962  	}
  3963  	switch to.Kind() {
  3964  	case cc.Int128:
  3965  		return p.convertToInt128(n, op, to, flags)
  3966  	case cc.UInt128:
  3967  		return p.convertToUint128(n, op, to, flags)
  3968  	}
  3969  
  3970  	if flags&fForceRuntimeConv != 0 {
  3971  		flags |= fForceConv
  3972  	}
  3973  	force := flags&fForceConv != 0
  3974  	if !force && from.IsScalarType() && from.Kind() == to.Kind() {
  3975  		return ""
  3976  	}
  3977  
  3978  	if from.IsIntegerType() {
  3979  		return p.convertInt(n, op, to, flags)
  3980  	}
  3981  
  3982  	if from == to {
  3983  		return ""
  3984  	}
  3985  
  3986  	switch from.Kind() {
  3987  	case cc.Ptr:
  3988  		if !force && from.Kind() == to.Kind() {
  3989  			return ""
  3990  		}
  3991  
  3992  		if to.IsIntegerType() {
  3993  			p.w("%s(", p.typ(n, to))
  3994  			return ")"
  3995  		}
  3996  
  3997  		if to.Kind() == cc.Ptr {
  3998  			return ""
  3999  		}
  4000  
  4001  		panic(todo("%v: force %v, %q %v -> %q %v", p.pos(n), force, from, from.Kind(), to, to.Kind()))
  4002  	case cc.Function, cc.Struct, cc.Union:
  4003  		if !force && from.Kind() == to.Kind() {
  4004  			return ""
  4005  		}
  4006  
  4007  		trc("%p %p", from, to)
  4008  		panic(todo("%q %v -> %q %v", from, from.Kind(), to, to.Kind()))
  4009  	case cc.Double, cc.Float:
  4010  		switch {
  4011  		case to.IsIntegerType():
  4012  			p.w("%s(", p.helperType2(n, from, to))
  4013  			return ")"
  4014  		default:
  4015  			p.w("%s(", p.typ(n, to))
  4016  			return ")"
  4017  		}
  4018  	case cc.Array:
  4019  		if from.Kind() == to.Kind() {
  4020  			return ""
  4021  		}
  4022  
  4023  		switch to.Kind() {
  4024  		case cc.Ptr:
  4025  			return ""
  4026  		}
  4027  
  4028  		panic(todo("%q, %v -> %q, %v", from, from.Kind(), to.Kind()))
  4029  	}
  4030  
  4031  	panic(todo("%q -> %q", from, to))
  4032  }
  4033  
  4034  func (p *project) convertInt(n cc.Node, op cc.Operand, to cc.Type, flags flags) string {
  4035  	from := op.Type()
  4036  	switch from.Kind() {
  4037  	case cc.Int128:
  4038  		panic(todo("", p.pos(n)))
  4039  	case cc.UInt128:
  4040  		panic(todo("", p.pos(n)))
  4041  	}
  4042  	switch to.Kind() {
  4043  	case cc.Int128:
  4044  		panic(todo("", p.pos(n)))
  4045  	case cc.UInt128:
  4046  		panic(todo("", p.pos(n)))
  4047  	}
  4048  
  4049  	force := flags&fForceConv != 0
  4050  	value := op.Value()
  4051  	if value == nil || !to.IsIntegerType() {
  4052  		if to.IsScalarType() {
  4053  			p.w("%s(", p.typ(n, to))
  4054  			return ")"
  4055  		}
  4056  
  4057  		panic(todo("", op.Type(), to))
  4058  	}
  4059  
  4060  	if flags&fForceRuntimeConv != 0 {
  4061  		p.w("%s(", p.helperType2(n, op.Type(), to))
  4062  		return ")"
  4063  	}
  4064  
  4065  	switch {
  4066  	case from.IsSignedType():
  4067  		switch {
  4068  		case to.IsSignedType():
  4069  			switch x := value.(type) {
  4070  			case cc.Int64Value:
  4071  				switch to.Size() {
  4072  				case 1:
  4073  					if x >= math.MinInt8 && x <= math.MaxInt8 {
  4074  						switch {
  4075  						case !force && from.Size() == to.Size():
  4076  							return ""
  4077  						default:
  4078  							p.w("int8(")
  4079  							return ")"
  4080  						}
  4081  					}
  4082  
  4083  					p.w("%sInt8FromInt%d(", p.task.crt, from.Size()*8)
  4084  					return ")"
  4085  				case 2:
  4086  					if x >= math.MinInt16 && x <= math.MaxInt16 {
  4087  						switch {
  4088  						case !force && from.Size() == to.Size():
  4089  							return ""
  4090  						default:
  4091  							p.w("int16(")
  4092  							return ")"
  4093  						}
  4094  					}
  4095  
  4096  					p.w("%sInt16FromInt%d(", p.task.crt, from.Size()*8)
  4097  					return ")"
  4098  				case 4:
  4099  					if x >= math.MinInt32 && x <= math.MaxInt32 {
  4100  						switch {
  4101  						case !force && from.Size() == to.Size():
  4102  							return ""
  4103  						default:
  4104  							p.w("int32(")
  4105  							return ")"
  4106  						}
  4107  					}
  4108  
  4109  					p.w("%sInt32FromInt%d(", p.task.crt, from.Size()*8)
  4110  					return ")"
  4111  				case 8:
  4112  					switch {
  4113  					case !force && from.Size() == to.Size():
  4114  						return ""
  4115  					default:
  4116  						p.w("int64(")
  4117  						return ")"
  4118  					}
  4119  				default:
  4120  					panic(todo("%T(%v) %v -> %v", x, op.Value(), from, to))
  4121  				}
  4122  			default:
  4123  				panic(todo("%T(%v) %v -> %v", x, op.Value(), from, to))
  4124  			}
  4125  		default: // to is unsigned
  4126  			switch x := value.(type) {
  4127  			case cc.Int64Value:
  4128  				switch to.Size() {
  4129  				case 1:
  4130  					if x >= 0 && x <= math.MaxUint8 {
  4131  						p.w("%s(", p.typ(n, to))
  4132  						return ")"
  4133  					}
  4134  
  4135  					p.w("%sUint8FromInt%d(", p.task.crt, from.Size()*8)
  4136  					return ")"
  4137  				case 2:
  4138  					if x >= 0 && x <= math.MaxUint16 {
  4139  						p.w("%s(", p.typ(n, to))
  4140  						return ")"
  4141  					}
  4142  
  4143  					p.w("%sUint16FromInt%d(", p.task.crt, from.Size()*8)
  4144  					return ")"
  4145  				case 4:
  4146  					if x >= 0 && x <= math.MaxUint32 {
  4147  						p.w("%s(", p.typ(n, to))
  4148  						return ")"
  4149  					}
  4150  
  4151  					p.w("%sUint32FromInt%d(", p.task.crt, from.Size()*8)
  4152  					return ")"
  4153  				case 8:
  4154  					if x >= 0 {
  4155  						p.w("uint64(")
  4156  						return ")"
  4157  					}
  4158  
  4159  					p.w("%sUint64FromInt%d(", p.task.crt, from.Size()*8)
  4160  					return ")"
  4161  				default:
  4162  					panic(todo("%T(%v) %v -> %v", x, op.Value(), from, to))
  4163  				}
  4164  			case cc.Uint64Value:
  4165  				switch to.Size() {
  4166  				case 1:
  4167  					if x <= math.MaxUint8 {
  4168  						p.w("%s(", p.typ(n, to))
  4169  						return ")"
  4170  					}
  4171  
  4172  					p.w("%sUint8FromUint%d(", p.task.crt, from.Size()*8)
  4173  					return ")"
  4174  				case 2:
  4175  					if x <= math.MaxUint16 {
  4176  						p.w("%s(", p.typ(n, to))
  4177  						return ")"
  4178  					}
  4179  
  4180  					p.w("%sUint16FromUint%d(", p.task.crt, from.Size()*8)
  4181  					return ")"
  4182  				case 4:
  4183  					if x <= math.MaxUint32 {
  4184  						p.w("%s(", p.typ(n, to))
  4185  						return ")"
  4186  					}
  4187  
  4188  					p.w("%sUint32FromUint%d(", p.task.crt, from.Size()*8)
  4189  					return ")"
  4190  				case 8:
  4191  					p.w("uint64(")
  4192  					return ")"
  4193  				default:
  4194  					panic(todo("%T(%v) %v -> %v", x, op.Value(), from, to))
  4195  				}
  4196  			default:
  4197  				panic(todo("%T(%v) %v -> %v", x, op.Value(), from, to))
  4198  			}
  4199  		}
  4200  	default: // from is unsigned
  4201  		switch {
  4202  		case to.IsSignedType():
  4203  			switch x := value.(type) {
  4204  			case cc.Uint64Value:
  4205  				switch to.Size() {
  4206  				case 1:
  4207  					if x <= math.MaxInt8 {
  4208  						p.w("int8(")
  4209  						return ")"
  4210  					}
  4211  
  4212  					p.w("%sInt8FromUint%d(", p.task.crt, from.Size()*8)
  4213  					return ")"
  4214  				case 2:
  4215  					if x <= math.MaxInt16 {
  4216  						p.w("int16(")
  4217  						return ")"
  4218  					}
  4219  
  4220  					p.w("%sInt16FromUint%d(", p.task.crt, from.Size()*8)
  4221  					return ")"
  4222  				case 4:
  4223  					if x <= math.MaxInt32 {
  4224  						p.w("int32(")
  4225  						return ")"
  4226  					}
  4227  
  4228  					p.w("%sInt32FromUint%d(", p.task.crt, from.Size()*8)
  4229  					return ")"
  4230  				case 8:
  4231  					if x <= math.MaxInt64 {
  4232  						p.w("int64(")
  4233  						return ")"
  4234  					}
  4235  
  4236  					p.w("%sInt64FromUint%d(", p.task.crt, from.Size()*8)
  4237  					return ")"
  4238  				default:
  4239  					panic(todo("%T(%v) %v -> %v", x, op.Value(), from, to))
  4240  				}
  4241  			default:
  4242  				panic(todo("%T(%v) %v -> %v", x, op.Value(), from, to))
  4243  			}
  4244  		default: // to is unsigned
  4245  			switch x := value.(type) {
  4246  			case cc.Uint64Value:
  4247  				switch to.Size() {
  4248  				case 1:
  4249  					if x <= math.MaxUint8 {
  4250  						switch {
  4251  						case !force && from.Size() == 1:
  4252  							return ""
  4253  						default:
  4254  							p.w("uint8(")
  4255  							return ")"
  4256  						}
  4257  					}
  4258  
  4259  					p.w("%sUint8FromUint%d(", p.task.crt, from.Size()*8)
  4260  					return ")"
  4261  				case 2:
  4262  					if x <= math.MaxUint16 {
  4263  						switch {
  4264  						case !force && from.Size() == 2:
  4265  							return ""
  4266  						default:
  4267  							p.w("uint16(")
  4268  							return ")"
  4269  						}
  4270  					}
  4271  
  4272  					p.w("%sUint16FromUint%d(", p.task.crt, from.Size()*8)
  4273  					return ")"
  4274  				case 4:
  4275  					if x <= math.MaxUint32 {
  4276  						switch {
  4277  						case !force && from.Size() == 4:
  4278  							return ""
  4279  						default:
  4280  							p.w("uint32(")
  4281  							return ")"
  4282  						}
  4283  					}
  4284  
  4285  					p.w("%sUint32FromUint%d(", p.task.crt, from.Size()*8)
  4286  					return ")"
  4287  				case 8:
  4288  					switch {
  4289  					case !force && from.Size() == 8:
  4290  						return ""
  4291  					default:
  4292  						p.w("uint64(")
  4293  						return ")"
  4294  					}
  4295  				default:
  4296  					panic(todo("%T(%v) %v -> %v", x, op.Value(), from, to))
  4297  				}
  4298  			default:
  4299  				panic(todo("%T(%v) %v -> %v", x, op.Value(), from, to))
  4300  			}
  4301  		}
  4302  	}
  4303  }
  4304  
  4305  func nonZeroUintptr(n uintptr) string {
  4306  	if n == 0 {
  4307  		return ""
  4308  	}
  4309  
  4310  	return fmt.Sprintf("%+d", n)
  4311  }
  4312  
  4313  func alias(attr []*cc.AttributeSpecifier) (r cc.StringID) {
  4314  	for _, v := range attr {
  4315  		cc.Inspect(v, func(n cc.Node, entry bool) bool {
  4316  			if !entry {
  4317  				return true
  4318  			}
  4319  
  4320  			if x, ok := n.(*cc.AttributeValue); ok && x.Token.Value == idAlias {
  4321  				switch y := x.ExpressionList.AssignmentExpression.Operand.Value().(type) {
  4322  				case cc.StringValue:
  4323  					r = cc.StringID(y)
  4324  					return false
  4325  				}
  4326  			}
  4327  			return true
  4328  		})
  4329  		if r != 0 {
  4330  			return r
  4331  		}
  4332  	}
  4333  	return 0
  4334  }
  4335  
  4336  func (p *project) tld(f *function, n *cc.InitDeclarator, sep string, staticLocal bool) {
  4337  	d := n.Declarator
  4338  	if d.IsExtern() && d.Linkage == cc.External && !d.IsTypedefName {
  4339  		if alias := alias(attrs(d.Type())); alias != 0 {
  4340  			p.capi = append(p.capi, d.Name().String())
  4341  			p.w("\n\nvar %s%s = %s\t// %v:\n", p.task.exportExterns, d.Name(), p.externs[alias].name, p.pos(d))
  4342  			return
  4343  		}
  4344  	}
  4345  
  4346  	if _, ok := p.wanted[d]; !ok && !staticLocal {
  4347  		isFn := d.Type().Kind() == cc.Function
  4348  		if isFn && p.task.header && p.task.funcSig {
  4349  			if nm := d.Name().String(); !strings.HasPrefix(nm, "__") {
  4350  				p.w("\n\n")
  4351  				t := p.tlds[d]
  4352  				if t == nil {
  4353  					t = &tld{}
  4354  					t.name = p.tldScope.take(d.Name())
  4355  				}
  4356  				p.functionSignature2(n, nil, d.Type(), t.name)
  4357  			}
  4358  		}
  4359  		return
  4360  	}
  4361  
  4362  	tld := p.tlds[d]
  4363  	if tld == nil { // Dead declaration.
  4364  		return
  4365  	}
  4366  
  4367  	t := d.Type()
  4368  	if d.IsTypedefName {
  4369  		p.checkAttributes(t)
  4370  		if _, ok := p.typedefsEmited[tld.name]; ok {
  4371  			return
  4372  		}
  4373  
  4374  		p.typedefsEmited[tld.name] = struct{}{}
  4375  		if t.Kind() != cc.Void {
  4376  			p.w("%stype %s = %s; /* %v */", sep, tld.name, p.typ(n, t), p.pos(d))
  4377  		}
  4378  		return
  4379  	}
  4380  
  4381  	switch n.Case {
  4382  	case cc.InitDeclaratorDecl: // Declarator AttributeSpecifierList
  4383  		p.w("%svar %s %s\t/* %v: */", sep, tld.name, p.typ(n, t), p.pos(n))
  4384  		switch t.Kind() {
  4385  		case cc.Struct, cc.Union:
  4386  			p.structs[t.Tag()].emit(p, nil)
  4387  		}
  4388  	case cc.InitDeclaratorInit: // Declarator AttributeSpecifierList '=' Initializer
  4389  		if d.IsStatic() && d.Read == 0 && d.Write == 1 && n.Initializer.IsConst() { // Initialized with no side effects and unused.
  4390  			break
  4391  		}
  4392  
  4393  		p.w("%svar %s ", sep, tld.name)
  4394  		if !isAggregateTypeOrUnion(d.Type()) {
  4395  			p.w("%s ", p.typ(n, d.Type()))
  4396  		}
  4397  		p.w("= ")
  4398  		p.initializer(f, n.Initializer, d.Type(), d.StorageClass, tld)
  4399  		p.w("; /* %v */", p.pos(d))
  4400  	default:
  4401  		panic(todo("%v: internal error: %v", n.Position(), n.Case))
  4402  	}
  4403  }
  4404  
  4405  func (p *project) functionDefinition(n *cc.FunctionDefinition) {
  4406  	// DeclarationSpecifiers Declarator DeclarationList CompoundStatement
  4407  	if p.task.header && !p.task.funcSig {
  4408  		return
  4409  	}
  4410  
  4411  	if _, ok := p.sharedFns[n]; ok {
  4412  		if _, ok := p.sharedFnsEmitted[n]; ok {
  4413  			return
  4414  		}
  4415  
  4416  		p.sharedFnsEmitted[n] = struct{}{}
  4417  	}
  4418  
  4419  	d := n.Declarator
  4420  	if d.IsExtern() && d.Type().Inline() {
  4421  		// https://gcc.gnu.org/onlinedocs/gcc/Inline.html
  4422  		//
  4423  		// If you specify both inline and extern in the function definition, then the
  4424  		// definition is used only for inlining. In no case is the function compiled on
  4425  		// its own, not even if you refer to its address explicitly. Such an address
  4426  		// becomes an external reference, as if you had only declared the function, and
  4427  		// had not defined it.
  4428  		//
  4429  		// This combination of inline and extern has almost the effect of a macro. The
  4430  		// way to use it is to put a function definition in a header file with these
  4431  		// keywords, and put another copy of the definition (lacking inline and extern)
  4432  		// in a library file. The definition in the header file causes most calls to
  4433  		// the function to be inlined. If any uses of the function remain, they refer
  4434  		// to the single copy in the library.
  4435  		return
  4436  	}
  4437  
  4438  	name := d.Name().String()
  4439  	if _, ok := p.task.hide[name]; ok {
  4440  		return
  4441  	}
  4442  
  4443  	if p.isMain && d.Linkage == cc.External && d.Read == 0 && !d.AddressTaken && len(p.task.asts) == 1 {
  4444  		return
  4445  	}
  4446  
  4447  	if d.Linkage == cc.Internal && d.Read == 0 && !d.AddressTaken /*TODO- && strings.HasPrefix(name, "__") */ {
  4448  		return
  4449  	}
  4450  
  4451  	tld := p.tlds[d]
  4452  	if tld == nil {
  4453  		return
  4454  	}
  4455  
  4456  	p.fn = name
  4457  
  4458  	defer func() { p.fn = "" }()
  4459  
  4460  	f := newFunction(p, n)
  4461  	p.pass1 = true
  4462  	p.compoundStatement(f, n.CompoundStatement, "", false, false, 0)
  4463  	p.pass1 = false
  4464  	p.w("\n\n")
  4465  	p.functionDefinitionSignature(n, f, tld)
  4466  	if p.task.header && p.task.funcSig {
  4467  		return
  4468  	}
  4469  
  4470  	p.w(" ")
  4471  	comment := fmt.Sprintf("/* %v: */", p.pos(d))
  4472  	if p.task.panicStubs {
  4473  		p.w("%s{ panic(%q) }", comment, tld.name)
  4474  		return
  4475  	}
  4476  
  4477  	brace := "{"
  4478  	if need := f.off; need != 0 {
  4479  		scope := f.blocks[n.CompoundStatement].scope
  4480  		f.bpName = scope.take(idBp)
  4481  		p.w("{%s\n%s := %s.Alloc(%d)\n", comment, f.bpName, f.tlsName, need)
  4482  		p.w("defer %s.Free(%d)\n", f.tlsName, need)
  4483  		for _, v := range d.Type().Parameters() {
  4484  			if local := f.locals[v.Declarator()]; local != nil && local.isPinned { // Pin it.
  4485  				p.w("*(*%s)(unsafe.Pointer(%s%s)) = %s\n", p.typ(v.Declarator(), paramTypeDecay(v.Declarator())), f.bpName, nonZeroUintptr(local.off), local.name)
  4486  			}
  4487  		}
  4488  		comment = ""
  4489  		brace = ""
  4490  	}
  4491  	if len(f.vlas) != 0 {
  4492  		p.w("%s%s\n", brace, comment)
  4493  		var vlas []*cc.Declarator
  4494  		for k := range f.vlas {
  4495  			vlas = append(vlas, k)
  4496  		}
  4497  		sort.Slice(vlas, func(i, j int) bool {
  4498  			return vlas[i].NameTok().Seq() < vlas[j].NameTok().Seq()
  4499  		})
  4500  		for _, v := range vlas {
  4501  			local := f.locals[v]
  4502  			switch {
  4503  			case local.isPinned:
  4504  				panic(todo("", v.Position()))
  4505  			default:
  4506  				p.w("var %s uintptr // %v: %v\n", local.name, p.pos(v), v.Type())
  4507  			}
  4508  		}
  4509  		switch {
  4510  		case len(vlas) == 1:
  4511  			p.w("defer %sXfree(%s, %s)\n", p.task.crt, f.tlsName, f.locals[vlas[0]].name)
  4512  		default:
  4513  			p.w("defer func() {\n")
  4514  			for _, v := range vlas {
  4515  				p.w("%sXfree(%s, %s)\n", p.task.crt, f.tlsName, f.locals[v].name)
  4516  			}
  4517  			p.w("\n}()\n")
  4518  		}
  4519  	}
  4520  	p.compoundStatement(f, n.CompoundStatement, comment, false, true, 0)
  4521  	p.w(";")
  4522  	p.flushLocalTaggesStructs()
  4523  	p.flushStaticTLDs()
  4524  }
  4525  
  4526  func (p *project) flushLocalTaggesStructs() {
  4527  	for _, v := range p.localTaggedStructs {
  4528  		v()
  4529  	}
  4530  	p.localTaggedStructs = nil
  4531  }
  4532  
  4533  func (p *project) flushStaticTLDs() {
  4534  	for _, v := range p.staticQueue {
  4535  		p.tld(nil, v, "\n", true)
  4536  	}
  4537  	p.staticQueue = nil
  4538  }
  4539  
  4540  func (p *project) compoundStatement(f *function, n *cc.CompoundStatement, scomment string, forceNoBraces, fnBody bool, mode exprMode) {
  4541  	if p.task.panicStubs {
  4542  		return
  4543  	}
  4544  
  4545  	// '{' BlockItemList '}'
  4546  	brace := (!n.IsJumpTarget() || n.Parent() == nil) && !forceNoBraces
  4547  	if brace && len(f.vlas) == 0 && (n.Parent() != nil || f.off == 0) {
  4548  		p.w("{%s", scomment)
  4549  	}
  4550  	if fnBody {
  4551  		p.instrument(n)
  4552  	}
  4553  	sv := f.block
  4554  	f.block = f.blocks[n]
  4555  	if f.block.topDecl {
  4556  		for _, v := range f.block.decls {
  4557  			p.declaration(f, v, true)
  4558  		}
  4559  	}
  4560  	var r *cc.JumpStatement
  4561  	for list := n.BlockItemList; list != nil; list = list.BlockItemList {
  4562  		m := mode
  4563  		if list.BlockItemList != nil {
  4564  			m = 0
  4565  		}
  4566  		r = p.blockItem(f, list.BlockItem, m)
  4567  	}
  4568  	if n.Parent() == nil && r == nil && f.rt.Kind() != cc.Void {
  4569  		p.w("\nreturn ")
  4570  		p.zeroValue(n, f.rt)
  4571  	}
  4572  	s := tidyComment("\n", &n.Token2)
  4573  	p.w("%s", s)
  4574  	if brace {
  4575  		if !strings.HasSuffix(s, "\n") {
  4576  			p.w("\n")
  4577  		}
  4578  		p.w("}")
  4579  	}
  4580  	f.block = sv
  4581  }
  4582  
  4583  func (p *project) zeroValue(n cc.Node, t cc.Type) {
  4584  	if t.IsScalarType() {
  4585  		p.w("%s(0)", p.typ(n, t))
  4586  		return
  4587  	}
  4588  
  4589  	switch t.Kind() {
  4590  	case cc.Struct, cc.Union:
  4591  		p.w("%s{}", p.typ(n, t))
  4592  	default:
  4593  		panic(todo("", t, t.Kind()))
  4594  	}
  4595  }
  4596  
  4597  func (p *project) blockItem(f *function, n *cc.BlockItem, mode exprMode) (r *cc.JumpStatement) {
  4598  	switch n.Case {
  4599  	case cc.BlockItemDecl: // Declaration
  4600  		p.declaration(f, n.Declaration, false)
  4601  	case cc.BlockItemStmt: // Statement
  4602  		r = p.statement(f, n.Statement, false, false, false, mode)
  4603  		p.w(";")
  4604  		if r == nil {
  4605  			p.instrument(n)
  4606  		}
  4607  	case cc.BlockItemLabel: // LabelDeclaration
  4608  		panic(todo("", p.pos(n)))
  4609  		p.w(";")
  4610  	case cc.BlockItemFuncDef: // DeclarationSpecifiers Declarator CompoundStatement
  4611  		p.err(n, "nested functions not supported")
  4612  		p.w(";")
  4613  	case cc.BlockItemPragma: // PragmaSTDC
  4614  		panic(todo("", p.pos(n)))
  4615  		p.w(";")
  4616  	default:
  4617  		panic(todo("%v: internal error: %v", n.Position(), n.Case))
  4618  	}
  4619  	return r
  4620  }
  4621  
  4622  func (p *project) instrument(n cc.Node) {
  4623  	if p.task.cover {
  4624  		p.w("%sCover();", p.task.crt)
  4625  	}
  4626  	if p.task.coverC {
  4627  		p.w("%sCoverC(%q);", p.task.crt, p.pos(n).String()+" "+p.fn)
  4628  	}
  4629  	if p.task.watch {
  4630  		p.w("%sWatch();", p.task.crt)
  4631  	}
  4632  }
  4633  
  4634  var dummyJumpStatement = &cc.JumpStatement{}
  4635  
  4636  func (p *project) statement(f *function, n *cc.Statement, forceCompoundStmtBrace, forceNoBraces, switchBlock bool, mode exprMode) (r *cc.JumpStatement) {
  4637  	if forceCompoundStmtBrace {
  4638  		if f.switchCtx == inSwitchFirst && p.pauseCodegen {
  4639  			p.pauseCodegen = false
  4640  			p.w(" {")
  4641  			p.pauseCodegen = true
  4642  		}
  4643  		p.w(" {")
  4644  		if !switchBlock {
  4645  			p.instrument(n)
  4646  		}
  4647  	}
  4648  	switch n.Case {
  4649  	case cc.StatementLabeled: // LabeledStatement
  4650  		r = p.labeledStatement(f, n.LabeledStatement)
  4651  	case cc.StatementCompound: // CompoundStatement
  4652  		if !forceCompoundStmtBrace {
  4653  			p.w("%s", n.CompoundStatement.Token.Sep)
  4654  		}
  4655  		if f.hasJumps {
  4656  			forceNoBraces = true
  4657  		}
  4658  		p.compoundStatement(f, n.CompoundStatement, "", forceCompoundStmtBrace || forceNoBraces, false, 0)
  4659  	case cc.StatementExpr: // ExpressionStatement
  4660  		if mode != 0 {
  4661  			p.w("return ")
  4662  			e := n.ExpressionStatement.Expression
  4663  			p.expression(f, e, e.Operand.Type(), exprValue, 0)
  4664  			r = dummyJumpStatement
  4665  			break
  4666  		}
  4667  
  4668  		p.expressionStatement(f, n.ExpressionStatement)
  4669  	case cc.StatementSelection: // SelectionStatement
  4670  		p.selectionStatement(f, n.SelectionStatement)
  4671  	case cc.StatementIteration: // IterationStatement
  4672  		p.iterationStatement(f, n.IterationStatement)
  4673  	case cc.StatementJump: // JumpStatement
  4674  		r = p.jumpStatement(f, n.JumpStatement)
  4675  	case cc.StatementAsm: // AsmStatement
  4676  		// AsmStatement:
  4677  		//         Asm AttributeSpecifierList ';'
  4678  		// Asm:
  4679  		//         "__asm__" AsmQualifierList '(' STRINGLITERAL AsmArgList ')'
  4680  		if n.AsmStatement.Asm.Token3.Value == 0 && n.AsmStatement.Asm.AsmArgList == nil {
  4681  			break
  4682  		}
  4683  
  4684  		p.w("panic(`%s: assembler statements not supported`)", n.Position())
  4685  	default:
  4686  		panic(todo("%v: internal error: %v", n.Position(), n.Case))
  4687  	}
  4688  	if forceCompoundStmtBrace {
  4689  		// We need to do this, to guarantee that we always close the brace is we opened it
  4690  		if f.switchCtx == inSwitchFirst && p.pauseCodegen {
  4691  			p.pauseCodegen = false
  4692  			p.w("}")
  4693  			p.pauseCodegen = true
  4694  		}
  4695  		p.w("}")
  4696  	}
  4697  	return r
  4698  }
  4699  
  4700  func (p *project) jumpStatement(f *function, n *cc.JumpStatement) (r *cc.JumpStatement) {
  4701  	p.w("%s", tidyComment("\n", n))
  4702  	if _, ok := n.Context().(*cc.SelectionStatement); ok && f.ifCtx == nil {
  4703  		switch f.switchCtx {
  4704  		case inSwitchCase:
  4705  			f.switchCtx = inSwitchSeenBreak
  4706  		case inSwitchSeenBreak:
  4707  			// nop but TODO
  4708  		case inSwitchFlat:
  4709  			// ok
  4710  		default:
  4711  			panic(todo("", n.Position(), f.switchCtx))
  4712  		}
  4713  	}
  4714  
  4715  	switch n.Case {
  4716  	case cc.JumpStatementGoto: // "goto" IDENTIFIER ';'
  4717  		p.w("goto %s", f.labelNames[n.Token2.Value])
  4718  	case cc.JumpStatementGotoExpr: // "goto" '*' Expression ';'
  4719  		panic(todo("", p.pos(n)))
  4720  	case cc.JumpStatementContinue: // "continue" ';'
  4721  		switch {
  4722  		case f.continueCtx != 0:
  4723  			p.w("goto __%d", f.continueCtx)
  4724  		default:
  4725  			p.w("continue")
  4726  		}
  4727  	case cc.JumpStatementBreak: // "break" ';'
  4728  		switch {
  4729  		case f.breakCtx != 0:
  4730  			p.w("goto __%d", f.breakCtx)
  4731  		default:
  4732  			p.w("break")
  4733  		}
  4734  	case cc.JumpStatementReturn: // "return" Expression ';'
  4735  		r = n
  4736  		switch {
  4737  		case f.rt != nil && f.rt.Kind() == cc.Void:
  4738  			if n.Expression != nil {
  4739  				p.expression(f, n.Expression, n.Expression.Operand.Type(), exprVoid, 0)
  4740  				p.w(";")
  4741  			}
  4742  			p.w("return")
  4743  		case f.rt != nil && f.rt.Kind() != cc.Void:
  4744  			if n.Expression != nil {
  4745  				p.expression(f, n.Expression, f.rt, exprCondReturn, 0)
  4746  				break
  4747  			}
  4748  
  4749  			p.w("return ")
  4750  			p.zeroValue(n, f.rt)
  4751  		default:
  4752  			if n.Expression != nil {
  4753  				p.expression(f, n.Expression, n.Expression.Operand.Type(), exprVoid, 0)
  4754  				p.w(";")
  4755  			}
  4756  			p.w("return")
  4757  		}
  4758  	default:
  4759  		panic(todo("%v: internal error: %v", n.Position(), n.Case))
  4760  	}
  4761  	return r
  4762  }
  4763  
  4764  func (p *project) expression(f *function, n *cc.Expression, t cc.Type, mode exprMode, flags flags) {
  4765  	switch mode {
  4766  	case exprVoid:
  4767  		p.expressionVoid(f, n, t, mode, flags)
  4768  	case exprValue, exprCondReturn, exprCondInit:
  4769  		p.expressionValue(f, n, t, mode, flags)
  4770  	case exprBool:
  4771  		p.expressionBool(f, n, t, mode, flags)
  4772  	case exprAddrOf:
  4773  		p.expressionAddrOf(f, n, t, mode, flags)
  4774  	case exprPSelect:
  4775  		p.expressionPSelect(f, n, t, mode, flags)
  4776  	case exprLValue:
  4777  		p.expressionLValue(f, n, t, mode, flags)
  4778  	case exprFunc:
  4779  		p.expressionFunc(f, n, t, mode, flags)
  4780  	case exprSelect:
  4781  		p.expressionSelect(f, n, t, mode, flags)
  4782  	case exprDecay:
  4783  		p.expressionDecay(f, n, t, mode, flags)
  4784  	default:
  4785  		panic(todo("", n.Position(), mode))
  4786  	}
  4787  }
  4788  
  4789  func (p *project) expressionDecay(f *function, n *cc.Expression, t cc.Type, mode exprMode, flags flags) {
  4790  	switch n.Case {
  4791  	case cc.ExpressionAssign: // AssignmentExpression
  4792  		p.assignmentExpression(f, n.AssignmentExpression, t, mode, flags)
  4793  	case cc.ExpressionComma: // Expression ',' AssignmentExpression
  4794  		p.w("func() uintptr {")
  4795  		p.expression(f, n.Expression, n.Expression.Operand.Type(), exprVoid, flags)
  4796  		p.w("; return ")
  4797  		p.assignmentExpression(f, n.AssignmentExpression, t, mode, flags)
  4798  		p.w("}()")
  4799  	default:
  4800  		panic(todo("%v: internal error: %v", n.Position(), n.Case))
  4801  	}
  4802  }
  4803  
  4804  func (p *project) expressionSelect(f *function, n *cc.Expression, t cc.Type, mode exprMode, flags flags) {
  4805  	switch n.Case {
  4806  	case cc.ExpressionAssign: // AssignmentExpression
  4807  		p.assignmentExpression(f, n.AssignmentExpression, t, mode, flags)
  4808  	case cc.ExpressionComma: // Expression ',' AssignmentExpression
  4809  		panic(todo("", p.pos(n)))
  4810  	default:
  4811  		panic(todo("%v: internal error: %v", n.Position(), n.Case))
  4812  	}
  4813  }
  4814  
  4815  func (p *project) expressionFunc(f *function, n *cc.Expression, t cc.Type, mode exprMode, flags flags) {
  4816  	switch n.Case {
  4817  	case cc.ExpressionAssign: // AssignmentExpression
  4818  		p.assignmentExpression(f, n.AssignmentExpression, t, mode, flags)
  4819  	case cc.ExpressionComma: // Expression ',' AssignmentExpression
  4820  		panic(todo("", p.pos(n)))
  4821  	default:
  4822  		panic(todo("%v: internal error: %v", n.Position(), n.Case))
  4823  	}
  4824  }
  4825  
  4826  func (p *project) expressionLValue(f *function, n *cc.Expression, t cc.Type, mode exprMode, flags flags) {
  4827  	switch n.Case {
  4828  	case cc.ExpressionAssign: // AssignmentExpression
  4829  		p.assignmentExpression(f, n.AssignmentExpression, t, mode, flags)
  4830  	case cc.ExpressionComma: // Expression ',' AssignmentExpression
  4831  		panic(todo("", p.pos(n)))
  4832  	default:
  4833  		panic(todo("%v: internal error: %v", n.Position(), n.Case))
  4834  	}
  4835  }
  4836  
  4837  func (p *project) expressionPSelect(f *function, n *cc.Expression, t cc.Type, mode exprMode, flags flags) {
  4838  	switch n.Case {
  4839  	case cc.ExpressionAssign: // AssignmentExpression
  4840  		p.assignmentExpression(f, n.AssignmentExpression, t, mode, flags)
  4841  	case cc.ExpressionComma: // Expression ',' AssignmentExpression
  4842  		panic(todo("", p.pos(n)))
  4843  	default:
  4844  		panic(todo("%v: internal error: %v", n.Position(), n.Case))
  4845  	}
  4846  }
  4847  
  4848  func (p *project) expressionAddrOf(f *function, n *cc.Expression, t cc.Type, mode exprMode, flags flags) {
  4849  	switch n.Case {
  4850  	case cc.ExpressionAssign: // AssignmentExpression
  4851  		p.assignmentExpression(f, n.AssignmentExpression, t, mode, flags)
  4852  	case cc.ExpressionComma: // Expression ',' AssignmentExpression
  4853  		p.w(" func() uintptr {")
  4854  		p.expression(f, n.Expression, n.Expression.Operand.Type(), exprVoid, flags)
  4855  		p.w("; return ")
  4856  		p.assignmentExpression(f, n.AssignmentExpression, t, mode, flags)
  4857  		p.w("}()")
  4858  	default:
  4859  		panic(todo("%v: internal error: %v", n.Position(), n.Case))
  4860  	}
  4861  }
  4862  
  4863  func (p *project) expressionBool(f *function, n *cc.Expression, t cc.Type, mode exprMode, flags flags) {
  4864  	switch n.Case {
  4865  	case cc.ExpressionAssign: // AssignmentExpression
  4866  		p.assignmentExpression(f, n.AssignmentExpression, t, mode, flags)
  4867  	case cc.ExpressionComma: // Expression ',' AssignmentExpression
  4868  		p.w("func() bool {")
  4869  		p.expression(f, n.Expression, n.Expression.Operand.Type(), exprVoid, flags)
  4870  		p.w("; return ")
  4871  		p.assignmentExpression(f, n.AssignmentExpression, n.AssignmentExpression.Operand.Type(), mode, flags)
  4872  		p.w("}()")
  4873  	default:
  4874  		panic(todo("%v: internal error: %v", n.Position(), n.Case))
  4875  	}
  4876  }
  4877  
  4878  func (p *project) expressionValue(f *function, n *cc.Expression, t cc.Type, mode exprMode, flags flags) {
  4879  	switch n.Case {
  4880  	case cc.ExpressionAssign: // AssignmentExpression
  4881  		p.assignmentExpression(f, n.AssignmentExpression, t, mode, flags)
  4882  	case cc.ExpressionComma: // Expression ',' AssignmentExpression
  4883  		if mode == exprCondReturn {
  4884  			p.expression(f, n.Expression, n.Expression.Operand.Type(), exprVoid, flags)
  4885  			p.w("; return ")
  4886  			p.assignmentExpression(f, n.AssignmentExpression, n.AssignmentExpression.Operand.Type(), exprValue, flags)
  4887  			return
  4888  		}
  4889  
  4890  		switch {
  4891  		case n.AssignmentExpression.Operand.Type().Kind() == cc.Array:
  4892  			p.expressionDecay(f, n, t, exprDecay, flags)
  4893  		default:
  4894  			defer p.w("%s", p.convertType(n, n.Operand.Type(), t, flags))
  4895  			p.w("func() %v {", p.typ(n, n.AssignmentExpression.Operand.Type()))
  4896  			p.expression(f, n.Expression, n.Expression.Operand.Type(), exprVoid, flags)
  4897  			p.w("; return ")
  4898  			p.assignmentExpression(f, n.AssignmentExpression, n.AssignmentExpression.Operand.Type(), exprValue, flags)
  4899  			p.w("}()")
  4900  		}
  4901  	default:
  4902  		panic(todo("%v: internal error: %v", n.Position(), n.Case))
  4903  	}
  4904  }
  4905  
  4906  func (p *project) expressionVoid(f *function, n *cc.Expression, t cc.Type, mode exprMode, flags flags) {
  4907  	switch n.Case {
  4908  	case cc.ExpressionAssign: // AssignmentExpression
  4909  		p.assignmentExpression(f, n.AssignmentExpression, t, mode, flags)
  4910  	case cc.ExpressionComma: // Expression ',' AssignmentExpression
  4911  		p.expression(f, n.Expression, t, mode, flags)
  4912  		p.w(";")
  4913  		p.assignmentExpression(f, n.AssignmentExpression, t, mode, flags)
  4914  	default:
  4915  		panic(todo("%v: internal error: %v", n.Position(), n.Case))
  4916  	}
  4917  }
  4918  
  4919  func (p *project) opKind(f *function, d declarator, t cc.Type) opKind {
  4920  	switch {
  4921  	case p.isArrayParameter(d, t):
  4922  		return opArrayParameter
  4923  	case !p.pass1 && p.isArray(f, d, t):
  4924  		return opArray
  4925  	case t.Kind() == cc.Union:
  4926  		return opUnion
  4927  	case t.Kind() == cc.Struct:
  4928  		return opStruct
  4929  	case t.IsBitFieldType():
  4930  		return opBitfield
  4931  	case t.Kind() == cc.Function:
  4932  		return opFunction
  4933  	default:
  4934  		return opNormal
  4935  	}
  4936  }
  4937  
  4938  func (p *project) assignmentExpression(f *function, n *cc.AssignmentExpression, t cc.Type, mode exprMode, flags flags) {
  4939  	switch mode {
  4940  	case exprVoid:
  4941  		p.assignmentExpressionVoid(f, n, t, mode, flags)
  4942  	case exprValue, exprCondReturn, exprCondInit:
  4943  		p.assignmentExpressionValue(f, n, t, mode, flags)
  4944  	case exprAddrOf:
  4945  		p.assignmentExpressionAddrOf(f, n, t, mode, flags)
  4946  	case exprBool:
  4947  		p.assignmentExpressionBool(f, n, t, mode, flags)
  4948  	case exprLValue:
  4949  		p.assignmentExpressionLValue(f, n, t, mode, flags)
  4950  	case exprPSelect:
  4951  		p.assignmentExpressionPSelect(f, n, t, mode, flags)
  4952  	case exprFunc:
  4953  		p.assignmentExpressionFunc(f, n, t, mode, flags)
  4954  	case exprSelect:
  4955  		p.assignmentExpressionSelect(f, n, t, mode, flags)
  4956  	case exprDecay:
  4957  		p.assignmentExpressionDecay(f, n, t, mode, flags)
  4958  	default:
  4959  		panic(todo("", n.Position(), mode))
  4960  	}
  4961  }
  4962  
  4963  func (p *project) assignmentExpressionDecay(f *function, n *cc.AssignmentExpression, t cc.Type, mode exprMode, flags flags) {
  4964  	switch n.Case {
  4965  	case cc.AssignmentExpressionCond: // ConditionalExpression
  4966  		p.conditionalExpression(f, n.ConditionalExpression, t, mode, flags)
  4967  	case cc.AssignmentExpressionAssign: // UnaryExpression '=' AssignmentExpression
  4968  		panic(todo("", p.pos(n)))
  4969  	case cc.AssignmentExpressionMul: // UnaryExpression "*=" AssignmentExpression
  4970  		panic(todo("", p.pos(n)))
  4971  	case cc.AssignmentExpressionDiv: // UnaryExpression "/=" AssignmentExpression
  4972  		panic(todo("", p.pos(n)))
  4973  	case cc.AssignmentExpressionMod: // UnaryExpression "%=" AssignmentExpression
  4974  		panic(todo("", p.pos(n)))
  4975  	case cc.AssignmentExpressionAdd: // UnaryExpression "+=" AssignmentExpression
  4976  		panic(todo("", p.pos(n)))
  4977  	case cc.AssignmentExpressionSub: // UnaryExpression "-=" AssignmentExpression
  4978  		panic(todo("", p.pos(n)))
  4979  	case cc.AssignmentExpressionLsh: // UnaryExpression "<<= AssignmentExpression
  4980  		panic(todo("", p.pos(n)))
  4981  	case cc.AssignmentExpressionRsh: // UnaryExpression ">>=" AssignmentExpression
  4982  		panic(todo("", p.pos(n)))
  4983  	case cc.AssignmentExpressionAnd: // UnaryExpression "&=" AssignmentExpression
  4984  		panic(todo("", p.pos(n)))
  4985  	case cc.AssignmentExpressionXor: // UnaryExpression "^=" AssignmentExpression
  4986  		panic(todo("", p.pos(n)))
  4987  	case cc.AssignmentExpressionOr: // UnaryExpression "|=" AssignmentExpression
  4988  		panic(todo("", p.pos(n)))
  4989  	default:
  4990  		panic(todo("%v: internal error: %v", n.Position(), n.Case))
  4991  	}
  4992  }
  4993  
  4994  func (p *project) assignmentExpressionSelect(f *function, n *cc.AssignmentExpression, t cc.Type, mode exprMode, flags flags) {
  4995  	switch n.Case {
  4996  	case cc.AssignmentExpressionCond: // ConditionalExpression
  4997  		p.conditionalExpression(f, n.ConditionalExpression, t, mode, flags)
  4998  	case cc.AssignmentExpressionAssign: // UnaryExpression '=' AssignmentExpression
  4999  		panic(todo("", p.pos(n)))
  5000  	case cc.AssignmentExpressionMul: // UnaryExpression "*=" AssignmentExpression
  5001  		panic(todo("", p.pos(n)))
  5002  	case cc.AssignmentExpressionDiv: // UnaryExpression "/=" AssignmentExpression
  5003  		panic(todo("", p.pos(n)))
  5004  	case cc.AssignmentExpressionMod: // UnaryExpression "%=" AssignmentExpression
  5005  		panic(todo("", p.pos(n)))
  5006  	case cc.AssignmentExpressionAdd: // UnaryExpression "+=" AssignmentExpression
  5007  		panic(todo("", p.pos(n)))
  5008  	case cc.AssignmentExpressionSub: // UnaryExpression "-=" AssignmentExpression
  5009  		panic(todo("", p.pos(n)))
  5010  	case cc.AssignmentExpressionLsh: // UnaryExpression "<<=" AssignmentExpression
  5011  		panic(todo("", p.pos(n)))
  5012  	case cc.AssignmentExpressionRsh: // UnaryExpression ">>=" AssignmentExpression
  5013  		panic(todo("", p.pos(n)))
  5014  	case cc.AssignmentExpressionAnd: // UnaryExpression "&=" AssignmentExpression
  5015  		panic(todo("", p.pos(n)))
  5016  	case cc.AssignmentExpressionXor: // UnaryExpression "^=" AssignmentExpression
  5017  		panic(todo("", p.pos(n)))
  5018  	case cc.AssignmentExpressionOr: // UnaryExpression "|=" AssignmentExpression
  5019  		panic(todo("", p.pos(n)))
  5020  	default:
  5021  		panic(todo("%v: internal error: %v", n.Position(), n.Case))
  5022  	}
  5023  }
  5024  
  5025  func (p *project) assignmentExpressionFunc(f *function, n *cc.AssignmentExpression, t cc.Type, mode exprMode, flags flags) {
  5026  	switch n.Case {
  5027  	case cc.AssignmentExpressionCond: // ConditionalExpression
  5028  		p.conditionalExpression(f, n.ConditionalExpression, t, mode, flags)
  5029  	case cc.AssignmentExpressionAssign: // UnaryExpression '=' AssignmentExpression
  5030  		panic(todo("", p.pos(n)))
  5031  	case cc.AssignmentExpressionMul: // UnaryExpression "*=" AssignmentExpression
  5032  		panic(todo("", p.pos(n)))
  5033  	case cc.AssignmentExpressionDiv: // UnaryExpression "/=" AssignmentExpression
  5034  		panic(todo("", p.pos(n)))
  5035  	case cc.AssignmentExpressionMod: // UnaryExpression "%=" AssignmentExpression
  5036  		panic(todo("", p.pos(n)))
  5037  	case cc.AssignmentExpressionAdd: // UnaryExpression "+=" AssignmentExpression
  5038  		panic(todo("", p.pos(n)))
  5039  	case cc.AssignmentExpressionSub: // UnaryExpression "-=" AssignmentExpression
  5040  		panic(todo("", p.pos(n)))
  5041  	case cc.AssignmentExpressionLsh: // UnaryExpremode, ssion "<<=
  5042  		panic(todo("", p.pos(n)))
  5043  	case cc.AssignmentExpressionRsh: // UnaryExpression ">>=" AssignmentExpression
  5044  		panic(todo("", p.pos(n)))
  5045  	case cc.AssignmentExpressionAnd: // UnaryExpression "&=" AssignmentExpression
  5046  		panic(todo("", p.pos(n)))
  5047  	case cc.AssignmentExpressionXor: // UnaryExpression "^=" AssignmentExpression
  5048  		panic(todo("", p.pos(n)))
  5049  	case cc.AssignmentExpressionOr: // UnaryExpression "|=" AssignmentExpression
  5050  		panic(todo("", p.pos(n)))
  5051  	default:
  5052  		panic(todo("%v: internal error: %v", n.Position(), n.Case))
  5053  	}
  5054  }
  5055  
  5056  func (p *project) assignmentExpressionPSelect(f *function, n *cc.AssignmentExpression, t cc.Type, mode exprMode, flags flags) {
  5057  	switch n.Case {
  5058  	case cc.AssignmentExpressionCond: // ConditionalExpression
  5059  		p.conditionalExpression(f, n.ConditionalExpression, t, mode, flags)
  5060  	case cc.AssignmentExpressionAssign: // UnaryExpression '=' AssignmentExpression
  5061  		p.w("(*%s)(unsafe.Pointer(", p.typ(n, n.AssignmentExpression.Operand.Type().Elem()))
  5062  		p.assignmentExpression(f, n, t, exprValue, flags)
  5063  		p.w("))")
  5064  	case cc.AssignmentExpressionMul: // UnaryExpression "*=" AssignmentExpression
  5065  		panic(todo("", p.pos(n)))
  5066  	case cc.AssignmentExpressionDiv: // UnaryExpression "/=" AssignmentExpression
  5067  		panic(todo("", p.pos(n)))
  5068  	case cc.AssignmentExpressionMod: // UnaryExpression "%=" AssignmentExpression
  5069  		panic(todo("", p.pos(n)))
  5070  	case cc.AssignmentExpressionAdd: // UnaryExpression "+=" AssignmentExpression
  5071  		panic(todo("", p.pos(n)))
  5072  	case cc.AssignmentExpressionSub: // UnaryExpression "-=" AssignmentExpression
  5073  		panic(todo("", p.pos(n)))
  5074  	case cc.AssignmentExpressionLsh: // UnaryExpression "<<=" AssignmentExpression
  5075  		panic(todo("", p.pos(n)))
  5076  	case cc.AssignmentExpressionRsh: // UnaryExpression ">>=" AssignmentExpression
  5077  		panic(todo("", p.pos(n)))
  5078  	case cc.AssignmentExpressionAnd: // UnaryExpression "&=" AssignmentExpression
  5079  		panic(todo("", p.pos(n)))
  5080  	case cc.AssignmentExpressionXor: // UnaryExpression "^=" AssignmentExpression
  5081  		panic(todo("", p.pos(n)))
  5082  	case cc.AssignmentExpressionOr: // UnaryExpression "|=" AssignmentExpression
  5083  		panic(todo("", p.pos(n)))
  5084  	default:
  5085  		panic(todo("%v: internal error: %v", n.Position(), n.Case))
  5086  	}
  5087  }
  5088  
  5089  func (p *project) assignmentExpressionLValue(f *function, n *cc.AssignmentExpression, t cc.Type, mode exprMode, flags flags) {
  5090  	switch n.Case {
  5091  	case cc.AssignmentExpressionCond: // ConditionalExpression
  5092  		p.conditionalExpression(f, n.ConditionalExpression, t, mode, flags)
  5093  	case cc.AssignmentExpressionAssign: // UnaryExpression '=' AssignmentExpression
  5094  		panic(todo("", p.pos(n)))
  5095  	case cc.AssignmentExpressionMul: // UnaryExpression "*=" AssignmentExpression
  5096  		panic(todo("", p.pos(n)))
  5097  	case cc.AssignmentExpressionDiv: // UnaryExpression "/=" AssignmentExpression
  5098  		panic(todo("", p.pos(n)))
  5099  	case cc.AssignmentExpressionMod: // UnaryExpression "%=" AssignmentExpression
  5100  		panic(todo("", p.pos(n)))
  5101  	case cc.AssignmentExpressionAdd: // UnaryExpression "+=" AssignmentExpression
  5102  		panic(todo("", p.pos(n)))
  5103  	case cc.AssignmentExpressionSub: // UnaryExpression "-=" AssignmentExpression
  5104  		panic(todo("", p.pos(n)))
  5105  	case cc.AssignmentExpressionLsh: // UnaryExpression "<<=" AssignmentExpression
  5106  		panic(todo("", p.pos(n)))
  5107  	case cc.AssignmentExpressionRsh: // UnaryExpression ">>=" AssignmentExpression
  5108  		panic(todo("", p.pos(n)))
  5109  	case cc.AssignmentExpressionAnd: // UnaryExpression "&=" AssignmentExpression
  5110  		panic(todo("", p.pos(n)))
  5111  	case cc.AssignmentExpressionXor: // UnaryExpression "^=" AssignmentExpression
  5112  		panic(todo("", p.pos(n)))
  5113  	case cc.AssignmentExpressionOr: // UnaryExpression "|=" AssignmentExpression
  5114  		panic(todo("", p.pos(n)))
  5115  	default:
  5116  		panic(todo("%v: internal error: %v", n.Position(), n.Case))
  5117  	}
  5118  }
  5119  
  5120  func (p *project) assignmentExpressionBool(f *function, n *cc.AssignmentExpression, t cc.Type, mode exprMode, flags flags) {
  5121  	switch n.Case {
  5122  	case cc.AssignmentExpressionCond: // ConditionalExpression
  5123  		p.conditionalExpression(f, n.ConditionalExpression, t, mode, flags)
  5124  	default:
  5125  		// case cc.AssignmentExpressionAssign: // UnaryExpression '=' AssignmentExpression
  5126  		// case cc.AssignmentExpressionMul: // UnaryExpression "*=" AssignmentExpression
  5127  		// case cc.AssignmentExpressionDiv: // UnaryExpression "/=" AssignmentExpression
  5128  		// case cc.AssignmentExpressionMod: // UnaryExpression "%=" AssignmentExpression
  5129  		// case cc.AssignmentExpressionAdd: // UnaryExpression "+=" AssignmentExpression
  5130  		// case cc.AssignmentExpressionSub: // UnaryExpression "-=" AssignmentExpression
  5131  		// case cc.AssignmentExpressionLsh: // UnaryExpression "<<=" AssignmentExpression
  5132  		// case cc.AssignmentExpressionRsh: // UnaryExpression ">>=" AssignmentExpression
  5133  		// case cc.AssignmentExpressionAnd: // UnaryExpression "&=" AssignmentExpression
  5134  		// case cc.AssignmentExpressionXor: // UnaryExpression "^=" AssignmentExpression
  5135  		// case cc.AssignmentExpressionOr: // UnaryExpression "|=" AssignmentExpression
  5136  		p.w("(")
  5137  		defer p.w(")")
  5138  		defer p.w(" != 0 ")
  5139  		p.assignmentExpression(f, n, t, exprValue, flags)
  5140  	}
  5141  }
  5142  
  5143  func (p *project) assignmentExpressionAddrOf(f *function, n *cc.AssignmentExpression, t cc.Type, mode exprMode, flags flags) {
  5144  	switch n.Case {
  5145  	case cc.AssignmentExpressionCond: // ConditionalExpression
  5146  		p.conditionalExpression(f, n.ConditionalExpression, t, mode, flags)
  5147  	case cc.AssignmentExpressionAssign: // UnaryExpression '=' AssignmentExpression
  5148  		p.assignmentExpressionValueAddrOf(f, n, t, mode, flags)
  5149  	case cc.AssignmentExpressionMul: // UnaryExpression "*=" AssignmentExpression
  5150  		panic(todo("", p.pos(n)))
  5151  	case cc.AssignmentExpressionDiv: // UnaryExpression "/=" AssignmentExpression
  5152  		panic(todo("", p.pos(n)))
  5153  	case cc.AssignmentExpressionMod: // UnaryExpression "%=" AssignmentExpression
  5154  		panic(todo("", p.pos(n)))
  5155  	case cc.AssignmentExpressionAdd: // UnaryExpression "+=" AssignmentExpression
  5156  		panic(todo("", p.pos(n)))
  5157  	case cc.AssignmentExpressionSub: // UnaryExpression "-=" AssignmentExpression
  5158  		panic(todo("", p.pos(n)))
  5159  	case cc.AssignmentExpressionLsh: // UnaryExpression "<<=" AssignmentExpression
  5160  		panic(todo("", p.pos(n)))
  5161  	case cc.AssignmentExpressionRsh: // UnaryExpression ">>=" AssignmentExpression
  5162  		panic(todo("", p.pos(n)))
  5163  	case cc.AssignmentExpressionAnd: // UnaryExpression "&=" AssignmentExpression
  5164  		panic(todo("", p.pos(n)))
  5165  	case cc.AssignmentExpressionXor: // UnaryExpression "^=" AssignmentExpression
  5166  		panic(todo("", p.pos(n)))
  5167  	case cc.AssignmentExpressionOr: // UnaryExpression "|=" AssignmentExpression
  5168  		panic(todo("", p.pos(n)))
  5169  	default:
  5170  		panic(todo("%v: internal error: %v", n.Position(), n.Case))
  5171  	}
  5172  }
  5173  
  5174  func (p *project) assignmentExpressionValueAddrOf(f *function, n *cc.AssignmentExpression, t cc.Type, mode exprMode, flags flags) {
  5175  	// UnaryExpression '=' AssignmentExpression
  5176  	if mode == exprCondReturn {
  5177  		panic(todo("", p.pos(n)))
  5178  	}
  5179  
  5180  	lhs := n.UnaryExpression
  5181  	switch k := p.opKind(f, lhs, lhs.Operand.Type()); k {
  5182  	case opStruct, opUnion:
  5183  		p.assignmentExpressionValueAssignStructAddrof(f, n, n.Operand.Type(), mode, flags)
  5184  	default:
  5185  		panic(todo("", n.Position(), k))
  5186  	}
  5187  }
  5188  
  5189  func (p *project) assignmentExpressionValueAssignStructAddrof(f *function, n *cc.AssignmentExpression, t cc.Type, mode exprMode, flags flags) {
  5190  	// UnaryExpression '=' AssignmentExpression
  5191  	lhs := n.UnaryExpression.Operand.Type()
  5192  	rhs := n.AssignmentExpression.Operand.Type()
  5193  	if lhs.Kind() == cc.Array || rhs.Kind() == cc.Array {
  5194  		panic(todo("", p.pos(n)))
  5195  	}
  5196  
  5197  	if d := n.UnaryExpression.Declarator(); d != nil {
  5198  		if local := f.locals[d]; local != nil {
  5199  			if local.isPinned {
  5200  				if !p.pass1 {
  5201  					p.w("%sXmemmove(tls, ", p.task.crt)
  5202  					p.unaryExpression(f, n.UnaryExpression, lhs, exprAddrOf, flags)
  5203  					p.w(", ")
  5204  					p.assignmentExpression(f, n.AssignmentExpression, rhs, exprAddrOf, flags)
  5205  					p.w(", %d)", lhs.Size())
  5206  					return
  5207  				}
  5208  			}
  5209  
  5210  			if !p.pass1 {
  5211  				panic(todo("", p.pos(n)))
  5212  			}
  5213  		}
  5214  	}
  5215  
  5216  	p.w("%sXmemmove(tls, ", p.task.crt)
  5217  	p.unaryExpression(f, n.UnaryExpression, lhs, exprAddrOf, flags)
  5218  	p.w(", ")
  5219  	p.assignmentExpression(f, n.AssignmentExpression, rhs, exprAddrOf, flags)
  5220  	p.w(", %d)", lhs.Size())
  5221  }
  5222  
  5223  func (p *project) assignmentExpressionValue(f *function, n *cc.AssignmentExpression, t cc.Type, mode exprMode, flags flags) {
  5224  	switch n.Case {
  5225  	case cc.AssignmentExpressionCond: // ConditionalExpression
  5226  		p.conditionalExpression(f, n.ConditionalExpression, t, mode, flags)
  5227  	case cc.AssignmentExpressionAssign: // UnaryExpression '=' AssignmentExpression
  5228  		p.assignmentExpressionValueAssign(f, n, t, mode, flags)
  5229  	case cc.AssignmentExpressionMul: // UnaryExpression "*=" AssignmentExpression
  5230  		p.assignOp(f, n, t, mode, "*", "Mul", flags)
  5231  	case cc.AssignmentExpressionDiv: // UnaryExpression "/=" AssignmentExpression
  5232  		p.assignOp(f, n, t, mode, "/", "Div", flags)
  5233  	case cc.AssignmentExpressionMod: // UnaryExpression "%=" AssignmentExpression
  5234  		p.assignOp(f, n, t, mode, "%", "Rem", flags)
  5235  	case cc.AssignmentExpressionAdd: // UnaryExpression "+=" AssignmentExpression
  5236  		p.assignOp(f, n, t, mode, "+", "Add", flags)
  5237  	case cc.AssignmentExpressionSub: // UnaryExpression "-=" AssignmentExpression
  5238  		p.assignOp(f, n, t, mode, "-", "Sub", flags)
  5239  	case cc.AssignmentExpressionLsh: // UnaryExpremode, ssion "<<=
  5240  		p.assignOp(f, n, t, mode, "<<", "Shl", flags)
  5241  	case cc.AssignmentExpressionRsh: // UnaryExpression ">>=" AssignmentExpression
  5242  		p.assignOp(f, n, t, mode, ">>", "Shr", flags)
  5243  	case cc.AssignmentExpressionAnd: // UnaryExpression "&=" AssignmentExpression
  5244  		p.assignOp(f, n, t, mode, "&", "And", flags)
  5245  	case cc.AssignmentExpressionXor: // UnaryExpression "^=" AssignmentExpression
  5246  		p.assignOp(f, n, t, mode, "^", "Xor", flags)
  5247  	case cc.AssignmentExpressionOr: // UnaryExpression "|=" AssignmentExpression
  5248  		p.assignOp(f, n, t, mode, "|", "Or", flags)
  5249  	default:
  5250  		panic(todo("%v: internal error: %v", n.Position(), n.Case))
  5251  	}
  5252  }
  5253  
  5254  func (p *project) assignmentExpressionValueAssign(f *function, n *cc.AssignmentExpression, t cc.Type, mode exprMode, flags flags) {
  5255  	// UnaryExpression '=' AssignmentExpression
  5256  	if mode == exprCondReturn {
  5257  		p.w("return ")
  5258  	}
  5259  	lhs := n.UnaryExpression
  5260  	switch k := p.opKind(f, lhs, lhs.Operand.Type()); k {
  5261  	case opNormal:
  5262  		p.assignmentExpressionValueAssignNormal(f, n, t, mode, flags)
  5263  	case opBitfield:
  5264  		p.assignmentExpressionValueAssignBitfield(f, n, t, mode, flags)
  5265  	case opStruct, opUnion:
  5266  		p.assignmentExpressionValueAssignStruct(f, n, t, mode, flags)
  5267  	default:
  5268  		panic(todo("", n.Position(), k))
  5269  	}
  5270  }
  5271  
  5272  func (p *project) assignmentExpressionValueAssignStruct(f *function, n *cc.AssignmentExpression, t cc.Type, mode exprMode, flags flags) {
  5273  	// UnaryExpression '=' AssignmentExpression
  5274  	lhs := n.UnaryExpression.Operand.Type()
  5275  	rhs := n.AssignmentExpression.Operand.Type()
  5276  	if lhs.Kind() == cc.Array || rhs.Kind() == cc.Array {
  5277  		panic(todo("", p.pos(n)))
  5278  	}
  5279  
  5280  	p.w(" func() %s { __v := ", p.typ(n, lhs))
  5281  	p.assignmentExpression(f, n.AssignmentExpression, rhs, exprValue, flags)
  5282  	p.w(";")
  5283  	p.unaryExpression(f, n.UnaryExpression, lhs, exprLValue, flags)
  5284  	p.w(" = __v; return __v}()")
  5285  }
  5286  
  5287  func (p *project) assignmentExpressionValueAssignBitfield(f *function, n *cc.AssignmentExpression, t cc.Type, mode exprMode, flags flags) {
  5288  	if d := n.UnaryExpression.Declarator(); d != nil {
  5289  		panic(todo("", p.pos(n)))
  5290  	}
  5291  
  5292  	lhs := n.UnaryExpression
  5293  	lt := lhs.Operand.Type()
  5294  	bf := lt.BitField()
  5295  	defer p.w("%s", p.convertType(n, lt, t, flags))
  5296  	p.w("%sAssignBitFieldPtr%d%s(", p.task.crt, bf.BitFieldBlockWidth(), p.bfHelperType(lt))
  5297  	p.unaryExpression(f, lhs, lt, exprAddrOf, flags)
  5298  	p.w(", ")
  5299  	p.assignmentExpression(f, n.AssignmentExpression, lt, exprValue, flags)
  5300  	p.w(", %d, %d, %#x)", bf.BitFieldWidth(), bf.BitFieldOffset(), bf.Mask())
  5301  }
  5302  
  5303  func (p *project) assignmentExpressionValueAssignNormal(f *function, n *cc.AssignmentExpression, t cc.Type, mode exprMode, flags flags) {
  5304  	if d := n.UnaryExpression.Declarator(); d != nil {
  5305  		if !d.Type().IsScalarType() {
  5306  			panic(todo("", p.pos(n)))
  5307  		}
  5308  
  5309  		if local := f.locals[d]; local != nil {
  5310  			if local.isPinned {
  5311  				defer p.w(")%s", p.convertType(n, d.Type(), t, flags))
  5312  				p.w("%sAssignPtr%s(", p.task.crt, p.helperType(d, d.Type()))
  5313  				p.w("%s%s /* %s */", f.bpName, nonZeroUintptr(local.off), local.name)
  5314  				p.w(", ")
  5315  				p.assignmentExpression(f, n.AssignmentExpression, n.UnaryExpression.Operand.Type(), exprValue, flags)
  5316  				return
  5317  			}
  5318  
  5319  			defer p.w(")%s", p.convertType(n, d.Type(), t, flags))
  5320  			p.w("%sAssign%s(&%s, ", p.task.crt, p.helperType(n, d.Type()), local.name)
  5321  			p.assignmentExpression(f, n.AssignmentExpression, n.UnaryExpression.Operand.Type(), exprValue, flags)
  5322  			return
  5323  		}
  5324  	}
  5325  
  5326  	defer p.w(")%s", p.convertType(n, n.UnaryExpression.Operand.Type(), t, flags))
  5327  	p.w("%sAssignPtr%s(", p.task.crt, p.helperType(n, n.UnaryExpression.Operand.Type()))
  5328  	p.unaryExpression(f, n.UnaryExpression, n.UnaryExpression.Operand.Type(), exprAddrOf, flags)
  5329  	p.w(", ")
  5330  	p.assignmentExpression(f, n.AssignmentExpression, n.UnaryExpression.Operand.Type(), exprValue, flags)
  5331  }
  5332  
  5333  func (p *project) assignmentExpressionVoid(f *function, n *cc.AssignmentExpression, t cc.Type, mode exprMode, flags flags) {
  5334  	switch n.Case {
  5335  	case cc.AssignmentExpressionCond: // ConditionalExpression
  5336  		p.conditionalExpression(f, n.ConditionalExpression, t, mode, flags)
  5337  	case cc.AssignmentExpressionAssign: // UnaryExpression '=' AssignmentExpression
  5338  		d := n.UnaryExpression.Declarator()
  5339  		lhs := n.UnaryExpression
  5340  		lt := lhs.Operand.Type()
  5341  		sv := f.condInitPrefix
  5342  		switch k := p.opKind(f, lhs, lt); k {
  5343  		case opArrayParameter:
  5344  			lt = lt.Decay()
  5345  			fallthrough
  5346  		case opNormal, opStruct:
  5347  			mode = exprValue
  5348  			if p.isArrayOrPinnedArray(f, n.AssignmentExpression, n.AssignmentExpression.Operand.Type()) {
  5349  				mode = exprDecay
  5350  			}
  5351  			switch {
  5352  			case flags&fNoCondAssignment == 0 && mode == exprValue && n.UnaryExpression.Declarator() != nil && p.isConditionalAssignmentExpr(n.AssignmentExpression):
  5353  				f.condInitPrefix = func() {
  5354  					p.unaryExpression(f, lhs, lt, exprLValue, flags)
  5355  					p.w(" = ")
  5356  				}
  5357  				p.assignmentExpression(f, n.AssignmentExpression, lt, exprCondInit, flags)
  5358  				p.w(";")
  5359  			default:
  5360  				if d != nil && p.isVolatileOrAtomic(d) {
  5361  					p.setVolatileDeclarator(d, f, n.AssignmentExpression, lt, mode, flags)
  5362  					return
  5363  				}
  5364  
  5365  				p.unaryExpression(f, lhs, lt, exprLValue, flags)
  5366  				p.w(" = ")
  5367  				p.assignmentExpression(f, n.AssignmentExpression, lt, mode, flags)
  5368  			}
  5369  		case opBitfield:
  5370  			bf := lt.BitField()
  5371  			p.w("%sSetBitFieldPtr%d%s(", p.task.crt, bf.BitFieldBlockWidth(), p.bfHelperType(lt))
  5372  			p.unaryExpression(f, lhs, lt, exprAddrOf, flags)
  5373  			p.w(", ")
  5374  			p.assignmentExpression(f, n.AssignmentExpression, lt, exprValue, flags)
  5375  			p.w(", %d, %#x)", bf.BitFieldOffset(), bf.Mask())
  5376  		case opUnion:
  5377  			p.unaryExpression(f, lhs, lt, exprLValue, flags)
  5378  			p.w(" = ")
  5379  			p.assignmentExpression(f, n.AssignmentExpression, lt, exprValue, flags)
  5380  		default:
  5381  			panic(todo("", n.Position(), k))
  5382  		}
  5383  		f.condInitPrefix = sv
  5384  	case cc.AssignmentExpressionMul: // UnaryExpression "*=" AssignmentExpression
  5385  		p.assignOp(f, n, t, mode, "*", "Mul", flags)
  5386  	case cc.AssignmentExpressionDiv: // UnaryExpression "/=" AssignmentExpression
  5387  		p.assignOp(f, n, t, mode, "/", "Div", flags)
  5388  	case cc.AssignmentExpressionMod: // UnaryExpression "%=" AssignmentExpression
  5389  		p.assignOp(f, n, t, mode, "%", "Mod", flags)
  5390  	case cc.AssignmentExpressionAdd: // UnaryExpression "+=" AssignmentExpression
  5391  		p.assignOp(f, n, t, mode, "+", "Add", flags)
  5392  	case cc.AssignmentExpressionSub: // UnaryExpression "-=" AssignmentExpression
  5393  		p.assignOp(f, n, t, mode, "-", "Sub", flags)
  5394  	case cc.AssignmentExpressionLsh: // UnaryExpression "<<=" AssignmentExpression
  5395  		p.assignShiftOp(f, n, t, mode, "<<", "Shl", flags)
  5396  	case cc.AssignmentExpressionRsh: // UnaryExpression ">>=" AssignmentExpression
  5397  		p.assignShiftOp(f, n, t, mode, ">>", "Shr", flags)
  5398  	case cc.AssignmentExpressionAnd: // UnaryExpression "&=" AssignmentExpression
  5399  		p.assignOp(f, n, t, mode, "&", "And", flags)
  5400  	case cc.AssignmentExpressionXor: // UnaryExpression "^=" AssignmentExpression
  5401  		p.assignOp(f, n, t, mode, "^", "Xor", flags)
  5402  	case cc.AssignmentExpressionOr: // UnaryExpression "|=" AssignmentExpression
  5403  		p.assignOp(f, n, t, mode, "|", "Or", flags)
  5404  	default:
  5405  		panic(todo("%v: internal error: %v", n.Position(), n.Case))
  5406  	}
  5407  }
  5408  
  5409  func (p *project) setVolatileDeclarator(d *cc.Declarator, f *function, n *cc.AssignmentExpression, t cc.Type, mode exprMode, flags flags) {
  5410  	sz := d.Type().Size()
  5411  	switch sz {
  5412  	case 4, 8:
  5413  		// ok
  5414  	default:
  5415  		p.err(d, "unsupported volatile declarator size: %v", sz)
  5416  		return
  5417  	}
  5418  
  5419  	if local := f.locals[d]; local != nil {
  5420  		if local.isPinned {
  5421  			p.w("%sAtomicStoreP%s(%s%s /* %s */, ", p.task.crt, p.helperType(n, d.Type()), f.bpName, nonZeroUintptr(local.off), local.name)
  5422  			p.assignmentExpression(f, n, t, mode, flags)
  5423  			p.w(")")
  5424  			return
  5425  		}
  5426  
  5427  		p.atomicStoreNamedAddr(n, d.Type(), local.name, n, f, mode, flags)
  5428  		return
  5429  	}
  5430  
  5431  	if tld := p.tlds[d]; tld != nil {
  5432  		p.atomicStoreNamedAddr(n, d.Type(), tld.name, n, f, mode, flags)
  5433  		return
  5434  	}
  5435  
  5436  	if imp := p.imports[d.Name().String()]; imp != nil {
  5437  		p.atomicStoreNamedAddr(n, d.Type(), fmt.Sprintf("%sX%s", imp.qualifier, d.Name()), n, f, mode, flags)
  5438  		return
  5439  	}
  5440  
  5441  	panic(todo("", n.Position(), d.Position(), d.Name()))
  5442  }
  5443  
  5444  func (p *project) atomicStoreNamedAddr(n cc.Node, t cc.Type, nm string, expr *cc.AssignmentExpression, f *function, mode exprMode, flags flags) {
  5445  	sz := t.Size()
  5446  	switch sz {
  5447  	case 4, 8:
  5448  		// ok
  5449  	default:
  5450  		p.err(n, "unsupported volatile declarator size: %v", sz)
  5451  		return
  5452  	}
  5453  
  5454  	var ht string
  5455  	switch {
  5456  	case t.IsScalarType():
  5457  		ht = p.helperType(n, t)
  5458  	default:
  5459  		p.err(n, "unsupported volatile declarator type: %v", t)
  5460  		return
  5461  	}
  5462  
  5463  	p.w("%sAtomicStore%s(&%s, %s(", p.task.crt, ht, nm, p.typ(n, t))
  5464  	p.assignmentExpression(f, expr, t, mode, flags)
  5465  	p.w("))")
  5466  }
  5467  
  5468  func (p *project) atomicLoadNamedAddr(n cc.Node, t cc.Type, nm string) {
  5469  	sz := t.Size()
  5470  	switch sz {
  5471  	case 4, 8:
  5472  		// ok
  5473  	default:
  5474  		p.err(n, "unsupported volatile declarator size: %v", sz)
  5475  		return
  5476  	}
  5477  
  5478  	var ht string
  5479  	switch {
  5480  	case t.IsScalarType():
  5481  		ht = p.helperType(n, t)
  5482  	default:
  5483  		p.err(n, "unsupported volatile declarator type: %v", t)
  5484  		return
  5485  	}
  5486  
  5487  	p.w("%sAtomicLoad%s(&%s)", p.task.crt, ht, nm)
  5488  }
  5489  
  5490  func isRealType(op cc.Operand) bool {
  5491  	switch op.Type().Kind() {
  5492  	case cc.Float, cc.Double:
  5493  		return true
  5494  	default:
  5495  		return false
  5496  	}
  5497  }
  5498  
  5499  func (p *project) bfHelperType(t cc.Type) string {
  5500  	switch {
  5501  	case t.IsSignedType():
  5502  		return fmt.Sprintf("Int%d", t.Size()*8)
  5503  	default:
  5504  		return fmt.Sprintf("Uint%d", t.Size()*8)
  5505  	}
  5506  }
  5507  
  5508  func (p *project) helperType(n cc.Node, t cc.Type) string {
  5509  	for t.IsAliasType() {
  5510  		if t2 := t.Alias(); t2 != t { //TODO HDF5 H5O.c
  5511  			t = t2
  5512  			continue
  5513  		}
  5514  
  5515  		break
  5516  	}
  5517  	switch t.Kind() {
  5518  	case cc.Int128:
  5519  		return "Int128"
  5520  	case cc.UInt128:
  5521  		return "Uint128"
  5522  	}
  5523  
  5524  	s := p.typ(n, t)
  5525  	return strings.ToUpper(s[:1]) + s[1:]
  5526  }
  5527  
  5528  func (p *project) helperType2(n cc.Node, from, to cc.Type) string {
  5529  	if from.Kind() == to.Kind() {
  5530  		return fmt.Sprintf("%s%s", p.task.crt, p.helperType(n, from))
  5531  	}
  5532  
  5533  	return fmt.Sprintf("%s%sFrom%s", p.task.crt, p.helperType(n, to), p.helperType(n, from))
  5534  }
  5535  
  5536  func (p *project) conditionalExpression(f *function, n *cc.ConditionalExpression, t cc.Type, mode exprMode, flags flags) {
  5537  	switch mode {
  5538  	case exprValue:
  5539  		p.conditionalExpressionValue(f, n, t, mode, flags)
  5540  	case exprVoid:
  5541  		p.conditionalExpressionVoid(f, n, t, mode, flags)
  5542  	case exprAddrOf:
  5543  		p.conditionalExpressionAddrOf(f, n, t, mode, flags)
  5544  	case exprBool:
  5545  		p.conditionalExpressionBool(f, n, t, mode, flags)
  5546  	case exprLValue:
  5547  		p.conditionalExpressionLValue(f, n, t, mode, flags)
  5548  	case exprPSelect:
  5549  		p.conditionalExpressionPSelect(f, n, t, mode, flags)
  5550  	case exprFunc:
  5551  		p.conditionalExpressionFunc(f, n, t, mode, flags)
  5552  	case exprSelect:
  5553  		p.conditionalExpressionSelect(f, n, t, mode, flags)
  5554  	case exprCondReturn:
  5555  		p.conditionalExpressionReturn(f, n, t, mode, flags)
  5556  	case exprCondInit:
  5557  		p.conditionalExpressionInit(f, n, t, mode, flags)
  5558  	case exprDecay:
  5559  		p.conditionalExpressionDecay(f, n, t, mode, flags)
  5560  	default:
  5561  		panic(todo("", n.Position(), mode))
  5562  	}
  5563  }
  5564  
  5565  func (p *project) conditionalExpressionDecay(f *function, n *cc.ConditionalExpression, t cc.Type, mode exprMode, flags flags) {
  5566  	switch n.Case {
  5567  	case cc.ConditionalExpressionLOr: // LogicalOrExpression
  5568  		p.logicalOrExpression(f, n.LogicalOrExpression, t, mode, flags)
  5569  	case cc.ConditionalExpressionCond: // LogicalOrExpression '?' Expression ':' ConditionalExpression
  5570  		t = t.Decay()
  5571  		p.w(" func() %s { if ", p.typ(n, t))
  5572  		p.logicalOrExpression(f, n.LogicalOrExpression, n.LogicalOrExpression.Operand.Type(), exprBool, flags)
  5573  		p.w(" { return ")
  5574  		switch n.Expression.Operand.Type().Kind() {
  5575  		case cc.Array:
  5576  			p.expression(f, n.Expression, t, exprDecay, flags)
  5577  		case cc.Ptr:
  5578  			panic(todo("", n.Expression.Position(), n.Expression.Operand.Type()))
  5579  		default:
  5580  			panic(todo("", n.Expression.Position(), n.Expression.Operand.Type()))
  5581  		}
  5582  		p.w("}; return ")
  5583  		switch n.ConditionalExpression.Operand.Type().Kind() {
  5584  		case cc.Array:
  5585  			p.conditionalExpression(f, n.ConditionalExpression, t, exprDecay, flags)
  5586  		default:
  5587  			p.conditionalExpression(f, n.ConditionalExpression, t, exprValue, flags)
  5588  		}
  5589  		p.w("}()")
  5590  	default:
  5591  		panic(todo("%v: internal error: %v", n.Position(), n.Case))
  5592  	}
  5593  }
  5594  
  5595  func (p *project) conditionalExpressionInit(f *function, n *cc.ConditionalExpression, t cc.Type, mode exprMode, flags flags) {
  5596  	switch n.Case {
  5597  	case cc.ConditionalExpressionLOr: // LogicalOrExpression
  5598  		f.condInitPrefix()
  5599  		p.logicalOrExpression(f, n.LogicalOrExpression, t, exprValue, flags)
  5600  	case cc.ConditionalExpressionCond: // LogicalOrExpression '?' Expression ':' ConditionalExpression
  5601  		t = t.Decay()
  5602  		p.w("if ")
  5603  		p.logicalOrExpression(f, n.LogicalOrExpression, n.LogicalOrExpression.Operand.Type(), exprBool, flags)
  5604  		p.w(" {")
  5605  		p.expression(f, n.Expression, t, mode, flags)
  5606  		p.w("} else { ")
  5607  		p.conditionalExpression(f, n.ConditionalExpression, t, mode, flags)
  5608  		p.w("}")
  5609  	default:
  5610  		panic(todo("%v: internal error: %v", n.Position(), n.Case))
  5611  	}
  5612  }
  5613  
  5614  func (p *project) conditionalExpressionReturn(f *function, n *cc.ConditionalExpression, t cc.Type, mode exprMode, flags flags) {
  5615  	switch n.Case {
  5616  	case cc.ConditionalExpressionLOr: // LogicalOrExpression
  5617  		p.w("return ")
  5618  		p.logicalOrExpression(f, n.LogicalOrExpression, t, exprValue, flags)
  5619  	case cc.ConditionalExpressionCond: // LogicalOrExpression '?' Expression ':' ConditionalExpression
  5620  		t = t.Decay()
  5621  		p.w("if ")
  5622  		p.logicalOrExpression(f, n.LogicalOrExpression, n.LogicalOrExpression.Operand.Type(), exprBool, flags)
  5623  		p.w(" {")
  5624  		p.expression(f, n.Expression, t, mode, flags)
  5625  		p.w("}; ")
  5626  		p.conditionalExpression(f, n.ConditionalExpression, t, mode, flags)
  5627  	default:
  5628  		panic(todo("%v: internal error: %v", n.Position(), n.Case))
  5629  	}
  5630  }
  5631  
  5632  func (p *project) conditionalExpressionSelect(f *function, n *cc.ConditionalExpression, t cc.Type, mode exprMode, flags flags) {
  5633  	switch n.Case {
  5634  	case cc.ConditionalExpressionLOr: // LogicalOrExpression
  5635  		p.logicalOrExpression(f, n.LogicalOrExpression, t, mode, flags)
  5636  	case cc.ConditionalExpressionCond: // LogicalOrExpression '?' Expression ':' ConditionalExpression
  5637  		panic(todo("", p.pos(n)))
  5638  	default:
  5639  		panic(todo("%v: internal error: %v", n.Position(), n.Case))
  5640  	}
  5641  }
  5642  
  5643  func (p *project) conditionalExpressionFunc(f *function, n *cc.ConditionalExpression, t cc.Type, mode exprMode, flags flags) {
  5644  	switch n.Case {
  5645  	case cc.ConditionalExpressionLOr: // LogicalOrExpression
  5646  		p.logicalOrExpression(f, n.LogicalOrExpression, t, mode, flags)
  5647  	case cc.ConditionalExpressionCond: // LogicalOrExpression '?' Expression ':' ConditionalExpression
  5648  		switch ot := n.Operand.Type(); ot.Kind() {
  5649  		case cc.Function:
  5650  			if t.Kind() != cc.Function {
  5651  				panic(todo("", n.Position()))
  5652  			}
  5653  		default:
  5654  			panic(todo("", ot.Kind()))
  5655  		}
  5656  
  5657  		p.w(" func() ")
  5658  		p.functionSignature(n, f, t, "")
  5659  		p.w("{ if ")
  5660  		p.logicalOrExpression(f, n.LogicalOrExpression, n.LogicalOrExpression.Operand.Type(), exprBool, flags)
  5661  		p.w(" { return ")
  5662  		switch d := n.Expression.Declarator(); {
  5663  		case d != nil:
  5664  			p.declaratorDefault(n, d)
  5665  		default:
  5666  			panic(todo("", n.Position()))
  5667  		}
  5668  		p.w("}; return ")
  5669  		switch d := n.ConditionalExpression.Declarator(); {
  5670  		case d != nil:
  5671  			p.declaratorDefault(n, d)
  5672  		default:
  5673  			panic(todo("", n.Position()))
  5674  		}
  5675  		p.w("}()")
  5676  	default:
  5677  		panic(todo("%v: internal error: %v", n.Position(), n.Case))
  5678  	}
  5679  }
  5680  
  5681  func (p *project) conditionalExpressionPSelect(f *function, n *cc.ConditionalExpression, t cc.Type, mode exprMode, flags flags) {
  5682  	switch n.Case {
  5683  	case cc.ConditionalExpressionLOr: // LogicalOrExpression
  5684  		p.logicalOrExpression(f, n.LogicalOrExpression, t, mode, flags)
  5685  	case cc.ConditionalExpressionCond: // LogicalOrExpression '?' Expression ':' ConditionalExpression
  5686  		p.w("(*%s)(unsafe.Pointer(", p.typ(n, n.Operand.Type().Elem()))
  5687  		p.conditionalExpression(f, n, t, exprValue, flags)
  5688  		p.w("))")
  5689  	default:
  5690  		panic(todo("%v: internal error: %v", n.Position(), n.Case))
  5691  	}
  5692  }
  5693  
  5694  func (p *project) conditionalExpressionLValue(f *function, n *cc.ConditionalExpression, t cc.Type, mode exprMode, flags flags) {
  5695  	switch n.Case {
  5696  	case cc.ConditionalExpressionLOr: // LogicalOrExpression
  5697  		p.logicalOrExpression(f, n.LogicalOrExpression, t, mode, flags)
  5698  	case cc.ConditionalExpressionCond: // LogicalOrExpression '?' Expression ':' ConditionalExpression
  5699  		panic(todo("", p.pos(n)))
  5700  	default:
  5701  		panic(todo("%v: internal error: %v", n.Position(), n.Case))
  5702  	}
  5703  }
  5704  
  5705  func (p *project) conditionalExpressionBool(f *function, n *cc.ConditionalExpression, t cc.Type, mode exprMode, flags flags) {
  5706  	switch n.Case {
  5707  	case cc.ConditionalExpressionLOr: // LogicalOrExpression
  5708  		p.logicalOrExpression(f, n.LogicalOrExpression, t, mode, flags)
  5709  	case cc.ConditionalExpressionCond: // LogicalOrExpression '?' Expression ':' ConditionalExpression
  5710  		p.w("(")
  5711  		defer p.w(")")
  5712  		defer p.w(" != 0 ")
  5713  		p.conditionalExpression(f, n, t, exprValue, flags)
  5714  	default:
  5715  		panic(todo("%v: internal error: %v", n.Position(), n.Case))
  5716  	}
  5717  }
  5718  
  5719  func (p *project) conditionalExpressionAddrOf(f *function, n *cc.ConditionalExpression, t cc.Type, mode exprMode, flags flags) {
  5720  	switch n.Case {
  5721  	case cc.ConditionalExpressionLOr: // LogicalOrExpression
  5722  		p.logicalOrExpression(f, n.LogicalOrExpression, t, mode, flags)
  5723  	case cc.ConditionalExpressionCond: // LogicalOrExpression '?' Expression ':' ConditionalExpression
  5724  		t = t.Decay()
  5725  		p.w(" func() %s { if ", p.typ(n, t))
  5726  		p.logicalOrExpression(f, n.LogicalOrExpression, n.LogicalOrExpression.Operand.Type(), exprBool, flags)
  5727  		p.w(" { return ")
  5728  		p.expression(f, n.Expression, t, exprValue, flags)
  5729  		p.w("}; return ")
  5730  		p.conditionalExpression(f, n.ConditionalExpression, t, exprValue, flags)
  5731  		p.w("}()")
  5732  	default:
  5733  		panic(todo("%v: internal error: %v", n.Position(), n.Case))
  5734  	}
  5735  }
  5736  
  5737  func (p *project) conditionalExpressionVoid(f *function, n *cc.ConditionalExpression, t cc.Type, mode exprMode, flags flags) {
  5738  	switch n.Case {
  5739  	case cc.ConditionalExpressionLOr: // LogicalOrExpression
  5740  		p.logicalOrExpression(f, n.LogicalOrExpression, t, mode, flags)
  5741  	case cc.ConditionalExpressionCond: // LogicalOrExpression '?' Expression ':' ConditionalExpression
  5742  		switch {
  5743  		case n.Expression.IsSideEffectsFree:
  5744  			p.w("if !(")
  5745  			p.logicalOrExpression(f, n.LogicalOrExpression, n.LogicalOrExpression.Operand.Type(), exprBool, flags)
  5746  			p.w(") {")
  5747  			p.conditionalExpression(f, n.ConditionalExpression, n.ConditionalExpression.Operand.Type(), mode, flags)
  5748  			p.w("}")
  5749  		default:
  5750  			p.w("if ")
  5751  			p.logicalOrExpression(f, n.LogicalOrExpression, n.LogicalOrExpression.Operand.Type(), exprBool, flags)
  5752  			p.w(" {")
  5753  			p.expression(f, n.Expression, n.Expression.Operand.Type(), mode, flags)
  5754  			p.w("} else {")
  5755  			p.conditionalExpression(f, n.ConditionalExpression, n.ConditionalExpression.Operand.Type(), mode, flags)
  5756  			p.w("}")
  5757  		}
  5758  	default:
  5759  		panic(todo("%v: internal error: %v", n.Position(), n.Case))
  5760  	}
  5761  }
  5762  
  5763  func (p *project) conditionalExpressionValue(f *function, n *cc.ConditionalExpression, t cc.Type, mode exprMode, flags flags) {
  5764  	switch n.Case {
  5765  	case cc.ConditionalExpressionLOr: // LogicalOrExpression
  5766  		p.logicalOrExpression(f, n.LogicalOrExpression, t, exprValue, flags)
  5767  	case cc.ConditionalExpressionCond: // LogicalOrExpression '?' Expression ':' ConditionalExpression
  5768  		t = t.Decay()
  5769  		p.w(" func() %s { if ", p.typ(n, t))
  5770  		p.logicalOrExpression(f, n.LogicalOrExpression, n.LogicalOrExpression.Operand.Type(), exprBool, flags)
  5771  		p.w(" { return ")
  5772  		p.expression(f, n.Expression, t, exprValue, flags)
  5773  		p.w("}; return ")
  5774  		p.conditionalExpression(f, n.ConditionalExpression, t, exprValue, flags)
  5775  		p.w("}()")
  5776  	default:
  5777  		panic(todo("%v: internal error: %v", n.Position(), n.Case))
  5778  	}
  5779  }
  5780  
  5781  func (p *project) logicalOrExpression(f *function, n *cc.LogicalOrExpression, t cc.Type, mode exprMode, flags flags) {
  5782  	switch mode {
  5783  	case exprValue:
  5784  		p.logicalOrExpressionValue(f, n, t, mode, flags)
  5785  	case exprVoid:
  5786  		p.logicalOrExpressionVoid(f, n, t, mode, flags)
  5787  	case exprAddrOf:
  5788  		p.logicalOrExpressionAddrOf(f, n, t, mode, flags)
  5789  	case exprBool:
  5790  		p.logicalOrExpressionBool(f, n, t, mode, flags)
  5791  	case exprLValue:
  5792  		p.logicalOrExpressionLValue(f, n, t, mode, flags)
  5793  	case exprPSelect:
  5794  		p.logicalOrExpressionPSelect(f, n, t, mode, flags)
  5795  	case exprFunc:
  5796  		p.logicalOrExpressionFunc(f, n, t, mode, flags)
  5797  	case exprSelect:
  5798  		p.logicalOrExpressionSelect(f, n, t, mode, flags)
  5799  	case exprDecay:
  5800  		p.logicalOrExpressionDecay(f, n, t, mode, flags)
  5801  	default:
  5802  		panic(todo("", n.Position(), mode))
  5803  	}
  5804  }
  5805  
  5806  func (p *project) logicalOrExpressionDecay(f *function, n *cc.LogicalOrExpression, t cc.Type, mode exprMode, flags flags) {
  5807  	switch n.Case {
  5808  	case cc.LogicalOrExpressionLAnd: // LogicalAndExpression
  5809  		p.logicalAndExpression(f, n.LogicalAndExpression, t, mode, flags)
  5810  	case cc.LogicalOrExpressionLOr: // LogicalOrExpression "||" LogicalAndExpression
  5811  		panic(todo("", p.pos(n)))
  5812  	default:
  5813  		panic(todo("%v: internal error: %v", n.Position(), n.Case))
  5814  	}
  5815  }
  5816  
  5817  func (p *project) logicalOrExpressionSelect(f *function, n *cc.LogicalOrExpression, t cc.Type, mode exprMode, flags flags) {
  5818  	switch n.Case {
  5819  	case cc.LogicalOrExpressionLAnd: // LogicalAndExpression
  5820  		p.logicalAndExpression(f, n.LogicalAndExpression, t, mode, flags)
  5821  	case cc.LogicalOrExpressionLOr: // LogicalOrExpression "||" LogicalAndExpression
  5822  		panic(todo("", p.pos(n)))
  5823  	default:
  5824  		panic(todo("%v: internal error: %v", n.Position(), n.Case))
  5825  	}
  5826  }
  5827  
  5828  func (p *project) logicalOrExpressionFunc(f *function, n *cc.LogicalOrExpression, t cc.Type, mode exprMode, flags flags) {
  5829  	switch n.Case {
  5830  	case cc.LogicalOrExpressionLAnd: // LogicalAndExpression
  5831  		p.logicalAndExpression(f, n.LogicalAndExpression, t, mode, flags)
  5832  	case cc.LogicalOrExpressionLOr: // LogicalOrExpression "||" LogicalAndExpression
  5833  		panic(todo("", p.pos(n)))
  5834  	default:
  5835  		panic(todo("%v: internal error: %v", n.Position(), n.Case))
  5836  	}
  5837  }
  5838  
  5839  func (p *project) logicalOrExpressionPSelect(f *function, n *cc.LogicalOrExpression, t cc.Type, mode exprMode, flags flags) {
  5840  	switch n.Case {
  5841  	case cc.LogicalOrExpressionLAnd: // LogicalAndExpression
  5842  		p.logicalAndExpression(f, n.LogicalAndExpression, t, mode, flags)
  5843  	case cc.LogicalOrExpressionLOr: // LogicalOrExpression "||" LogicalAndExpression
  5844  		panic(todo("", p.pos(n)))
  5845  	default:
  5846  		panic(todo("%v: internal error: %v", n.Position(), n.Case))
  5847  	}
  5848  }
  5849  
  5850  func (p *project) logicalOrExpressionLValue(f *function, n *cc.LogicalOrExpression, t cc.Type, mode exprMode, flags flags) {
  5851  	switch n.Case {
  5852  	case cc.LogicalOrExpressionLAnd: // LogicalAndExpression
  5853  		p.logicalAndExpression(f, n.LogicalAndExpression, t, mode, flags)
  5854  	case cc.LogicalOrExpressionLOr: // LogicalOrExpression "||" LogicalAndExpression
  5855  		panic(todo("", p.pos(n)))
  5856  	default:
  5857  		panic(todo("%v: internal error: %v", n.Position(), n.Case))
  5858  	}
  5859  }
  5860  
  5861  func (p *project) logicalOrExpressionBool(f *function, n *cc.LogicalOrExpression, t cc.Type, mode exprMode, flags flags) {
  5862  	switch n.Case {
  5863  	case cc.LogicalOrExpressionLAnd: // LogicalAndExpression
  5864  		p.logicalAndExpression(f, n.LogicalAndExpression, t, mode, flags)
  5865  	case cc.LogicalOrExpressionLOr: // LogicalOrExpression "||" LogicalAndExpression
  5866  		p.binaryLogicalOrExpression(f, n, t, mode, flags)
  5867  	default:
  5868  		panic(todo("%v: internal error: %v", n.Position(), n.Case))
  5869  	}
  5870  }
  5871  
  5872  func (p *project) logicalOrExpressionAddrOf(f *function, n *cc.LogicalOrExpression, t cc.Type, mode exprMode, flags flags) {
  5873  	switch n.Case {
  5874  	case cc.LogicalOrExpressionLAnd: // LogicalAndExpression
  5875  		p.logicalAndExpression(f, n.LogicalAndExpression, t, mode, flags)
  5876  	case cc.LogicalOrExpressionLOr: // LogicalOrExpression "||" LogicalAndExpression
  5877  		panic(todo("", p.pos(n)))
  5878  	default:
  5879  		panic(todo("%v: internal error: %v", n.Position(), n.Case))
  5880  	}
  5881  }
  5882  
  5883  func (p *project) logicalOrExpressionVoid(f *function, n *cc.LogicalOrExpression, t cc.Type, mode exprMode, flags flags) {
  5884  	switch n.Case {
  5885  	case cc.LogicalOrExpressionLAnd: // LogicalAndExpression
  5886  		p.logicalAndExpression(f, n.LogicalAndExpression, t, mode, flags)
  5887  	case cc.LogicalOrExpressionLOr: // LogicalOrExpression "||" LogicalAndExpression
  5888  		p.w("_ = ")
  5889  		p.logicalOrExpression(f, n, n.Operand.Type(), exprValue, flags)
  5890  	default:
  5891  		panic(todo("%v: internal error: %v", n.Position(), n.Case))
  5892  	}
  5893  }
  5894  
  5895  func (p *project) logicalOrExpressionValue(f *function, n *cc.LogicalOrExpression, t cc.Type, mode exprMode, flags flags) {
  5896  	switch n.Case {
  5897  	case cc.LogicalOrExpressionLAnd: // LogicalAndExpression
  5898  		p.logicalAndExpression(f, n.LogicalAndExpression, t, mode, flags)
  5899  	case cc.LogicalOrExpressionLOr: // LogicalOrExpression "||" LogicalAndExpression
  5900  		p.binaryLogicalOrExpression(f, n, t, mode, flags)
  5901  	default:
  5902  		panic(todo("%v: internal error: %v", n.Position(), n.Case))
  5903  	}
  5904  }
  5905  
  5906  func (p *project) binaryLogicalOrExpression(f *function, n *cc.LogicalOrExpression, t cc.Type, mode exprMode, flags flags) {
  5907  	switch mode {
  5908  	case exprValue:
  5909  		p.binaryLogicalOrExpressionValue(f, n, t, mode, flags)
  5910  	case exprBool:
  5911  		p.binaryLogicalOrExpressionBool(f, n, t, mode, flags)
  5912  	default:
  5913  		panic(todo("", n.Position(), mode))
  5914  	}
  5915  }
  5916  
  5917  func (p *project) binaryLogicalOrExpressionBool(f *function, n *cc.LogicalOrExpression, t cc.Type, mode exprMode, flags flags) {
  5918  	defer p.w("%s", p.booleanBinaryExpression(n, n.Operand, n.Operand.Type(), &mode, flags))
  5919  	p.logicalOrExpression(f, n.LogicalOrExpression, n.LogicalOrExpression.Operand.Type(), exprBool, flags)
  5920  	p.w(" ||%s", tidyComment(" ", &n.Token))
  5921  	p.logicalAndExpression(f, n.LogicalAndExpression, n.LogicalAndExpression.Operand.Type(), exprBool, flags)
  5922  }
  5923  
  5924  func (p *project) binaryLogicalOrExpressionValue(f *function, n *cc.LogicalOrExpression, t cc.Type, mode exprMode, flags flags) {
  5925  	defer p.w("%s", p.booleanBinaryExpression(n, n.Operand, t, &mode, flags))
  5926  	p.logicalOrExpression(f, n.LogicalOrExpression, n.LogicalOrExpression.Operand.Type(), exprBool, flags)
  5927  	p.w(" ||%s", tidyComment(" ", &n.Token))
  5928  	p.logicalAndExpression(f, n.LogicalAndExpression, n.LogicalAndExpression.Operand.Type(), exprBool, flags)
  5929  }
  5930  
  5931  func (p *project) booleanBinaryExpression(n cc.Node, from cc.Operand, to cc.Type, mode *exprMode, flags flags) (r string) {
  5932  	p.w("(")
  5933  	r = ")"
  5934  	switch *mode {
  5935  	case exprBool:
  5936  		*mode = exprValue
  5937  	default:
  5938  		r = p.convert(n, from, to, flags) + r
  5939  		p.w("%sBool32(", p.task.crt)
  5940  		r = ")" + r
  5941  	}
  5942  	return r
  5943  }
  5944  
  5945  func (p *project) logicalAndExpression(f *function, n *cc.LogicalAndExpression, t cc.Type, mode exprMode, flags flags) {
  5946  	switch mode {
  5947  	case exprValue:
  5948  		p.logicalAndExpressionValue(f, n, t, mode, flags)
  5949  	case exprVoid:
  5950  		p.logicalAndExpressionVoid(f, n, t, mode, flags)
  5951  	case exprAddrOf:
  5952  		p.logicalAndExpressionAddrOf(f, n, t, mode, flags)
  5953  	case exprBool:
  5954  		p.logicalAndExpressionBool(f, n, t, mode, flags)
  5955  	case exprLValue:
  5956  		p.logicalAndExpressionLValue(f, n, t, mode, flags)
  5957  	case exprPSelect:
  5958  		p.logicalAndExpressionPSelect(f, n, t, mode, flags)
  5959  	case exprFunc:
  5960  		p.logicalAndExpressionFunc(f, n, t, mode, flags)
  5961  	case exprSelect:
  5962  		p.logicalAndExpressionSelect(f, n, t, mode, flags)
  5963  	case exprDecay:
  5964  		p.logicalAndExpressionDecay(f, n, t, mode, flags)
  5965  	default:
  5966  		panic(todo("", n.Position(), mode))
  5967  	}
  5968  }
  5969  
  5970  func (p *project) logicalAndExpressionDecay(f *function, n *cc.LogicalAndExpression, t cc.Type, mode exprMode, flags flags) {
  5971  	switch n.Case {
  5972  	case cc.LogicalAndExpressionOr: // InclusiveOrExpression
  5973  		p.inclusiveOrExpression(f, n.InclusiveOrExpression, t, mode, flags)
  5974  	case cc.LogicalAndExpressionLAnd: // LogicalAndExpression "&&" InclusiveOrExpression
  5975  		panic(todo("", p.pos(n)))
  5976  	default:
  5977  		panic(todo("%v: internal error: %v", n.Position(), n.Case))
  5978  	}
  5979  }
  5980  
  5981  func (p *project) logicalAndExpressionSelect(f *function, n *cc.LogicalAndExpression, t cc.Type, mode exprMode, flags flags) {
  5982  	switch n.Case {
  5983  	case cc.LogicalAndExpressionOr: // InclusiveOrExpression
  5984  		p.inclusiveOrExpression(f, n.InclusiveOrExpression, t, mode, flags)
  5985  	case cc.LogicalAndExpressionLAnd: // LogicalAndExpression "&&" InclusiveOrExpression
  5986  		panic(todo("", p.pos(n)))
  5987  	default:
  5988  		panic(todo("%v: internal error: %v", n.Position(), n.Case))
  5989  	}
  5990  }
  5991  
  5992  func (p *project) logicalAndExpressionFunc(f *function, n *cc.LogicalAndExpression, t cc.Type, mode exprMode, flags flags) {
  5993  	switch n.Case {
  5994  	case cc.LogicalAndExpressionOr: // InclusiveOrExpression
  5995  		p.inclusiveOrExpression(f, n.InclusiveOrExpression, t, mode, flags)
  5996  	case cc.LogicalAndExpressionLAnd: // LogicalAndExpression "&&" InclusiveOrExpression
  5997  		panic(todo("", p.pos(n)))
  5998  	default:
  5999  		panic(todo("%v: internal error: %v", n.Position(), n.Case))
  6000  	}
  6001  }
  6002  
  6003  func (p *project) logicalAndExpressionPSelect(f *function, n *cc.LogicalAndExpression, t cc.Type, mode exprMode, flags flags) {
  6004  	switch n.Case {
  6005  	case cc.LogicalAndExpressionOr: // InclusiveOrExpression
  6006  		p.inclusiveOrExpression(f, n.InclusiveOrExpression, t, mode, flags)
  6007  	case cc.LogicalAndExpressionLAnd: // LogicalAndExpression "&&" InclusiveOrExpression
  6008  		panic(todo("", p.pos(n)))
  6009  	default:
  6010  		panic(todo("%v: internal error: %v", n.Position(), n.Case))
  6011  	}
  6012  }
  6013  
  6014  func (p *project) logicalAndExpressionLValue(f *function, n *cc.LogicalAndExpression, t cc.Type, mode exprMode, flags flags) {
  6015  	switch n.Case {
  6016  	case cc.LogicalAndExpressionOr: // InclusiveOrExpression
  6017  		p.inclusiveOrExpression(f, n.InclusiveOrExpression, t, mode, flags)
  6018  	case cc.LogicalAndExpressionLAnd: // LogicalAndExpression "&&" InclusiveOrExpression
  6019  		panic(todo("", p.pos(n)))
  6020  	default:
  6021  		panic(todo("%v: internal error: %v", n.Position(), n.Case))
  6022  	}
  6023  }
  6024  
  6025  func (p *project) logicalAndExpressionBool(f *function, n *cc.LogicalAndExpression, t cc.Type, mode exprMode, flags flags) {
  6026  	switch n.Case {
  6027  	case cc.LogicalAndExpressionOr: // InclusiveOrExpression
  6028  		p.inclusiveOrExpression(f, n.InclusiveOrExpression, t, mode, flags)
  6029  	case cc.LogicalAndExpressionLAnd: // LogicalAndExpression "&&" InclusiveOrExpression
  6030  		p.binaryLogicalAndExpression(f, n, t, mode, flags)
  6031  	default:
  6032  		panic(todo("%v: internal error: %v", n.Position(), n.Case))
  6033  	}
  6034  }
  6035  
  6036  func (p *project) logicalAndExpressionAddrOf(f *function, n *cc.LogicalAndExpression, t cc.Type, mode exprMode, flags flags) {
  6037  	switch n.Case {
  6038  	case cc.LogicalAndExpressionOr: // InclusiveOrExpression
  6039  		p.inclusiveOrExpression(f, n.InclusiveOrExpression, t, mode, flags)
  6040  	case cc.LogicalAndExpressionLAnd: // LogicalAndExpression "&&" InclusiveOrExpression
  6041  		panic(todo("", p.pos(n)))
  6042  	default:
  6043  		panic(todo("%v: internal error: %v", n.Position(), n.Case))
  6044  	}
  6045  }
  6046  
  6047  func (p *project) logicalAndExpressionVoid(f *function, n *cc.LogicalAndExpression, t cc.Type, mode exprMode, flags flags) {
  6048  	switch n.Case {
  6049  	case cc.LogicalAndExpressionOr: // InclusiveOrExpression
  6050  		p.inclusiveOrExpression(f, n.InclusiveOrExpression, t, mode, flags)
  6051  	case cc.LogicalAndExpressionLAnd: // LogicalAndExpression "&&" InclusiveOrExpression
  6052  		p.binaryLogicalAndExpressionValue(f, n, t, mode, flags)
  6053  	default:
  6054  		panic(todo("%v: internal error: %v", n.Position(), n.Case))
  6055  	}
  6056  }
  6057  
  6058  func (p *project) logicalAndExpressionValue(f *function, n *cc.LogicalAndExpression, t cc.Type, mode exprMode, flags flags) {
  6059  	switch n.Case {
  6060  	case cc.LogicalAndExpressionOr: // InclusiveOrExpression
  6061  		p.inclusiveOrExpression(f, n.InclusiveOrExpression, t, mode, flags)
  6062  	case cc.LogicalAndExpressionLAnd: // LogicalAndExpression "&&" InclusiveOrExpression
  6063  		p.binaryLogicalAndExpression(f, n, t, mode, flags)
  6064  	default:
  6065  		panic(todo("%v: internal error: %v", n.Position(), n.Case))
  6066  	}
  6067  }
  6068  
  6069  func (p *project) binaryLogicalAndExpression(f *function, n *cc.LogicalAndExpression, t cc.Type, mode exprMode, flags flags) {
  6070  	switch mode {
  6071  	case exprBool:
  6072  		p.binaryLogicalAndExpressionBool(f, n, t, mode, flags)
  6073  	case exprValue:
  6074  		p.binaryLogicalAndExpressionValue(f, n, t, mode, flags)
  6075  	default:
  6076  		panic(todo("", n.Position(), mode))
  6077  	}
  6078  }
  6079  
  6080  func (p *project) binaryLogicalAndExpressionValue(f *function, n *cc.LogicalAndExpression, t cc.Type, mode exprMode, flags flags) {
  6081  	defer p.w("%s", p.booleanBinaryExpression(n, n.Operand, t, &mode, flags))
  6082  	p.logicalAndExpression(f, n.LogicalAndExpression, n.LogicalAndExpression.Operand.Type(), exprBool, flags)
  6083  	p.w(" &&%s", tidyComment(" ", &n.Token))
  6084  	p.inclusiveOrExpression(f, n.InclusiveOrExpression, n.InclusiveOrExpression.Operand.Type(), exprBool, flags)
  6085  }
  6086  
  6087  func (p *project) binaryLogicalAndExpressionBool(f *function, n *cc.LogicalAndExpression, t cc.Type, mode exprMode, flags flags) {
  6088  	defer p.w("%s", p.booleanBinaryExpression(n, n.Operand, t, &mode, flags))
  6089  	p.logicalAndExpression(f, n.LogicalAndExpression, n.LogicalAndExpression.Operand.Type(), exprBool, flags)
  6090  	p.w(" &&%s", tidyComment(" ", &n.Token))
  6091  	p.inclusiveOrExpression(f, n.InclusiveOrExpression, n.InclusiveOrExpression.Operand.Type(), exprBool, flags)
  6092  }
  6093  
  6094  func (p *project) inclusiveOrExpression(f *function, n *cc.InclusiveOrExpression, t cc.Type, mode exprMode, flags flags) {
  6095  	switch mode {
  6096  	case exprValue:
  6097  		p.inclusiveOrExpressionValue(f, n, t, mode, flags)
  6098  	case exprVoid:
  6099  		p.inclusiveOrExpressionVoid(f, n, t, mode, flags)
  6100  	case exprAddrOf:
  6101  		p.inclusiveOrExpressionAddrof(f, n, t, mode, flags)
  6102  	case exprBool:
  6103  		p.inclusiveOrExpressionBool(f, n, t, mode, flags)
  6104  	case exprLValue:
  6105  		p.inclusiveOrExpressionLValue(f, n, t, mode, flags)
  6106  	case exprPSelect:
  6107  		p.inclusiveOrExpressionPSelect(f, n, t, mode, flags)
  6108  	case exprFunc:
  6109  		p.inclusiveOrExpressionFunc(f, n, t, mode, flags)
  6110  	case exprSelect:
  6111  		p.inclusiveOrExpressionSelect(f, n, t, mode, flags)
  6112  	case exprDecay:
  6113  		p.inclusiveOrExpressionDecay(f, n, t, mode, flags)
  6114  	default:
  6115  		panic(todo("", n.Position(), mode))
  6116  	}
  6117  }
  6118  
  6119  func (p *project) inclusiveOrExpressionDecay(f *function, n *cc.InclusiveOrExpression, t cc.Type, mode exprMode, flags flags) {
  6120  	switch n.Case {
  6121  	case cc.InclusiveOrExpressionXor: // ExclusiveOrExpression
  6122  		p.exclusiveOrExpression(f, n.ExclusiveOrExpression, t, mode, flags)
  6123  	case cc.InclusiveOrExpressionOr: // InclusiveOrExpression '|' ExclusiveOrExpression
  6124  		panic(todo("", p.pos(n)))
  6125  	default:
  6126  		panic(todo("%v: internal error: %v", n.Position(), n.Case))
  6127  	}
  6128  }
  6129  
  6130  func (p *project) inclusiveOrExpressionSelect(f *function, n *cc.InclusiveOrExpression, t cc.Type, mode exprMode, flags flags) {
  6131  	switch n.Case {
  6132  	case cc.InclusiveOrExpressionXor: // ExclusiveOrExpression
  6133  		p.exclusiveOrExpression(f, n.ExclusiveOrExpression, t, mode, flags)
  6134  	case cc.InclusiveOrExpressionOr: // InclusiveOrExpression '|' ExclusiveOrExpression
  6135  		panic(todo("", p.pos(n)))
  6136  	default:
  6137  		panic(todo("%v: internal error: %v", n.Position(), n.Case))
  6138  	}
  6139  }
  6140  
  6141  func (p *project) inclusiveOrExpressionFunc(f *function, n *cc.InclusiveOrExpression, t cc.Type, mode exprMode, flags flags) {
  6142  	switch n.Case {
  6143  	case cc.InclusiveOrExpressionXor: // ExclusiveOrExpression
  6144  		p.exclusiveOrExpression(f, n.ExclusiveOrExpression, t, mode, flags)
  6145  	case cc.InclusiveOrExpressionOr: // InclusiveOrExpression '|' ExclusiveOrExpression
  6146  		panic(todo("", p.pos(n)))
  6147  	default:
  6148  		panic(todo("%v: internal error: %v", n.Position(), n.Case))
  6149  	}
  6150  }
  6151  
  6152  func (p *project) inclusiveOrExpressionPSelect(f *function, n *cc.InclusiveOrExpression, t cc.Type, mode exprMode, flags flags) {
  6153  	switch n.Case {
  6154  	case cc.InclusiveOrExpressionXor: // ExclusiveOrExpression
  6155  		p.exclusiveOrExpression(f, n.ExclusiveOrExpression, t, mode, flags)
  6156  	case cc.InclusiveOrExpressionOr: // InclusiveOrExpression '|' ExclusiveOrExpression
  6157  		panic(todo("", p.pos(n)))
  6158  	default:
  6159  		panic(todo("%v: internal error: %v", n.Position(), n.Case))
  6160  	}
  6161  }
  6162  
  6163  func (p *project) inclusiveOrExpressionLValue(f *function, n *cc.InclusiveOrExpression, t cc.Type, mode exprMode, flags flags) {
  6164  	switch n.Case {
  6165  	case cc.InclusiveOrExpressionXor: // ExclusiveOrExpression
  6166  		p.exclusiveOrExpression(f, n.ExclusiveOrExpression, t, mode, flags)
  6167  	case cc.InclusiveOrExpressionOr: // InclusiveOrExpression '|' ExclusiveOrExpression
  6168  		panic(todo("", p.pos(n)))
  6169  	default:
  6170  		panic(todo("%v: internal error: %v", n.Position(), n.Case))
  6171  	}
  6172  }
  6173  
  6174  func (p *project) inclusiveOrExpressionBool(f *function, n *cc.InclusiveOrExpression, t cc.Type, mode exprMode, flags flags) {
  6175  	switch n.Case {
  6176  	case cc.InclusiveOrExpressionXor: // ExclusiveOrExpression
  6177  		p.exclusiveOrExpression(f, n.ExclusiveOrExpression, t, mode, flags)
  6178  	case cc.InclusiveOrExpressionOr: // InclusiveOrExpression '|' ExclusiveOrExpression
  6179  		p.binaryInclusiveOrExpression(f, n, t, mode, flags)
  6180  	default:
  6181  		panic(todo("%v: internal error: %v", n.Position(), n.Case))
  6182  	}
  6183  }
  6184  
  6185  func (p *project) inclusiveOrExpressionAddrof(f *function, n *cc.InclusiveOrExpression, t cc.Type, mode exprMode, flags flags) {
  6186  	switch n.Case {
  6187  	case cc.InclusiveOrExpressionXor: // ExclusiveOrExpression
  6188  		p.exclusiveOrExpression(f, n.ExclusiveOrExpression, t, mode, flags)
  6189  	case cc.InclusiveOrExpressionOr: // InclusiveOrExpression '|' ExclusiveOrExpression
  6190  		panic(todo("", p.pos(n)))
  6191  	default:
  6192  		panic(todo("%v: internal error: %v", n.Position(), n.Case))
  6193  	}
  6194  }
  6195  
  6196  func (p *project) inclusiveOrExpressionVoid(f *function, n *cc.InclusiveOrExpression, t cc.Type, mode exprMode, flags flags) {
  6197  	switch n.Case {
  6198  	case cc.InclusiveOrExpressionXor: // ExclusiveOrExpression
  6199  		p.exclusiveOrExpression(f, n.ExclusiveOrExpression, t, mode, flags)
  6200  	case cc.InclusiveOrExpressionOr: // InclusiveOrExpression '|' ExclusiveOrExpression
  6201  		p.w("_ = ")
  6202  		p.inclusiveOrExpression(f, n, n.Operand.Type(), exprValue, flags)
  6203  	default:
  6204  		panic(todo("%v: internal error: %v", n.Position(), n.Case))
  6205  	}
  6206  }
  6207  
  6208  func (p *project) inclusiveOrExpressionValue(f *function, n *cc.InclusiveOrExpression, t cc.Type, mode exprMode, flags flags) {
  6209  	switch n.Case {
  6210  	case cc.InclusiveOrExpressionXor: // ExclusiveOrExpression
  6211  		p.exclusiveOrExpression(f, n.ExclusiveOrExpression, t, mode, flags)
  6212  	case cc.InclusiveOrExpressionOr: // InclusiveOrExpression '|' ExclusiveOrExpression
  6213  		p.binaryInclusiveOrExpression(f, n, t, mode, flags)
  6214  	default:
  6215  		panic(todo("%v: internal error: %v", n.Position(), n.Case))
  6216  	}
  6217  }
  6218  
  6219  func (p *project) binaryInclusiveOrExpression(f *function, n *cc.InclusiveOrExpression, t cc.Type, mode exprMode, flags flags) {
  6220  	// InclusiveOrExpression '|' ExclusiveOrExpression
  6221  	switch mode {
  6222  	case exprBool:
  6223  		p.binaryInclusiveOrExpressionBool(f, n, t, mode, flags)
  6224  	case exprValue:
  6225  		p.binaryInclusiveOrExpressionValue(f, n, t, mode, flags)
  6226  	default:
  6227  		panic(todo("", n.Position(), mode))
  6228  	}
  6229  }
  6230  
  6231  func (p *project) binaryInclusiveOrExpressionValue(f *function, n *cc.InclusiveOrExpression, t cc.Type, mode exprMode, flags flags) {
  6232  	// InclusiveOrExpression '|' ExclusiveOrExpression
  6233  
  6234  	lt := n.InclusiveOrExpression.Operand.Type()
  6235  	rt := n.ExclusiveOrExpression.Operand.Type()
  6236  	switch lk, rk := lt.Kind(), rt.Kind(); {
  6237  	case
  6238  		lk == cc.UInt128 || rk == cc.UInt128,
  6239  		lk == cc.Int128 || rk == cc.Int128:
  6240  
  6241  		p.binaryOrExpressionUint128(f, n, t, mode, flags)
  6242  		return
  6243  	}
  6244  
  6245  	defer p.w("%s", p.artithmeticBinaryExpression(n, n.Operand, t, &mode, flags))
  6246  	switch {
  6247  	case orOverflows(n.InclusiveOrExpression.Operand, n.ExclusiveOrExpression.Operand, n.Promote()):
  6248  		p.inclusiveOrExpression(f, n.InclusiveOrExpression, n.Promote(), exprValue, flags)
  6249  		p.w(" |%s", tidyComment(" ", &n.Token))
  6250  		p.exclusiveOrExpression(f, n.ExclusiveOrExpression, n.Promote(), exprValue, flags|fForceRuntimeConv)
  6251  	default:
  6252  		p.inclusiveOrExpression(f, n.InclusiveOrExpression, n.Promote(), exprValue, flags)
  6253  		p.w(" |%s", tidyComment(" ", &n.Token))
  6254  		p.exclusiveOrExpression(f, n.ExclusiveOrExpression, n.Promote(), exprValue, flags)
  6255  	}
  6256  }
  6257  
  6258  func (p *project) binaryOrExpressionUint128(f *function, n *cc.InclusiveOrExpression, t cc.Type, mode exprMode, flags flags) {
  6259  	// InclusiveOrExpression '|' ExclusiveOrExpression
  6260  	defer p.w("%s", p.artithmeticBinaryExpression(n, n.Operand, t, &mode, flags))
  6261  	p.inclusiveOrExpression(f, n.InclusiveOrExpression, n.Promote(), exprValue, flags)
  6262  	p.w(".Or(")
  6263  	p.exclusiveOrExpression(f, n.ExclusiveOrExpression, n.Promote(), exprValue, flags)
  6264  	p.w(")")
  6265  }
  6266  
  6267  func (p *project) binaryInclusiveOrExpressionBool(f *function, n *cc.InclusiveOrExpression, t cc.Type, mode exprMode, flags flags) {
  6268  	defer p.w("%s", p.artithmeticBinaryExpression(n, n.Operand, t, &mode, flags))
  6269  	switch {
  6270  	case orOverflows(n.InclusiveOrExpression.Operand, n.ExclusiveOrExpression.Operand, n.Promote()):
  6271  		p.inclusiveOrExpression(f, n.InclusiveOrExpression, n.Promote(), exprValue, flags)
  6272  		p.w(" |%s", tidyComment(" ", &n.Token))
  6273  		p.exclusiveOrExpression(f, n.ExclusiveOrExpression, n.Promote(), exprValue, flags|fForceRuntimeConv)
  6274  	default:
  6275  		p.inclusiveOrExpression(f, n.InclusiveOrExpression, n.Promote(), exprValue, flags)
  6276  		p.w(" |%s", tidyComment(" ", &n.Token))
  6277  		p.exclusiveOrExpression(f, n.ExclusiveOrExpression, n.Promote(), exprValue, flags)
  6278  	}
  6279  }
  6280  
  6281  func orOverflows(lo, ro cc.Operand, promote cc.Type) bool {
  6282  	a, b, ok := getIntOperands(lo, ro)
  6283  	if !ok {
  6284  		return false
  6285  	}
  6286  
  6287  	return overflows(a.Or(a, b), promote)
  6288  }
  6289  
  6290  func (p *project) artithmeticBinaryExpression(n cc.Node, from cc.Operand, to cc.Type, mode *exprMode, flags flags) (r string) {
  6291  	p.w("(")
  6292  	r = ")"
  6293  	switch *mode {
  6294  	case exprBool:
  6295  		p.w("(")
  6296  		r = ") != 0" + r
  6297  		*mode = exprValue
  6298  	default:
  6299  		switch fk, tk := from.Type().Kind(), to.Kind(); {
  6300  		case fk != tk && fk == cc.Int128:
  6301  			return fmt.Sprintf(".%s()%s", p.helperType(n, to), r)
  6302  		case fk != tk && fk == cc.UInt128:
  6303  			return fmt.Sprintf(".%s()%s", p.helperType(n, to), r)
  6304  		default:
  6305  			r = p.convert(n, from, to, flags) + r
  6306  		}
  6307  	}
  6308  	return r
  6309  }
  6310  
  6311  func (p *project) exclusiveOrExpression(f *function, n *cc.ExclusiveOrExpression, t cc.Type, mode exprMode, flags flags) {
  6312  	switch mode {
  6313  	case exprValue:
  6314  		p.exclusiveOrExpressionValue(f, n, t, mode, flags)
  6315  	case exprVoid:
  6316  		p.exclusiveOrExpressionVoid(f, n, t, mode, flags)
  6317  	case exprAddrOf:
  6318  		p.exclusiveOrExpressionAddrOf(f, n, t, mode, flags)
  6319  	case exprBool:
  6320  		p.exclusiveOrExpressionBool(f, n, t, mode, flags)
  6321  	case exprLValue:
  6322  		p.exclusiveOrExpressionLValue(f, n, t, mode, flags)
  6323  	case exprPSelect:
  6324  		p.exclusiveOrExpressionPSelect(f, n, t, mode, flags)
  6325  	case exprFunc:
  6326  		p.exclusiveOrExpressionFunc(f, n, t, mode, flags)
  6327  	case exprSelect:
  6328  		p.exclusiveOrExpressionSelect(f, n, t, mode, flags)
  6329  	case exprDecay:
  6330  		p.exclusiveOrExpressionDecay(f, n, t, mode, flags)
  6331  	default:
  6332  		panic(todo("", n.Position(), mode))
  6333  	}
  6334  }
  6335  
  6336  func (p *project) exclusiveOrExpressionDecay(f *function, n *cc.ExclusiveOrExpression, t cc.Type, mode exprMode, flags flags) {
  6337  	switch n.Case {
  6338  	case cc.ExclusiveOrExpressionAnd: // AndExpression
  6339  		p.andExpression(f, n.AndExpression, t, mode, flags)
  6340  	case cc.ExclusiveOrExpressionXor: // ExclusiveOrExpression '^' AndExpression
  6341  		panic(todo("", p.pos(n)))
  6342  	default:
  6343  		panic(todo("%v: internal error: %v", n.Position(), n.Case))
  6344  	}
  6345  }
  6346  
  6347  func (p *project) exclusiveOrExpressionSelect(f *function, n *cc.ExclusiveOrExpression, t cc.Type, mode exprMode, flags flags) {
  6348  	switch n.Case {
  6349  	case cc.ExclusiveOrExpressionAnd: // AndExpression
  6350  		p.andExpression(f, n.AndExpression, t, mode, flags)
  6351  	case cc.ExclusiveOrExpressionXor: // ExclusiveOrExpression '^' AndExpression
  6352  		panic(todo("", p.pos(n)))
  6353  	default:
  6354  		panic(todo("%v: internal error: %v", n.Position(), n.Case))
  6355  	}
  6356  }
  6357  
  6358  func (p *project) exclusiveOrExpressionFunc(f *function, n *cc.ExclusiveOrExpression, t cc.Type, mode exprMode, flags flags) {
  6359  	switch n.Case {
  6360  	case cc.ExclusiveOrExpressionAnd: // AndExpression
  6361  		p.andExpression(f, n.AndExpression, t, mode, flags)
  6362  	case cc.ExclusiveOrExpressionXor: // ExclusiveOrExpression '^' AndExpression
  6363  		panic(todo("", p.pos(n)))
  6364  	default:
  6365  		panic(todo("%v: internal error: %v", n.Position(), n.Case))
  6366  	}
  6367  }
  6368  
  6369  func (p *project) exclusiveOrExpressionPSelect(f *function, n *cc.ExclusiveOrExpression, t cc.Type, mode exprMode, flags flags) {
  6370  	switch n.Case {
  6371  	case cc.ExclusiveOrExpressionAnd: // AndExpression
  6372  		p.andExpression(f, n.AndExpression, t, mode, flags)
  6373  	case cc.ExclusiveOrExpressionXor: // ExclusiveOrExpression '^' AndExpression
  6374  		panic(todo("", p.pos(n)))
  6375  	default:
  6376  		panic(todo("%v: internal error: %v", n.Position(), n.Case))
  6377  	}
  6378  }
  6379  
  6380  func (p *project) exclusiveOrExpressionLValue(f *function, n *cc.ExclusiveOrExpression, t cc.Type, mode exprMode, flags flags) {
  6381  	switch n.Case {
  6382  	case cc.ExclusiveOrExpressionAnd: // AndExpression
  6383  		p.andExpression(f, n.AndExpression, t, mode, flags)
  6384  	case cc.ExclusiveOrExpressionXor: // ExclusiveOrExpression '^' AndExpression
  6385  		panic(todo("", p.pos(n)))
  6386  	default:
  6387  		panic(todo("%v: internal error: %v", n.Position(), n.Case))
  6388  	}
  6389  }
  6390  
  6391  func (p *project) exclusiveOrExpressionBool(f *function, n *cc.ExclusiveOrExpression, t cc.Type, mode exprMode, flags flags) {
  6392  	switch n.Case {
  6393  	case cc.ExclusiveOrExpressionAnd: // AndExpression
  6394  		p.andExpression(f, n.AndExpression, t, mode, flags)
  6395  	case cc.ExclusiveOrExpressionXor: // ExclusiveOrExpression '^' AndExpression
  6396  		p.binaryExclusiveOrExpression(f, n, t, mode, flags)
  6397  	default:
  6398  		panic(todo("%v: internal error: %v", n.Position(), n.Case))
  6399  	}
  6400  }
  6401  
  6402  func (p *project) exclusiveOrExpressionAddrOf(f *function, n *cc.ExclusiveOrExpression, t cc.Type, mode exprMode, flags flags) {
  6403  	switch n.Case {
  6404  	case cc.ExclusiveOrExpressionAnd: // AndExpression
  6405  		p.andExpression(f, n.AndExpression, t, mode, flags)
  6406  	case cc.ExclusiveOrExpressionXor: // ExclusiveOrExpression '^' AndExpression
  6407  		panic(todo("", p.pos(n)))
  6408  	default:
  6409  		panic(todo("%v: internal error: %v", n.Position(), n.Case))
  6410  	}
  6411  }
  6412  
  6413  func (p *project) exclusiveOrExpressionVoid(f *function, n *cc.ExclusiveOrExpression, t cc.Type, mode exprMode, flags flags) {
  6414  	switch n.Case {
  6415  	case cc.ExclusiveOrExpressionAnd: // AndExpression
  6416  		p.andExpression(f, n.AndExpression, t, mode, flags)
  6417  	case cc.ExclusiveOrExpressionXor: // ExclusiveOrExpression '^' AndExpression
  6418  		p.w("_ = ")
  6419  		p.exclusiveOrExpression(f, n, n.Operand.Type(), exprValue, flags)
  6420  	default:
  6421  		panic(todo("%v: internal error: %v", n.Position(), n.Case))
  6422  	}
  6423  }
  6424  
  6425  func (p *project) exclusiveOrExpressionValue(f *function, n *cc.ExclusiveOrExpression, t cc.Type, mode exprMode, flags flags) {
  6426  	switch n.Case {
  6427  	case cc.ExclusiveOrExpressionAnd: // AndExpression
  6428  		p.andExpression(f, n.AndExpression, t, mode, flags)
  6429  	case cc.ExclusiveOrExpressionXor: // ExclusiveOrExpression '^' AndExpression
  6430  		p.binaryExclusiveOrExpression(f, n, t, mode, flags)
  6431  	default:
  6432  		panic(todo("%v: internal error: %v", n.Position(), n.Case))
  6433  	}
  6434  }
  6435  
  6436  func (p *project) binaryExclusiveOrExpression(f *function, n *cc.ExclusiveOrExpression, t cc.Type, mode exprMode, flags flags) {
  6437  	// ExclusiveOrExpression '^' AndExpression
  6438  	switch mode {
  6439  	case exprValue, exprBool:
  6440  		p.binaryExclusiveOrExpressionValue(f, n, t, mode, flags)
  6441  	default:
  6442  		panic(todo("", n.Position(), mode))
  6443  	}
  6444  }
  6445  
  6446  func (p *project) binaryExclusiveOrExpressionValue(f *function, n *cc.ExclusiveOrExpression, t cc.Type, mode exprMode, flags flags) {
  6447  	// ExclusiveOrExpression '^' AndExpression
  6448  
  6449  	lt := n.ExclusiveOrExpression.Operand.Type()
  6450  	rt := n.AndExpression.Operand.Type()
  6451  	switch lk, rk := lt.Kind(), rt.Kind(); {
  6452  	case
  6453  		lk == cc.UInt128 || rk == cc.UInt128,
  6454  		lk == cc.Int128 || rk == cc.Int128:
  6455  
  6456  		p.binaryExclusiveOrExpressionUint128(f, n, t, mode, flags)
  6457  		return
  6458  	}
  6459  
  6460  	defer p.w("%s", p.artithmeticBinaryExpression(n, n.Operand, t, &mode, flags))
  6461  	switch {
  6462  	case xorOverflows(n.ExclusiveOrExpression.Operand, n.AndExpression.Operand, n.Promote()):
  6463  		p.exclusiveOrExpression(f, n.ExclusiveOrExpression, n.Promote(), exprValue, flags)
  6464  		p.w(" ^%s", tidyComment(" ", &n.Token))
  6465  		p.andExpression(f, n.AndExpression, n.Promote(), exprValue, flags|fForceRuntimeConv)
  6466  	default:
  6467  		p.exclusiveOrExpression(f, n.ExclusiveOrExpression, n.Promote(), exprValue, flags)
  6468  		p.w(" ^%s", tidyComment(" ", &n.Token))
  6469  		p.andExpression(f, n.AndExpression, n.Promote(), exprValue, flags)
  6470  	}
  6471  }
  6472  
  6473  func (p *project) binaryExclusiveOrExpressionUint128(f *function, n *cc.ExclusiveOrExpression, t cc.Type, mode exprMode, flags flags) {
  6474  	// ExclusiveOrExpression '^' AndExpression
  6475  	defer p.w("%s", p.artithmeticBinaryExpression(n, n.Operand, t, &mode, flags))
  6476  	p.exclusiveOrExpression(f, n.ExclusiveOrExpression, n.Promote(), exprValue, flags)
  6477  	p.w(".Xor(")
  6478  	p.andExpression(f, n.AndExpression, n.Promote(), exprValue, flags)
  6479  	p.w(")")
  6480  }
  6481  
  6482  func xorOverflows(lo, ro cc.Operand, promote cc.Type) bool {
  6483  	a, b, ok := getIntOperands(lo, ro)
  6484  	if !ok {
  6485  		return false
  6486  	}
  6487  
  6488  	return !lo.Type().IsSignedType() && a.Sign() == 0 ||
  6489  		!ro.Type().IsSignedType() && b.Sign() == 0 ||
  6490  		overflows(a.Xor(a, b), promote)
  6491  }
  6492  
  6493  func (p *project) andExpression(f *function, n *cc.AndExpression, t cc.Type, mode exprMode, flags flags) {
  6494  	switch mode {
  6495  	case exprValue:
  6496  		p.andExpressionValue(f, n, t, mode, flags)
  6497  	case exprVoid:
  6498  		p.andExpressionVoid(f, n, t, mode, flags)
  6499  	case exprAddrOf:
  6500  		p.andExpressionAddrof(f, n, t, mode, flags)
  6501  	case exprBool:
  6502  		p.andExpressionBool(f, n, t, mode, flags)
  6503  	case exprLValue:
  6504  		p.andExpressionLValue(f, n, t, mode, flags)
  6505  	case exprPSelect:
  6506  		p.andExpressionPSelect(f, n, t, mode, flags)
  6507  	case exprFunc:
  6508  		p.andExpressionFunc(f, n, t, mode, flags)
  6509  	case exprSelect:
  6510  		p.andExpressionSelect(f, n, t, mode, flags)
  6511  	case exprDecay:
  6512  		p.andExpressionDecay(f, n, t, mode, flags)
  6513  	default:
  6514  		panic(todo("", n.Position(), mode))
  6515  	}
  6516  }
  6517  
  6518  func (p *project) andExpressionDecay(f *function, n *cc.AndExpression, t cc.Type, mode exprMode, flags flags) {
  6519  	switch n.Case {
  6520  	case cc.AndExpressionEq: // EqualityExpression
  6521  		p.equalityExpression(f, n.EqualityExpression, t, mode, flags)
  6522  	case cc.AndExpressionAnd: // AndExpression '&' EqualityExpression
  6523  		panic(todo("", p.pos(n)))
  6524  	default:
  6525  		panic(todo("%v: internal error: %v", n.Position(), n.Case))
  6526  	}
  6527  }
  6528  
  6529  func (p *project) andExpressionSelect(f *function, n *cc.AndExpression, t cc.Type, mode exprMode, flags flags) {
  6530  	switch n.Case {
  6531  	case cc.AndExpressionEq: // EqualityExpression
  6532  		p.equalityExpression(f, n.EqualityExpression, t, mode, flags)
  6533  	case cc.AndExpressionAnd: // AndExpression '&' EqualityExpression
  6534  		panic(todo("", p.pos(n)))
  6535  	default:
  6536  		panic(todo("%v: internal error: %v", n.Position(), n.Case))
  6537  	}
  6538  }
  6539  
  6540  func (p *project) andExpressionFunc(f *function, n *cc.AndExpression, t cc.Type, mode exprMode, flags flags) {
  6541  	switch n.Case {
  6542  	case cc.AndExpressionEq: // EqualityExpression
  6543  		p.equalityExpression(f, n.EqualityExpression, t, mode, flags)
  6544  	case cc.AndExpressionAnd: // AndExpression '&' EqualityExpression
  6545  		panic(todo("", p.pos(n)))
  6546  	default:
  6547  		panic(todo("%v: internal error: %v", n.Position(), n.Case))
  6548  	}
  6549  }
  6550  
  6551  func (p *project) andExpressionPSelect(f *function, n *cc.AndExpression, t cc.Type, mode exprMode, flags flags) {
  6552  	switch n.Case {
  6553  	case cc.AndExpressionEq: // EqualityExpression
  6554  		p.equalityExpression(f, n.EqualityExpression, t, mode, flags)
  6555  	case cc.AndExpressionAnd: // AndExpression '&' EqualityExpression
  6556  		panic(todo("", p.pos(n)))
  6557  	default:
  6558  		panic(todo("%v: internal error: %v", n.Position(), n.Case))
  6559  	}
  6560  }
  6561  
  6562  func (p *project) andExpressionLValue(f *function, n *cc.AndExpression, t cc.Type, mode exprMode, flags flags) {
  6563  	switch n.Case {
  6564  	case cc.AndExpressionEq: // EqualityExpression
  6565  		p.equalityExpression(f, n.EqualityExpression, t, mode, flags)
  6566  	case cc.AndExpressionAnd: // AndExpression '&' EqualityExpression
  6567  		panic(todo("", p.pos(n)))
  6568  	default:
  6569  		panic(todo("%v: internal error: %v", n.Position(), n.Case))
  6570  	}
  6571  }
  6572  
  6573  func (p *project) andExpressionBool(f *function, n *cc.AndExpression, t cc.Type, mode exprMode, flags flags) {
  6574  	switch n.Case {
  6575  	case cc.AndExpressionEq: // EqualityExpression
  6576  		p.equalityExpression(f, n.EqualityExpression, t, mode, flags)
  6577  	case cc.AndExpressionAnd: // AndExpression '&' EqualityExpression
  6578  		p.binaryAndExpression(f, n, t, mode, flags)
  6579  	default:
  6580  		panic(todo("%v: internal error: %v", n.Position(), n.Case))
  6581  	}
  6582  }
  6583  
  6584  func (p *project) andExpressionAddrof(f *function, n *cc.AndExpression, t cc.Type, mode exprMode, flags flags) {
  6585  	switch n.Case {
  6586  	case cc.AndExpressionEq: // EqualityExpression
  6587  		p.equalityExpression(f, n.EqualityExpression, t, mode, flags)
  6588  	case cc.AndExpressionAnd: // AndExpression '&' EqualityExpression
  6589  		panic(todo("", p.pos(n)))
  6590  	default:
  6591  		panic(todo("%v: internal error: %v", n.Position(), n.Case))
  6592  	}
  6593  }
  6594  
  6595  func (p *project) andExpressionVoid(f *function, n *cc.AndExpression, t cc.Type, mode exprMode, flags flags) {
  6596  	switch n.Case {
  6597  	case cc.AndExpressionEq: // EqualityExpression
  6598  		p.equalityExpression(f, n.EqualityExpression, t, mode, flags)
  6599  	case cc.AndExpressionAnd: // AndExpression '&' EqualityExpression
  6600  		p.w("_ = ")
  6601  		p.andExpression(f, n, n.Operand.Type(), exprValue, flags)
  6602  	default:
  6603  		panic(todo("%v: internal error: %v", n.Position(), n.Case))
  6604  	}
  6605  }
  6606  
  6607  func (p *project) andExpressionValue(f *function, n *cc.AndExpression, t cc.Type, mode exprMode, flags flags) {
  6608  	switch n.Case {
  6609  	case cc.AndExpressionEq: // EqualityExpression
  6610  		p.equalityExpression(f, n.EqualityExpression, t, mode, flags)
  6611  	case cc.AndExpressionAnd: // AndExpression '&' EqualityExpression
  6612  		p.binaryAndExpression(f, n, t, mode, flags)
  6613  	default:
  6614  		panic(todo("%v: internal error: %v", n.Position(), n.Case))
  6615  	}
  6616  }
  6617  
  6618  func (p *project) binaryAndExpression(f *function, n *cc.AndExpression, t cc.Type, mode exprMode, flags flags) {
  6619  	// AndExpression '&' EqualityExpression
  6620  	switch mode {
  6621  	case exprValue:
  6622  		p.binaryAndExpressionValue(f, n, t, mode, flags)
  6623  	case exprBool:
  6624  		p.binaryAndExpressionBool(f, n, t, mode, flags)
  6625  	default:
  6626  		panic(todo("", n.Position(), mode))
  6627  	}
  6628  }
  6629  
  6630  func (p *project) binaryAndExpressionBool(f *function, n *cc.AndExpression, t cc.Type, mode exprMode, flags flags) {
  6631  	defer p.w("%s", p.artithmeticBinaryExpression(n, n.Operand, n.Operand.Type(), &mode, flags))
  6632  	switch {
  6633  	case andOverflows(n.AndExpression.Operand, n.EqualityExpression.Operand, n.Promote()):
  6634  		p.andExpression(f, n.AndExpression, n.Promote(), exprValue, flags)
  6635  		p.w(" &%s", tidyComment(" ", &n.Token))
  6636  		p.equalityExpression(f, n.EqualityExpression, n.Promote(), exprValue, flags|fForceRuntimeConv)
  6637  	default:
  6638  		p.andExpression(f, n.AndExpression, n.Promote(), exprValue, flags)
  6639  		p.w(" &%s", tidyComment(" ", &n.Token))
  6640  		p.equalityExpression(f, n.EqualityExpression, n.Promote(), exprValue, flags)
  6641  	}
  6642  }
  6643  
  6644  func (p *project) binaryAndExpressionValue(f *function, n *cc.AndExpression, t cc.Type, mode exprMode, flags flags) {
  6645  	// AndExpression '&' EqualityExpression
  6646  
  6647  	lt := n.AndExpression.Operand.Type()
  6648  	rt := n.EqualityExpression.Operand.Type()
  6649  	switch lk, rk := lt.Kind(), rt.Kind(); {
  6650  	case
  6651  		lk == cc.UInt128 || rk == cc.UInt128,
  6652  		lk == cc.Int128 || rk == cc.Int128:
  6653  
  6654  		p.binaryAndExpressionUint128(f, n, t, mode, flags)
  6655  		return
  6656  	}
  6657  
  6658  	defer p.w("%s", p.artithmeticBinaryExpression(n, n.Operand, t, &mode, flags))
  6659  	switch {
  6660  	case andOverflows(n.AndExpression.Operand, n.EqualityExpression.Operand, n.Promote()):
  6661  		p.andExpression(f, n.AndExpression, n.Promote(), exprValue, flags)
  6662  		p.w(" &%s", tidyComment(" ", &n.Token))
  6663  		p.equalityExpression(f, n.EqualityExpression, n.Promote(), exprValue, flags|fForceRuntimeConv)
  6664  	default:
  6665  		p.andExpression(f, n.AndExpression, n.Promote(), exprValue, flags)
  6666  		p.w(" &%s", tidyComment(" ", &n.Token))
  6667  		p.equalityExpression(f, n.EqualityExpression, n.Promote(), exprValue, flags)
  6668  	}
  6669  }
  6670  
  6671  func (p *project) binaryAndExpressionUint128(f *function, n *cc.AndExpression, t cc.Type, mode exprMode, flags flags) {
  6672  	// AndExpression '&' EqualityExpression
  6673  	defer p.w("%s", p.artithmeticBinaryExpression(n, n.Operand, t, &mode, flags))
  6674  	p.andExpression(f, n.AndExpression, n.Promote(), exprValue, flags)
  6675  	p.w(".And(")
  6676  	p.equalityExpression(f, n.EqualityExpression, n.Promote(), exprValue, flags)
  6677  	p.w(")")
  6678  }
  6679  
  6680  func andOverflows(lo, ro cc.Operand, promote cc.Type) bool {
  6681  	a, b, ok := getIntOperands(lo, ro)
  6682  	if !ok {
  6683  		return false
  6684  	}
  6685  
  6686  	return overflows(a.And(a, b), promote)
  6687  }
  6688  
  6689  func (p *project) equalityExpression(f *function, n *cc.EqualityExpression, t cc.Type, mode exprMode, flags flags) {
  6690  	switch mode {
  6691  	case exprValue:
  6692  		p.equalityExpressionValue(f, n, t, mode, flags)
  6693  	case exprVoid:
  6694  		p.equalityExpressionVoid(f, n, t, mode, flags)
  6695  	case exprAddrOf:
  6696  		p.equalityExpressionAddrOf(f, n, t, mode, flags)
  6697  	case exprBool:
  6698  		p.equalityExpressionBool(f, n, t, mode, flags)
  6699  	case exprLValue:
  6700  		p.equalityExpressionLValue(f, n, t, mode, flags)
  6701  	case exprPSelect:
  6702  		p.equalityExpressionPSelect(f, n, t, mode, flags)
  6703  	case exprFunc:
  6704  		p.equalityExpressionFunc(f, n, t, mode, flags)
  6705  	case exprSelect:
  6706  		p.equalityExpressionSelect(f, n, t, mode, flags)
  6707  	case exprDecay:
  6708  		p.equalityExpressionDecay(f, n, t, mode, flags)
  6709  	default:
  6710  		panic(todo("", n.Position(), mode))
  6711  	}
  6712  }
  6713  
  6714  func (p *project) equalityExpressionDecay(f *function, n *cc.EqualityExpression, t cc.Type, mode exprMode, flags flags) {
  6715  	switch n.Case {
  6716  	case cc.EqualityExpressionRel: // RelationalExpression
  6717  		p.relationalExpression(f, n.RelationalExpression, t, mode, flags)
  6718  	case cc.EqualityExpressionEq: // EqualityExpression "==" RelationalExpression
  6719  		panic(todo("", p.pos(n)))
  6720  	case cc.EqualityExpressionNeq: // EqualityExpression "!=" RelationalExpression
  6721  		panic(todo("", p.pos(n)))
  6722  	default:
  6723  		panic(todo("%v: internal error: %v", n.Position(), n.Case))
  6724  	}
  6725  }
  6726  
  6727  func (p *project) equalityExpressionSelect(f *function, n *cc.EqualityExpression, t cc.Type, mode exprMode, flags flags) {
  6728  	switch n.Case {
  6729  	case cc.EqualityExpressionRel: // RelationalExpression
  6730  		p.relationalExpression(f, n.RelationalExpression, t, mode, flags)
  6731  	case cc.EqualityExpressionEq: // EqualityExpression "==" RelationalExpression
  6732  		panic(todo("", p.pos(n)))
  6733  	case cc.EqualityExpressionNeq: // EqualityExpression "!=" RelationalExpression
  6734  		panic(todo("", p.pos(n)))
  6735  	default:
  6736  		panic(todo("%v: internal error: %v", n.Position(), n.Case))
  6737  	}
  6738  }
  6739  
  6740  func (p *project) equalityExpressionFunc(f *function, n *cc.EqualityExpression, t cc.Type, mode exprMode, flags flags) {
  6741  	switch n.Case {
  6742  	case cc.EqualityExpressionRel: // RelationalExpression
  6743  		p.relationalExpression(f, n.RelationalExpression, t, mode, flags)
  6744  	case cc.EqualityExpressionEq: // EqualityExpression "==" RelationalExpression
  6745  		panic(todo("", p.pos(n)))
  6746  	case cc.EqualityExpressionNeq: // EqualityExpression "!=" RelationalExpression
  6747  		panic(todo("", p.pos(n)))
  6748  	default:
  6749  		panic(todo("%v: internal error: %v", n.Position(), n.Case))
  6750  	}
  6751  }
  6752  
  6753  func (p *project) equalityExpressionPSelect(f *function, n *cc.EqualityExpression, t cc.Type, mode exprMode, flags flags) {
  6754  	switch n.Case {
  6755  	case cc.EqualityExpressionRel: // RelationalExpression
  6756  		p.relationalExpression(f, n.RelationalExpression, t, mode, flags)
  6757  	case cc.EqualityExpressionEq: // EqualityExpression "==" RelationalExpression
  6758  		panic(todo("", p.pos(n)))
  6759  	case cc.EqualityExpressionNeq: // EqualityExpression "!=" RelationalExpression
  6760  		panic(todo("", p.pos(n)))
  6761  	default:
  6762  		panic(todo("%v: internal error: %v", n.Position(), n.Case))
  6763  	}
  6764  }
  6765  
  6766  func (p *project) equalityExpressionLValue(f *function, n *cc.EqualityExpression, t cc.Type, mode exprMode, flags flags) {
  6767  	switch n.Case {
  6768  	case cc.EqualityExpressionRel: // RelationalExpression
  6769  		p.relationalExpression(f, n.RelationalExpression, t, mode, flags)
  6770  	case cc.EqualityExpressionEq: // EqualityExpression "==" RelationalExpression
  6771  		panic(todo("", p.pos(n)))
  6772  	case cc.EqualityExpressionNeq: // EqualityExpression "!=" RelationalExpression
  6773  		panic(todo("", p.pos(n)))
  6774  	default:
  6775  		panic(todo("%v: internal error: %v", n.Position(), n.Case))
  6776  	}
  6777  }
  6778  
  6779  func (p *project) equalityExpressionBool(f *function, n *cc.EqualityExpression, t cc.Type, mode exprMode, flags flags) {
  6780  	switch n.Case {
  6781  	case cc.EqualityExpressionRel: // RelationalExpression
  6782  		p.relationalExpression(f, n.RelationalExpression, t, mode, flags)
  6783  	case cc.EqualityExpressionEq: // EqualityExpression "==" RelationalExpression
  6784  		p.binaryEqualityExpression(f, n, " == ", t, mode, flags)
  6785  	case cc.EqualityExpressionNeq: // EqualityExpression "!=" RelationalExpression
  6786  		p.binaryEqualityExpression(f, n, " != ", t, mode, flags)
  6787  	default:
  6788  		panic(todo("%v: internal error: %v", n.Position(), n.Case))
  6789  	}
  6790  }
  6791  
  6792  func (p *project) equalityExpressionAddrOf(f *function, n *cc.EqualityExpression, t cc.Type, mode exprMode, flags flags) {
  6793  	switch n.Case {
  6794  	case cc.EqualityExpressionRel: // RelationalExpression
  6795  		p.relationalExpression(f, n.RelationalExpression, t, mode, flags)
  6796  	case cc.EqualityExpressionEq: // EqualityExpression "==" RelationalExpression
  6797  		panic(todo("", p.pos(n)))
  6798  	case cc.EqualityExpressionNeq: // EqualityExpression "!=" RelationalExpression
  6799  		panic(todo("", p.pos(n)))
  6800  	default:
  6801  		panic(todo("%v: internal error: %v", n.Position(), n.Case))
  6802  	}
  6803  }
  6804  
  6805  func (p *project) equalityExpressionVoid(f *function, n *cc.EqualityExpression, t cc.Type, mode exprMode, flags flags) {
  6806  	switch n.Case {
  6807  	case cc.EqualityExpressionRel: // RelationalExpression
  6808  		p.relationalExpression(f, n.RelationalExpression, t, mode, flags)
  6809  	default:
  6810  		// case cc.EqualityExpressionEq: // EqualityExpression "==" RelationalExpression
  6811  		// case cc.EqualityExpressionNeq: // EqualityExpression "!=" RelationalExpression
  6812  		p.w("_ = ")
  6813  		p.equalityExpression(f, n, n.Operand.Type(), exprValue, flags)
  6814  	}
  6815  }
  6816  
  6817  func (p *project) equalityExpressionValue(f *function, n *cc.EqualityExpression, t cc.Type, mode exprMode, flags flags) {
  6818  	switch n.Case {
  6819  	case cc.EqualityExpressionRel: // RelationalExpression
  6820  		p.relationalExpression(f, n.RelationalExpression, t, mode, flags)
  6821  	case cc.EqualityExpressionEq: // EqualityExpression "==" RelationalExpression
  6822  		p.binaryEqualityExpression(f, n, " == ", t, mode, flags)
  6823  	case cc.EqualityExpressionNeq: // EqualityExpression "!=" RelationalExpression
  6824  		p.binaryEqualityExpression(f, n, " != ", t, mode, flags)
  6825  	default:
  6826  		panic(todo("%v: internal error: %v", n.Position(), n.Case))
  6827  	}
  6828  }
  6829  
  6830  func (p *project) binaryEqualityExpression(f *function, n *cc.EqualityExpression, oper string, t cc.Type, mode exprMode, flags flags) {
  6831  	switch mode {
  6832  	case exprValue:
  6833  		p.binaryEqualityExpressionValue(f, n, oper, t, mode, flags)
  6834  	case exprBool:
  6835  		p.binaryEqualityExpressionBool(f, n, oper, t, mode, flags)
  6836  	default:
  6837  		panic(todo("", n.Position(), mode))
  6838  	}
  6839  }
  6840  
  6841  func (p *project) binaryEqualityExpressionBool(f *function, n *cc.EqualityExpression, oper string, t cc.Type, mode exprMode, flags flags) {
  6842  	defer p.w("%s", p.booleanBinaryExpression(n, n.Operand, t, &mode, flags))
  6843  	p.equalityExpression(f, n.EqualityExpression, n.Promote(), exprValue, flags)
  6844  	p.w(" %s%s", oper, tidyComment(" ", &n.Token))
  6845  	p.relationalExpression(f, n.RelationalExpression, n.Promote(), exprValue, flags)
  6846  }
  6847  
  6848  func (p *project) binaryEqualityExpressionValue(f *function, n *cc.EqualityExpression, oper string, t cc.Type, mode exprMode, flags flags) {
  6849  	defer p.w("%s", p.booleanBinaryExpression(n, n.Operand, t, &mode, flags))
  6850  	p.equalityExpression(f, n.EqualityExpression, n.Promote(), exprValue, flags)
  6851  	p.w(" %s%s", oper, tidyComment(" ", &n.Token))
  6852  	p.relationalExpression(f, n.RelationalExpression, n.Promote(), exprValue, flags)
  6853  }
  6854  
  6855  func (p *project) relationalExpression(f *function, n *cc.RelationalExpression, t cc.Type, mode exprMode, flags flags) {
  6856  	switch mode {
  6857  	case exprValue:
  6858  		p.relationalExpressionValue(f, n, t, mode, flags)
  6859  	case exprVoid:
  6860  		p.relationalExpressionVoid(f, n, t, mode, flags)
  6861  	case exprAddrOf:
  6862  		p.relationalExpressionAddrOf(f, n, t, mode, flags)
  6863  	case exprBool:
  6864  		p.relationalExpressionBool(f, n, t, mode, flags)
  6865  	case exprLValue:
  6866  		p.relationalExpressionLValue(f, n, t, mode, flags)
  6867  	case exprPSelect:
  6868  		p.relationalExpressionPSelect(f, n, t, mode, flags)
  6869  	case exprFunc:
  6870  		p.relationalExpressionFunc(f, n, t, mode, flags)
  6871  	case exprSelect:
  6872  		p.relationalExpressionSelect(f, n, t, mode, flags)
  6873  	case exprDecay:
  6874  		p.relationalExpressionDecay(f, n, t, mode, flags)
  6875  	default:
  6876  		panic(todo("", n.Position(), mode))
  6877  	}
  6878  }
  6879  
  6880  func (p *project) relationalExpressionDecay(f *function, n *cc.RelationalExpression, t cc.Type, mode exprMode, flags flags) {
  6881  	switch n.Case {
  6882  	case cc.RelationalExpressionShift: // ShiftExpression
  6883  		p.shiftExpression(f, n.ShiftExpression, t, mode, flags)
  6884  	case cc.RelationalExpressionLt: // RelationalExpression '<' ShiftExpression
  6885  		panic(todo("", p.pos(n)))
  6886  	case cc.RelationalExpressionGt: // RelationalExpression '>' ShiftExpression
  6887  		panic(todo("", p.pos(n)))
  6888  	case cc.RelationalExpressionLeq: // RelationalExpression "<=" ShiftExpression
  6889  		panic(todo("", p.pos(n)))
  6890  	case cc.RelationalExpressionGeq: // RelationalExpression ">=" ShiftExpression
  6891  		panic(todo("", p.pos(n)))
  6892  	default:
  6893  		panic(todo("%v: internal error: %v", n.Position(), n.Case))
  6894  	}
  6895  }
  6896  
  6897  func (p *project) relationalExpressionSelect(f *function, n *cc.RelationalExpression, t cc.Type, mode exprMode, flags flags) {
  6898  	switch n.Case {
  6899  	case cc.RelationalExpressionShift: // ShiftExpression
  6900  		p.shiftExpression(f, n.ShiftExpression, t, mode, flags)
  6901  	case cc.RelationalExpressionLt: // RelationalExpression '<' ShiftExpression
  6902  		panic(todo("", p.pos(n)))
  6903  	case cc.RelationalExpressionGt: // RelationalExpression '>' ShiftExpression
  6904  		panic(todo("", p.pos(n)))
  6905  	case cc.RelationalExpressionLeq: // RelationalExpression "<=" ShiftExpression
  6906  		panic(todo("", p.pos(n)))
  6907  	case cc.RelationalExpressionGeq: // RelationalExpression ">=" ShiftExpression
  6908  		panic(todo("", p.pos(n)))
  6909  	default:
  6910  		panic(todo("%v: internal error: %v", n.Position(), n.Case))
  6911  	}
  6912  }
  6913  
  6914  func (p *project) relationalExpressionFunc(f *function, n *cc.RelationalExpression, t cc.Type, mode exprMode, flags flags) {
  6915  	switch n.Case {
  6916  	case cc.RelationalExpressionShift: // ShiftExpression
  6917  		p.shiftExpression(f, n.ShiftExpression, t, mode, flags)
  6918  	case cc.RelationalExpressionLt: // RelationalExpression '<' ShiftExpression
  6919  		panic(todo("", p.pos(n)))
  6920  	case cc.RelationalExpressionGt: // RelationalExpression '>' ShiftExpression
  6921  		panic(todo("", p.pos(n)))
  6922  	case cc.RelationalExpressionLeq: // RelationalExpression "<=" ShiftExpression
  6923  		panic(todo("", p.pos(n)))
  6924  	case cc.RelationalExpressionGeq: // RelationalExpression ">=" ShiftExpression
  6925  		panic(todo("", p.pos(n)))
  6926  	default:
  6927  		panic(todo("%v: internal error: %v", n.Position(), n.Case))
  6928  	}
  6929  }
  6930  
  6931  func (p *project) relationalExpressionPSelect(f *function, n *cc.RelationalExpression, t cc.Type, mode exprMode, flags flags) {
  6932  	switch n.Case {
  6933  	case cc.RelationalExpressionShift: // ShiftExpression
  6934  		p.shiftExpression(f, n.ShiftExpression, t, mode, flags)
  6935  	case cc.RelationalExpressionLt: // RelationalExpression '<' ShiftExpression
  6936  		panic(todo("", p.pos(n)))
  6937  	case cc.RelationalExpressionGt: // RelationalExpression '>' ShiftExpression
  6938  		panic(todo("", p.pos(n)))
  6939  	case cc.RelationalExpressionLeq: // RelationalExpression "<=" ShiftExpression
  6940  		panic(todo("", p.pos(n)))
  6941  	case cc.RelationalExpressionGeq: // RelationalExpression ">=" ShiftExpression
  6942  		panic(todo("", p.pos(n)))
  6943  	default:
  6944  		panic(todo("%v: internal error: %v", n.Position(), n.Case))
  6945  	}
  6946  }
  6947  
  6948  func (p *project) relationalExpressionLValue(f *function, n *cc.RelationalExpression, t cc.Type, mode exprMode, flags flags) {
  6949  	switch n.Case {
  6950  	case cc.RelationalExpressionShift: // ShiftExpression
  6951  		p.shiftExpression(f, n.ShiftExpression, t, mode, flags)
  6952  	case cc.RelationalExpressionLt: // RelationalExpression '<' ShiftExpression
  6953  		panic(todo("", p.pos(n)))
  6954  	case cc.RelationalExpressionGt: // RelationalExpression '>' ShiftExpression
  6955  		panic(todo("", p.pos(n)))
  6956  	case cc.RelationalExpressionLeq: // RelationalExpression "<=" ShiftExpression
  6957  		panic(todo("", p.pos(n)))
  6958  	case cc.RelationalExpressionGeq: // RelationalExpression ">=" ShiftExpression
  6959  		panic(todo("", p.pos(n)))
  6960  	default:
  6961  		panic(todo("%v: internal error: %v", n.Position(), n.Case))
  6962  	}
  6963  }
  6964  
  6965  func (p *project) relationalExpressionBool(f *function, n *cc.RelationalExpression, t cc.Type, mode exprMode, flags flags) {
  6966  	switch n.Case {
  6967  	case cc.RelationalExpressionShift: // ShiftExpression
  6968  		p.shiftExpression(f, n.ShiftExpression, t, mode, flags)
  6969  	case cc.RelationalExpressionLt: // RelationalExpression '<' ShiftExpression
  6970  		p.binaryRelationalExpression(f, n, " < ", t, mode, flags)
  6971  	case cc.RelationalExpressionGt: // RelationalExpression '>' ShiftExpression
  6972  		p.binaryRelationalExpression(f, n, " > ", t, mode, flags)
  6973  	case cc.RelationalExpressionLeq: // RelationalExpression "<=" ShiftExpression
  6974  		p.binaryRelationalExpression(f, n, " <= ", t, mode, flags)
  6975  	case cc.RelationalExpressionGeq: // RelationalExpression ">=" ShiftExpression
  6976  		p.binaryRelationalExpression(f, n, " >= ", t, mode, flags)
  6977  	default:
  6978  		panic(todo("%v: internal error: %v", n.Position(), n.Case))
  6979  	}
  6980  }
  6981  
  6982  func (p *project) relationalExpressionAddrOf(f *function, n *cc.RelationalExpression, t cc.Type, mode exprMode, flags flags) {
  6983  	switch n.Case {
  6984  	case cc.RelationalExpressionShift: // ShiftExpression
  6985  		p.shiftExpression(f, n.ShiftExpression, t, mode, flags)
  6986  	case cc.RelationalExpressionLt: // RelationalExpression '<' ShiftExpression
  6987  		panic(todo("", p.pos(n)))
  6988  	case cc.RelationalExpressionGt: // RelationalExpression '>' ShiftExpression
  6989  		panic(todo("", p.pos(n)))
  6990  	case cc.RelationalExpressionLeq: // RelationalExpression "<=" ShiftExpression
  6991  		panic(todo("", p.pos(n)))
  6992  	case cc.RelationalExpressionGeq: // RelationalExpression ">=" ShiftExpression
  6993  		panic(todo("", p.pos(n)))
  6994  	default:
  6995  		panic(todo("%v: internal error: %v", n.Position(), n.Case))
  6996  	}
  6997  }
  6998  
  6999  func (p *project) relationalExpressionVoid(f *function, n *cc.RelationalExpression, t cc.Type, mode exprMode, flags flags) {
  7000  	switch n.Case {
  7001  	case cc.RelationalExpressionShift: // ShiftExpression
  7002  		p.shiftExpression(f, n.ShiftExpression, t, mode, flags)
  7003  	default:
  7004  		// case cc.RelationalExpressionLt: // RelationalExpression '<' ShiftExpression
  7005  		// case cc.RelationalExpressionGt: // RelationalExpression '>' ShiftExpression
  7006  		// case cc.RelationalExpressionLeq: // RelationalExpression "<=" ShiftExpression
  7007  		// case cc.RelationalExpressionGeq: // RelationalExpression ">=" ShiftExpression
  7008  		p.w("_ = ")
  7009  		p.relationalExpression(f, n, n.Operand.Type(), exprValue, flags)
  7010  	}
  7011  }
  7012  
  7013  func (p *project) relationalExpressionValue(f *function, n *cc.RelationalExpression, t cc.Type, mode exprMode, flags flags) {
  7014  	switch n.Case {
  7015  	case cc.RelationalExpressionShift: // ShiftExpression
  7016  		p.shiftExpression(f, n.ShiftExpression, t, mode, flags)
  7017  	case cc.RelationalExpressionLt: // RelationalExpression '<' ShiftExpression
  7018  		p.binaryRelationalExpression(f, n, " < ", t, mode, flags)
  7019  	case cc.RelationalExpressionGt: // RelationalExpression '>' ShiftExpression
  7020  		p.binaryRelationalExpression(f, n, " > ", t, mode, flags)
  7021  	case cc.RelationalExpressionLeq: // RelationalExpression "<=" ShiftExpression
  7022  		p.binaryRelationalExpression(f, n, " <= ", t, mode, flags)
  7023  	case cc.RelationalExpressionGeq: // RelationalExpression ">=" ShiftExpression
  7024  		p.binaryRelationalExpression(f, n, " >= ", t, mode, flags)
  7025  	default:
  7026  		panic(todo("%v: internal error: %v", n.Position(), n.Case))
  7027  	}
  7028  }
  7029  
  7030  func (p *project) binaryRelationalExpression(f *function, n *cc.RelationalExpression, oper string, t cc.Type, mode exprMode, flags flags) {
  7031  	// RelationalExpression "<=" ShiftExpression
  7032  	lt := n.RelationalExpression.Operand.Type()
  7033  	rt := n.ShiftExpression.Operand.Type()
  7034  	switch lk, rk := lt.Kind(), rt.Kind(); {
  7035  	case
  7036  		lk == cc.UInt128 || rk == cc.UInt128,
  7037  		lk == cc.Int128 || rk == cc.Int128:
  7038  
  7039  		p.binaryRelationalExpressionInt128(f, n, oper, t, mode, flags)
  7040  		return
  7041  	}
  7042  
  7043  	defer p.w("%s", p.booleanBinaryExpression(n, n.Operand, t, &mode, flags))
  7044  	p.relationalExpression(f, n.RelationalExpression, n.Promote(), exprValue, flags)
  7045  	p.w(" %s%s", oper, tidyComment(" ", &n.Token))
  7046  	p.shiftExpression(f, n.ShiftExpression, n.Promote(), exprValue, flags)
  7047  }
  7048  
  7049  func (p *project) binaryRelationalExpressionInt128(f *function, n *cc.RelationalExpression, oper string, t cc.Type, mode exprMode, flags flags) {
  7050  	// RelationalExpression "<=" ShiftExpression
  7051  	defer p.w("%s", p.booleanBinaryExpression(n, n.Operand, t, &mode, flags))
  7052  	p.relationalExpression(f, n.RelationalExpression, n.Promote(), exprValue, flags)
  7053  	p.w(".Cmp(")
  7054  	p.shiftExpression(f, n.ShiftExpression, n.Promote(), exprValue, flags)
  7055  	p.w(") %s 0", oper)
  7056  }
  7057  
  7058  func (p *project) shiftExpression(f *function, n *cc.ShiftExpression, t cc.Type, mode exprMode, flags flags) {
  7059  	switch mode {
  7060  	case exprValue:
  7061  		p.shiftExpressionValue(f, n, t, mode, flags)
  7062  	case exprVoid:
  7063  		p.shiftExpressionVoid(f, n, t, mode, flags)
  7064  	case exprAddrOf:
  7065  		p.shiftExpressionAddrOf(f, n, t, mode, flags)
  7066  	case exprBool:
  7067  		p.shiftExpressionBool(f, n, t, mode, flags)
  7068  	case exprLValue:
  7069  		p.shiftExpressionLValue(f, n, t, mode, flags)
  7070  	case exprPSelect:
  7071  		p.shiftExpressionPSelect(f, n, t, mode, flags)
  7072  	case exprFunc:
  7073  		p.shiftExpressionFunc(f, n, t, mode, flags)
  7074  	case exprSelect:
  7075  		p.shiftExpressionSelect(f, n, t, mode, flags)
  7076  	case exprDecay:
  7077  		p.shiftExpressionDecay(f, n, t, mode, flags)
  7078  	default:
  7079  		panic(todo("", n.Position(), mode))
  7080  	}
  7081  }
  7082  
  7083  func (p *project) shiftExpressionDecay(f *function, n *cc.ShiftExpression, t cc.Type, mode exprMode, flags flags) {
  7084  	switch n.Case {
  7085  	case cc.ShiftExpressionAdd: // AdditiveExpression
  7086  		p.additiveExpression(f, n.AdditiveExpression, t, mode, flags)
  7087  	case cc.ShiftExpressionLsh: // ShiftExpression "<<" AdditiveExpression
  7088  		panic(todo("", p.pos(n)))
  7089  	case cc.ShiftExpressionRsh: // ShiftExpression ">>" AdditiveExpression
  7090  		panic(todo("", p.pos(n)))
  7091  	default:
  7092  		panic(todo("%v: internal error: %v", n.Position(), n.Case))
  7093  	}
  7094  }
  7095  
  7096  func (p *project) shiftExpressionSelect(f *function, n *cc.ShiftExpression, t cc.Type, mode exprMode, flags flags) {
  7097  	switch n.Case {
  7098  	case cc.ShiftExpressionAdd: // AdditiveExpression
  7099  		p.additiveExpression(f, n.AdditiveExpression, t, mode, flags)
  7100  	case cc.ShiftExpressionLsh: // ShiftExpression "<<" AdditiveExpression
  7101  		panic(todo("", p.pos(n)))
  7102  	case cc.ShiftExpressionRsh: // ShiftExpression ">>" AdditiveExpression
  7103  		panic(todo("", p.pos(n)))
  7104  	default:
  7105  		panic(todo("%v: internal error: %v", n.Position(), n.Case))
  7106  	}
  7107  }
  7108  
  7109  func (p *project) shiftExpressionFunc(f *function, n *cc.ShiftExpression, t cc.Type, mode exprMode, flags flags) {
  7110  	switch n.Case {
  7111  	case cc.ShiftExpressionAdd: // AdditiveExpression
  7112  		p.additiveExpression(f, n.AdditiveExpression, t, mode, flags)
  7113  	case cc.ShiftExpressionLsh: // ShiftExpression "<<" AdditiveExpression
  7114  		panic(todo("", p.pos(n)))
  7115  	case cc.ShiftExpressionRsh: // ShiftExpression ">>" AdditiveExpression
  7116  		panic(todo("", p.pos(n)))
  7117  	default:
  7118  		panic(todo("%v: internal error: %v", n.Position(), n.Case))
  7119  	}
  7120  }
  7121  
  7122  func (p *project) shiftExpressionPSelect(f *function, n *cc.ShiftExpression, t cc.Type, mode exprMode, flags flags) {
  7123  	switch n.Case {
  7124  	case cc.ShiftExpressionAdd: // AdditiveExpression
  7125  		p.additiveExpression(f, n.AdditiveExpression, t, mode, flags)
  7126  	case cc.ShiftExpressionLsh: // ShiftExpression "<<" AdditiveExpression
  7127  		panic(todo("", p.pos(n)))
  7128  	case cc.ShiftExpressionRsh: // ShiftExpression ">>" AdditiveExpression
  7129  		panic(todo("", p.pos(n)))
  7130  	default:
  7131  		panic(todo("%v: internal error: %v", n.Position(), n.Case))
  7132  	}
  7133  }
  7134  
  7135  func (p *project) shiftExpressionLValue(f *function, n *cc.ShiftExpression, t cc.Type, mode exprMode, flags flags) {
  7136  	switch n.Case {
  7137  	case cc.ShiftExpressionAdd: // AdditiveExpression
  7138  		p.additiveExpression(f, n.AdditiveExpression, t, mode, flags)
  7139  	case cc.ShiftExpressionLsh: // ShiftExpression "<<" AdditiveExpression
  7140  		panic(todo("", p.pos(n)))
  7141  	case cc.ShiftExpressionRsh: // ShiftExpression ">>" AdditiveExpression
  7142  		panic(todo("", p.pos(n)))
  7143  	default:
  7144  		panic(todo("%v: internal error: %v", n.Position(), n.Case))
  7145  	}
  7146  }
  7147  
  7148  func (p *project) shiftExpressionBool(f *function, n *cc.ShiftExpression, t cc.Type, mode exprMode, flags flags) {
  7149  	switch n.Case {
  7150  	case cc.ShiftExpressionAdd: // AdditiveExpression
  7151  		p.additiveExpression(f, n.AdditiveExpression, t, mode, flags)
  7152  	case cc.ShiftExpressionLsh: // ShiftExpression "<<" AdditiveExpression
  7153  		p.binaryShiftExpression(f, n, "<<", t, mode, flags)
  7154  	case cc.ShiftExpressionRsh: // ShiftExpression ">>" AdditiveExpression
  7155  		p.binaryShiftExpression(f, n, ">>", t, mode, flags)
  7156  	default:
  7157  		panic(todo("%v: internal error: %v", n.Position(), n.Case))
  7158  	}
  7159  }
  7160  
  7161  func (p *project) shiftExpressionAddrOf(f *function, n *cc.ShiftExpression, t cc.Type, mode exprMode, flags flags) {
  7162  	switch n.Case {
  7163  	case cc.ShiftExpressionAdd: // AdditiveExpression
  7164  		p.additiveExpression(f, n.AdditiveExpression, t, mode, flags)
  7165  	case cc.ShiftExpressionLsh: // ShiftExpression "<<" AdditiveExpression
  7166  		panic(todo("", p.pos(n)))
  7167  	case cc.ShiftExpressionRsh: // ShiftExpression ">>" AdditiveExpression
  7168  		panic(todo("", p.pos(n)))
  7169  	default:
  7170  		panic(todo("%v: internal error: %v", n.Position(), n.Case))
  7171  	}
  7172  }
  7173  
  7174  func (p *project) shiftExpressionVoid(f *function, n *cc.ShiftExpression, t cc.Type, mode exprMode, flags flags) {
  7175  	switch n.Case {
  7176  	case cc.ShiftExpressionAdd: // AdditiveExpression
  7177  		p.additiveExpression(f, n.AdditiveExpression, t, mode, flags)
  7178  	case cc.ShiftExpressionLsh: // ShiftExpression "<<" AdditiveExpression
  7179  		panic(todo("", p.pos(n)))
  7180  	case cc.ShiftExpressionRsh: // ShiftExpression ">>" AdditiveExpression
  7181  		panic(todo("", p.pos(n)))
  7182  	default:
  7183  		panic(todo("%v: internal error: %v", n.Position(), n.Case))
  7184  	}
  7185  }
  7186  
  7187  func (p *project) shiftExpressionValue(f *function, n *cc.ShiftExpression, t cc.Type, mode exprMode, flags flags) {
  7188  	switch n.Case {
  7189  	case cc.ShiftExpressionAdd: // AdditiveExpression
  7190  		p.additiveExpression(f, n.AdditiveExpression, t, mode, flags)
  7191  	case cc.ShiftExpressionLsh: // ShiftExpression "<<" AdditiveExpression
  7192  		p.binaryShiftExpression(f, n, "<<", t, mode, flags)
  7193  	case cc.ShiftExpressionRsh: // ShiftExpression ">>" AdditiveExpression
  7194  		p.binaryShiftExpression(f, n, ">>", t, mode, flags)
  7195  	default:
  7196  		panic(todo("%v: internal error: %v", n.Position(), n.Case))
  7197  	}
  7198  }
  7199  
  7200  func (p *project) binaryShiftExpression(f *function, n *cc.ShiftExpression, oper string, t cc.Type, mode exprMode, flags flags) {
  7201  	// ShiftExpression "<<" AdditiveExpression
  7202  	switch mode {
  7203  	case exprValue:
  7204  		p.binaryShiftExpressionValue(f, n, oper, t, mode, flags)
  7205  	case exprBool:
  7206  		p.binaryShiftExpressionBool(f, n, oper, t, mode, flags)
  7207  	default:
  7208  		panic(todo("", n.Position(), mode))
  7209  	}
  7210  }
  7211  
  7212  func (p *project) todo(n cc.Node, t cc.Type) {
  7213  	p.w("func() %s { panic(`%v: TODO (%v)`)}()", p.typ(n, t), n.Position(), origin(2))
  7214  }
  7215  
  7216  func (p *project) binaryShiftExpressionBool(f *function, n *cc.ShiftExpression, oper string, t cc.Type, mode exprMode, flags flags) {
  7217  	defer p.w("%s", p.artithmeticBinaryExpression(n, n.Operand, n.Operand.Type(), &mode, flags))
  7218  	switch {
  7219  	case n.ShiftExpression.Operand.Type().IsBitFieldType():
  7220  		p.w("(")
  7221  		p.shiftExpression(f, n.ShiftExpression, n.Operand.Type(), exprValue, flags)
  7222  		p.w(" %s%s", oper, tidyComment(" ", &n.Token))
  7223  		p.additiveExpression(f, n.AdditiveExpression, n.Promote(), exprValue, flags)
  7224  		p.w(")&%#x", bfValueMask(n.ShiftExpression.Operand.Type().BitField()))
  7225  	case shiftOverflows(n, n.ShiftExpression.Operand, n.AdditiveExpression.Operand, oper, n.Operand.Type()):
  7226  		p.shiftExpression(f, n.ShiftExpression, n.Operand.Type(), exprValue, flags|fForceRuntimeConv)
  7227  		p.w(" %s%s", oper, tidyComment(" ", &n.Token))
  7228  		p.additiveExpression(f, n.AdditiveExpression, n.Promote(), exprValue, flags)
  7229  	case isConstInteger(n.ShiftExpression.Operand):
  7230  		s := p.convertNil(n, n.Operand.Type(), 0)
  7231  		p.shiftExpression(f, n.ShiftExpression, n.Operand.Type(), exprValue, flags)
  7232  		p.w("%s %s%s", s, oper, tidyComment(" ", &n.Token))
  7233  		p.additiveExpression(f, n.AdditiveExpression, n.Promote(), exprValue, flags)
  7234  	default:
  7235  		p.shiftExpression(f, n.ShiftExpression, n.Operand.Type(), exprValue, flags)
  7236  		p.w(" %s%s", oper, tidyComment(" ", &n.Token))
  7237  		p.additiveExpression(f, n.AdditiveExpression, n.Promote(), exprValue, flags)
  7238  	}
  7239  }
  7240  
  7241  func shiftOp(s string) string {
  7242  	switch s {
  7243  	case "<<":
  7244  		return "Shl"
  7245  	case ">>":
  7246  		return "Shr"
  7247  	default:
  7248  		panic(todo("%q", s))
  7249  	}
  7250  }
  7251  
  7252  func bfValueMask(bf cc.Field) uint64 {
  7253  	return uint64(1)<<bf.BitFieldWidth() - 1
  7254  }
  7255  
  7256  func (p *project) binaryShiftExpressionValue(f *function, n *cc.ShiftExpression, oper string, t cc.Type, mode exprMode, flags flags) {
  7257  	// ShiftExpression "<<" AdditiveExpression
  7258  	defer p.w("%s", p.artithmeticBinaryExpression(n, n.Operand, t, &mode, flags))
  7259  	switch k := n.ShiftExpression.Operand.Type().Kind(); {
  7260  	case k == cc.Int128, k == cc.UInt128:
  7261  		p.w("(")
  7262  		p.shiftExpression(f, n.ShiftExpression, n.Operand.Type(), exprValue, flags)
  7263  		p.w(").%s(", shiftOp(oper))
  7264  		p.additiveExpression(f, n.AdditiveExpression, p.intType, exprValue, flags)
  7265  		p.w(")")
  7266  	case n.ShiftExpression.Operand.Type().IsBitFieldType():
  7267  		p.w("(")
  7268  		p.shiftExpression(f, n.ShiftExpression, n.Operand.Type(), exprValue, flags)
  7269  		p.w(" %s%s", oper, tidyComment(" ", &n.Token))
  7270  		p.additiveExpression(f, n.AdditiveExpression, n.Promote(), exprValue, flags)
  7271  		p.w(")&%#x", bfValueMask(n.ShiftExpression.Operand.Type().BitField()))
  7272  	case shiftOverflows(n, n.ShiftExpression.Operand, n.AdditiveExpression.Operand, oper, n.Operand.Type()):
  7273  		p.shiftExpression(f, n.ShiftExpression, n.Operand.Type(), exprValue, flags|fForceRuntimeConv)
  7274  		p.w(" %s%s", oper, tidyComment(" ", &n.Token))
  7275  		p.additiveExpression(f, n.AdditiveExpression, n.Promote(), exprValue, flags)
  7276  	case isConstInteger(n.ShiftExpression.Operand):
  7277  		s := p.convertNil(n, n.Operand.Type(), 0)
  7278  		p.shiftExpression(f, n.ShiftExpression, n.Operand.Type(), exprValue, flags)
  7279  		p.w("%s %s%s", s, oper, tidyComment(" ", &n.Token))
  7280  		p.additiveExpression(f, n.AdditiveExpression, n.Promote(), exprValue, flags)
  7281  	default:
  7282  		p.shiftExpression(f, n.ShiftExpression, n.Operand.Type(), exprValue, flags)
  7283  		p.w(" %s%s", oper, tidyComment(" ", &n.Token))
  7284  		p.additiveExpression(f, n.AdditiveExpression, n.Promote(), exprValue, flags)
  7285  	}
  7286  }
  7287  
  7288  func shiftOverflows(n cc.Node, lo, ro cc.Operand, oper string, result cc.Type) bool {
  7289  	a, b, ok := getIntOperands(lo, ro)
  7290  	if !ok {
  7291  		return false
  7292  	}
  7293  
  7294  	if !b.IsUint64() {
  7295  		return true
  7296  	}
  7297  
  7298  	bits := b.Uint64()
  7299  	if bits > mathutil.MaxUint {
  7300  		return true
  7301  	}
  7302  
  7303  	switch oper {
  7304  	case "<<":
  7305  		return overflows(a.Lsh(a, uint(bits)), result)
  7306  	case ">>":
  7307  		return overflows(a.Rsh(a, uint(bits)), result)
  7308  	default:
  7309  		panic(todo("", pos(n)))
  7310  	}
  7311  }
  7312  
  7313  func (p *project) additiveExpression(f *function, n *cc.AdditiveExpression, t cc.Type, mode exprMode, flags flags) {
  7314  	switch mode {
  7315  	case exprValue:
  7316  		p.additiveExpressionValue(f, n, t, mode, flags)
  7317  	case exprVoid:
  7318  		p.additiveExpressionVoid(f, n, t, mode, flags)
  7319  	case exprAddrOf:
  7320  		p.additiveExpressionAddrOf(f, n, t, mode, flags)
  7321  	case exprBool:
  7322  		p.additiveExpressionBool(f, n, t, mode, flags)
  7323  	case exprLValue:
  7324  		p.additiveExpressionLValue(f, n, t, mode, flags)
  7325  	case exprPSelect:
  7326  		p.additiveExpressionPSelect(f, n, t, mode, flags)
  7327  	case exprFunc:
  7328  		p.additiveExpressionFunc(f, n, t, mode, flags)
  7329  	case exprSelect:
  7330  		p.additiveExpressionSelect(f, n, t, mode, flags)
  7331  	case exprDecay:
  7332  		p.additiveExpressionDecay(f, n, t, mode, flags)
  7333  	default:
  7334  		panic(todo("", n.Position(), mode))
  7335  	}
  7336  }
  7337  
  7338  func (p *project) additiveExpressionDecay(f *function, n *cc.AdditiveExpression, t cc.Type, mode exprMode, flags flags) {
  7339  	switch n.Case {
  7340  	case cc.AdditiveExpressionMul: // MultiplicativeExpression
  7341  		p.multiplicativeExpression(f, n.MultiplicativeExpression, t, mode, flags)
  7342  	case cc.AdditiveExpressionAdd: // AdditiveExpression '+' MultiplicativeExpression
  7343  		panic(todo("", p.pos(n)))
  7344  	case cc.AdditiveExpressionSub: // AdditiveExpression '-' MultiplicativeExpression
  7345  		panic(todo("", p.pos(n)))
  7346  	default:
  7347  		panic(todo("%v: internal error: %v", n.Position(), n.Case))
  7348  	}
  7349  }
  7350  
  7351  func (p *project) additiveExpressionSelect(f *function, n *cc.AdditiveExpression, t cc.Type, mode exprMode, flags flags) {
  7352  	switch n.Case {
  7353  	case cc.AdditiveExpressionMul: // MultiplicativeExpression
  7354  		p.multiplicativeExpression(f, n.MultiplicativeExpression, t, mode, flags)
  7355  	case cc.AdditiveExpressionAdd: // AdditiveExpression '+' MultiplicativeExpression
  7356  		panic(todo("", p.pos(n)))
  7357  	case cc.AdditiveExpressionSub: // AdditiveExpression '-' MultiplicativeExpression
  7358  		panic(todo("", p.pos(n)))
  7359  	default:
  7360  		panic(todo("%v: internal error: %v", n.Position(), n.Case))
  7361  	}
  7362  }
  7363  
  7364  func (p *project) additiveExpressionFunc(f *function, n *cc.AdditiveExpression, t cc.Type, mode exprMode, flags flags) {
  7365  	switch n.Case {
  7366  	case cc.AdditiveExpressionMul: // MultiplicativeExpression
  7367  		p.multiplicativeExpression(f, n.MultiplicativeExpression, t, mode, flags)
  7368  	case cc.AdditiveExpressionAdd: // AdditiveExpression '+' MultiplicativeExpression
  7369  		panic(todo("", p.pos(n)))
  7370  	case cc.AdditiveExpressionSub: // AdditiveExpression '-' MultiplicativeExpression
  7371  		panic(todo("", p.pos(n)))
  7372  	default:
  7373  		panic(todo("%v: internal error: %v", n.Position(), n.Case))
  7374  	}
  7375  }
  7376  
  7377  func (p *project) additiveExpressionPSelect(f *function, n *cc.AdditiveExpression, t cc.Type, mode exprMode, flags flags) {
  7378  	switch n.Case {
  7379  	case cc.AdditiveExpressionMul: // MultiplicativeExpression
  7380  		p.multiplicativeExpression(f, n.MultiplicativeExpression, t, mode, flags)
  7381  	case cc.AdditiveExpressionAdd: // AdditiveExpression '+' MultiplicativeExpression
  7382  		p.w("(*%s)(unsafe.Pointer(", p.typ(n, t.Elem()))
  7383  		p.additiveExpression(f, n, t, exprValue, flags)
  7384  		p.w("))")
  7385  	case cc.AdditiveExpressionSub: // AdditiveExpression '-' MultiplicativeExpression
  7386  		p.w("(*%s)(unsafe.Pointer(", p.typ(n, t.Elem()))
  7387  		p.additiveExpression(f, n, t, exprValue, flags)
  7388  
  7389  	default:
  7390  		panic(todo("%v: internal error: %v", n.Position(), n.Case))
  7391  	}
  7392  }
  7393  
  7394  func (p *project) additiveExpressionLValue(f *function, n *cc.AdditiveExpression, t cc.Type, mode exprMode, flags flags) {
  7395  	switch n.Case {
  7396  	case cc.AdditiveExpressionMul: // MultiplicativeExpression
  7397  		p.multiplicativeExpression(f, n.MultiplicativeExpression, t, mode, flags)
  7398  	case cc.AdditiveExpressionAdd: // AdditiveExpression '+' MultiplicativeExpression
  7399  		panic(todo("", p.pos(n)))
  7400  	case cc.AdditiveExpressionSub: // AdditiveExpression '-' MultiplicativeExpression
  7401  		panic(todo("", p.pos(n)))
  7402  	default:
  7403  		panic(todo("%v: internal error: %v", n.Position(), n.Case))
  7404  	}
  7405  }
  7406  
  7407  func (p *project) additiveExpressionBool(f *function, n *cc.AdditiveExpression, t cc.Type, mode exprMode, flags flags) {
  7408  	switch n.Case {
  7409  	case cc.AdditiveExpressionMul: // MultiplicativeExpression
  7410  		p.multiplicativeExpression(f, n.MultiplicativeExpression, t, mode, flags)
  7411  	case cc.AdditiveExpressionAdd: // AdditiveExpression '+' MultiplicativeExpression
  7412  		p.binaryAdditiveExpression(f, n, "+", t, mode, flags)
  7413  	case cc.AdditiveExpressionSub: // AdditiveExpression '-' MultiplicativeExpression
  7414  		p.binaryAdditiveExpression(f, n, "-", t, mode, flags)
  7415  	default:
  7416  		panic(todo("%v: internal error: %v", n.Position(), n.Case))
  7417  	}
  7418  }
  7419  
  7420  func (p *project) additiveExpressionAddrOf(f *function, n *cc.AdditiveExpression, t cc.Type, mode exprMode, flags flags) {
  7421  	switch n.Case {
  7422  	case cc.AdditiveExpressionMul: // MultiplicativeExpression
  7423  		p.multiplicativeExpression(f, n.MultiplicativeExpression, t, mode, flags)
  7424  	case cc.AdditiveExpressionAdd: // AdditiveExpression '+' MultiplicativeExpression
  7425  		panic(todo("", p.pos(n)))
  7426  	case cc.AdditiveExpressionSub: // AdditiveExpression '-' MultiplicativeExpression
  7427  		panic(todo("", p.pos(n)))
  7428  	default:
  7429  		panic(todo("%v: internal error: %v", n.Position(), n.Case))
  7430  	}
  7431  }
  7432  
  7433  func (p *project) additiveExpressionVoid(f *function, n *cc.AdditiveExpression, t cc.Type, mode exprMode, flags flags) {
  7434  	switch n.Case {
  7435  	case cc.AdditiveExpressionMul: // MultiplicativeExpression
  7436  		p.multiplicativeExpression(f, n.MultiplicativeExpression, t, mode, flags)
  7437  	case
  7438  		cc.AdditiveExpressionAdd, // AdditiveExpression '+' MultiplicativeExpression
  7439  		cc.AdditiveExpressionSub: // AdditiveExpression '-' MultiplicativeExpression
  7440  
  7441  		p.w("_ = ")
  7442  		p.additiveExpression(f, n, n.Operand.Type(), exprValue, flags)
  7443  	default:
  7444  		panic(todo("%v: internal error: %v", n.Position(), n.Case))
  7445  	}
  7446  }
  7447  
  7448  func (p *project) additiveExpressionValue(f *function, n *cc.AdditiveExpression, t cc.Type, mode exprMode, flags flags) {
  7449  	switch n.Case {
  7450  	case cc.AdditiveExpressionMul: // MultiplicativeExpression
  7451  		p.multiplicativeExpression(f, n.MultiplicativeExpression, t, mode, flags)
  7452  	case cc.AdditiveExpressionAdd: // AdditiveExpression '+' MultiplicativeExpression
  7453  		p.binaryAdditiveExpression(f, n, "+", t, mode, flags)
  7454  	case cc.AdditiveExpressionSub: // AdditiveExpression '-' MultiplicativeExpression
  7455  		p.binaryAdditiveExpression(f, n, "-", t, mode, flags)
  7456  	default:
  7457  		panic(todo("%v: internal error: %v", n.Position(), n.Case))
  7458  	}
  7459  }
  7460  
  7461  func (p *project) binaryAdditiveExpression(f *function, n *cc.AdditiveExpression, oper string, t cc.Type, mode exprMode, flags flags) {
  7462  	// AdditiveExpression '+' MultiplicativeExpression
  7463  	switch mode {
  7464  	case exprValue:
  7465  		p.binaryAdditiveExpressionValue(f, n, oper, t, mode, flags)
  7466  	case exprBool:
  7467  		p.binaryAdditiveExpressionBool(f, n, oper, t, mode, flags)
  7468  	default:
  7469  		panic(todo("", mode))
  7470  	}
  7471  }
  7472  
  7473  func (p *project) binaryAdditiveExpressionBool(f *function, n *cc.AdditiveExpression, oper string, t cc.Type, mode exprMode, flags flags) {
  7474  	// AdditiveExpression '+' MultiplicativeExpression
  7475  	defer p.w("%s", p.artithmeticBinaryExpression(n, n.Operand, n.Operand.Type(), &mode, flags))
  7476  	lo := n.AdditiveExpression.Operand
  7477  	ro := n.MultiplicativeExpression.Operand
  7478  	lt := lo.Type()
  7479  	rt := ro.Type()
  7480  	switch {
  7481  	case lt.Kind() == cc.Ptr && rt.Kind() == cc.Ptr && oper == "-":
  7482  		p.additiveExpression(f, n.AdditiveExpression, n.Promote(), exprValue, flags)
  7483  		p.w(" %s%s", oper, tidyComment(" ", &n.Token))
  7484  		p.multiplicativeExpression(f, n.MultiplicativeExpression, n.Promote(), exprValue, flags)
  7485  	case lt.IsArithmeticType() && rt.IsArithmeticType(): // x +- y
  7486  		defer p.w("%s", p.bitFieldPatch2(n, lo, ro, n.Promote())) //TODO bit field big endian
  7487  		switch {
  7488  		case intAddOverflows(n, lo, ro, oper, n.Promote()): // i +- j
  7489  			p.additiveExpression(f, n.AdditiveExpression, n.Promote(), exprValue, flags)
  7490  			p.w(" %s%s", oper, tidyComment(" ", &n.Token))
  7491  			p.multiplicativeExpression(f, n.MultiplicativeExpression, n.Promote(), exprValue, flags|fForceRuntimeConv)
  7492  		default:
  7493  			var s string
  7494  			if isRealType(n.Operand) && n.Operand.Value() != nil {
  7495  				s = p.convertNil(n, n.Promote(), flags)
  7496  			}
  7497  			p.additiveExpression(f, n.AdditiveExpression, n.Promote(), exprValue, flags)
  7498  			p.w("%s %s%s", s, oper, tidyComment(" ", &n.Token))
  7499  			p.multiplicativeExpression(f, n.MultiplicativeExpression, n.Promote(), exprValue, flags)
  7500  		}
  7501  	default:
  7502  		panic(todo("", n.Position(), lt, rt, oper))
  7503  	}
  7504  }
  7505  
  7506  func (p *project) binaryAdditiveExpressionValue(f *function, n *cc.AdditiveExpression, oper string, t cc.Type, mode exprMode, flags flags) {
  7507  	// AdditiveExpression '+' MultiplicativeExpression
  7508  
  7509  	lt := n.AdditiveExpression.Operand.Type()
  7510  	rt := n.MultiplicativeExpression.Operand.Type()
  7511  	switch lk, rk := lt.Kind(), rt.Kind(); {
  7512  	case
  7513  		lk == cc.UInt128 || rk == cc.UInt128,
  7514  		lk == cc.Int128 || rk == cc.Int128:
  7515  
  7516  		p.binaryAdditiveExpressionUint128(f, n, oper, t, mode, flags)
  7517  		return
  7518  	}
  7519  
  7520  	defer p.w("%s", p.artithmeticBinaryExpression(n, n.Operand, t, &mode, flags))
  7521  	lo := n.AdditiveExpression.Operand
  7522  	ro := n.MultiplicativeExpression.Operand
  7523  	switch {
  7524  	case lt.IsArithmeticType() && rt.IsArithmeticType(): // x +- y
  7525  		defer p.w("%s", p.bitFieldPatch2(n, lo, ro, n.Promote())) //TODO bit field big endian
  7526  		switch {
  7527  		case intAddOverflows(n, lo, ro, oper, n.Promote()): // i +- j
  7528  			p.additiveExpression(f, n.AdditiveExpression, n.Promote(), exprValue, flags)
  7529  			p.w(" %s%s", oper, tidyComment(" ", &n.Token))
  7530  			p.multiplicativeExpression(f, n.MultiplicativeExpression, n.Promote(), exprValue, flags|fForceRuntimeConv)
  7531  		default:
  7532  			var s string
  7533  			if isRealType(n.Operand) && n.Operand.Value() != nil {
  7534  				s = p.convertNil(n, n.Promote(), flags)
  7535  			}
  7536  			p.additiveExpression(f, n.AdditiveExpression, n.Promote(), exprValue, flags)
  7537  			p.w("%s %s%s", s, oper, tidyComment(" ", &n.Token))
  7538  			p.multiplicativeExpression(f, n.MultiplicativeExpression, n.Promote(), exprValue, flags)
  7539  		}
  7540  	case lt.Kind() == cc.Ptr && rt.IsIntegerType(): // p +- i
  7541  		p.additiveExpression(f, n.AdditiveExpression, lt, exprValue, flags)
  7542  		p.w(" %s%s uintptr(", oper, tidyComment(" ", &n.Token))
  7543  		p.multiplicativeExpression(f, n.MultiplicativeExpression, rt, exprValue, flags)
  7544  		p.w(")")
  7545  		if sz := lt.Elem().Size(); sz != 1 {
  7546  			p.w("*%d", sz)
  7547  		}
  7548  	case lt.Kind() == cc.Array && rt.IsIntegerType(): // p +- i
  7549  		p.additiveExpression(f, n.AdditiveExpression, lt, exprDecay, flags)
  7550  		p.w(" %s%s uintptr(", oper, tidyComment(" ", &n.Token))
  7551  		p.multiplicativeExpression(f, n.MultiplicativeExpression, rt, exprValue, flags)
  7552  		p.w(")")
  7553  		if sz := lt.Elem().Size(); sz != 1 {
  7554  			p.w("*%d", sz)
  7555  		}
  7556  	case lt.IsIntegerType() && rt.Kind() == cc.Ptr: // i +- p
  7557  		p.w("uintptr(")
  7558  		p.additiveExpression(f, n.AdditiveExpression, lt, exprValue, flags)
  7559  		p.w(")")
  7560  		if sz := rt.Elem().Size(); sz != 1 {
  7561  			p.w("*%d", sz)
  7562  		}
  7563  		p.w(" %s%s ", oper, tidyComment(" ", &n.Token))
  7564  		p.multiplicativeExpression(f, n.MultiplicativeExpression, rt, exprValue, flags)
  7565  	case lt.IsIntegerType() && rt.Kind() == cc.Array: // i +- p
  7566  		panic(todo("", p.pos(n)))
  7567  	case lt.Kind() == cc.Ptr && rt.Kind() == cc.Ptr && oper == "-": // p - q
  7568  		p.w("(")
  7569  		p.additiveExpression(f, n.AdditiveExpression, n.Operand.Type(), exprValue, flags)
  7570  		p.w(" %s%s", oper, tidyComment(" ", &n.Token))
  7571  		p.multiplicativeExpression(f, n.MultiplicativeExpression, n.Operand.Type(), exprValue, flags)
  7572  		p.w(")/%d", lt.Elem().Size())
  7573  	case lt.Kind() == cc.Ptr && rt.Kind() == cc.Array && oper == "-": // p - q
  7574  		defer p.w("%s", p.convertType(n, nil, n.Operand.Type(), 0))
  7575  		p.w("(")
  7576  		p.additiveExpression(f, n.AdditiveExpression, lt, exprValue, flags)
  7577  		p.w(" %s%s", oper, tidyComment(" ", &n.Token))
  7578  		p.multiplicativeExpression(f, n.MultiplicativeExpression, rt.Decay(), exprDecay, flags)
  7579  		p.w(")/%d", lt.Elem().Size())
  7580  	case lt.Kind() == cc.Array && rt.Kind() == cc.Ptr && oper == "-": // p - q
  7581  		panic(todo("", p.pos(n)))
  7582  	case lt.Kind() == cc.Array && rt.Kind() == cc.Array && oper == "-": // p - q
  7583  		panic(todo("", p.pos(n)))
  7584  	default:
  7585  		panic(todo("", n.Position(), lt, rt, oper))
  7586  	}
  7587  }
  7588  
  7589  func (p *project) binaryAdditiveExpressionUint128(f *function, n *cc.AdditiveExpression, oper string, t cc.Type, mode exprMode, flags flags) {
  7590  	// AdditiveExpression '+' MultiplicativeExpression
  7591  	defer p.w("%s", p.artithmeticBinaryExpression(n, n.Operand, t, &mode, flags))
  7592  	p.additiveExpression(f, n.AdditiveExpression, n.Promote(), exprValue, flags)
  7593  	switch oper {
  7594  	case "+":
  7595  		p.w(".Add(")
  7596  	case "-":
  7597  		p.w(".Sub(")
  7598  	default:
  7599  		panic(todo("%q", oper))
  7600  	}
  7601  	p.multiplicativeExpression(f, n.MultiplicativeExpression, n.Promote(), exprValue, flags)
  7602  	p.w(")")
  7603  }
  7604  
  7605  func (p *project) bitFieldPatch2(n cc.Node, a, b cc.Operand, promote cc.Type) string {
  7606  	//TODO bit field big endian
  7607  	var m uint64
  7608  	var w int
  7609  	switch {
  7610  	case a.Type().IsBitFieldType():
  7611  		bf := a.Type().BitField()
  7612  		w = bf.BitFieldWidth()
  7613  		m = bf.Mask() >> bf.BitFieldOffset()
  7614  		if b.Type().IsBitFieldType() {
  7615  			bf = b.Type().BitField()
  7616  			w2 := bf.BitFieldWidth()
  7617  			if w2 != w {
  7618  				panic(todo("", p.pos(n)))
  7619  			}
  7620  		}
  7621  	case b.Type().IsBitFieldType():
  7622  		bf := b.Type().BitField()
  7623  		w = bf.BitFieldWidth()
  7624  		m = bf.Mask() >> bf.BitFieldOffset()
  7625  	default:
  7626  		return ""
  7627  	}
  7628  
  7629  	p.w("((")
  7630  	switch {
  7631  	case promote.IsSignedType():
  7632  		n := int(promote.Size())*8 - w
  7633  		var s string
  7634  		switch promote.Size() {
  7635  		case 4:
  7636  			s = fmt.Sprintf(")&%#x", int32(m))
  7637  		default:
  7638  			s = fmt.Sprintf(")&%#x", m)
  7639  		}
  7640  		if n != 0 {
  7641  			s += fmt.Sprintf("<<%d>>%[1]d", n)
  7642  		}
  7643  		return ")" + s
  7644  	default:
  7645  		return fmt.Sprintf(")&%#x)", m)
  7646  	}
  7647  }
  7648  
  7649  func intAddOverflows(n cc.Node, lo, ro cc.Operand, oper string, promote cc.Type) bool {
  7650  	a, b, ok := getIntOperands(lo, ro)
  7651  	if !ok {
  7652  		return false
  7653  	}
  7654  
  7655  	switch oper {
  7656  	case "+":
  7657  		return overflows(a.Add(a, b), promote)
  7658  	case "-":
  7659  		return overflows(a.Sub(a, b), promote)
  7660  	default:
  7661  		panic(todo("", pos(n)))
  7662  	}
  7663  }
  7664  
  7665  func getIntOperands(a, b cc.Operand) (x, y *big.Int, ok bool) {
  7666  	switch n := a.Value().(type) {
  7667  	case cc.Int64Value:
  7668  		x = big.NewInt(int64(n))
  7669  	case cc.Uint64Value:
  7670  		x = big.NewInt(0).SetUint64(uint64(n))
  7671  	default:
  7672  		return nil, nil, false
  7673  	}
  7674  
  7675  	switch n := b.Value().(type) {
  7676  	case cc.Int64Value:
  7677  		return x, big.NewInt(int64(n)), true
  7678  	case cc.Uint64Value:
  7679  		return x, big.NewInt(0).SetUint64(uint64(n)), true
  7680  	default:
  7681  		return nil, nil, false
  7682  	}
  7683  }
  7684  
  7685  func overflows(n *big.Int, promote cc.Type) bool {
  7686  	switch k := promote.Kind(); {
  7687  	case k == cc.Int128, k == cc.UInt128:
  7688  		return false
  7689  	case isSigned(promote):
  7690  		switch promote.Size() {
  7691  		case 4:
  7692  			return n.Cmp(minInt32) < 0 || n.Cmp(maxInt32) > 0
  7693  		case 8:
  7694  			return n.Cmp(minInt64) < 0 || n.Cmp(maxInt64) > 0
  7695  		}
  7696  	default:
  7697  		switch promote.Size() {
  7698  		case 4:
  7699  			return n.Sign() < 0 || n.Cmp(maxUint32) > 0
  7700  		case 8:
  7701  			return n.Sign() < 0 || n.Cmp(maxUint64) > 0
  7702  		}
  7703  	}
  7704  	panic(todo("", promote.Size(), promote))
  7705  }
  7706  
  7707  func (p *project) multiplicativeExpression(f *function, n *cc.MultiplicativeExpression, t cc.Type, mode exprMode, flags flags) {
  7708  	switch mode {
  7709  	case exprValue:
  7710  		p.multiplicativeExpressionValue(f, n, t, mode, flags)
  7711  	case exprVoid:
  7712  		p.multiplicativeExpressionVoid(f, n, t, mode, flags)
  7713  	case exprAddrOf:
  7714  		p.multiplicativeExpressionAddrOf(f, n, t, mode, flags)
  7715  	case exprBool:
  7716  		p.multiplicativeExpressionBool(f, n, t, mode, flags)
  7717  	case exprLValue:
  7718  		p.multiplicativeExpressionLValue(f, n, t, mode, flags)
  7719  	case exprPSelect:
  7720  		p.multiplicativeExpressionPSelect(f, n, t, mode, flags)
  7721  	case exprFunc:
  7722  		p.multiplicativeExpressionFunc(f, n, t, mode, flags)
  7723  	case exprSelect:
  7724  		p.multiplicativeExpressionSelect(f, n, t, mode, flags)
  7725  	case exprDecay:
  7726  		p.multiplicativeExpressionDecay(f, n, t, mode, flags)
  7727  	default:
  7728  		panic(todo("", n.Position(), mode))
  7729  	}
  7730  }
  7731  
  7732  func (p *project) multiplicativeExpressionDecay(f *function, n *cc.MultiplicativeExpression, t cc.Type, mode exprMode, flags flags) {
  7733  	switch n.Case {
  7734  	case cc.MultiplicativeExpressionCast: // CastExpression
  7735  		p.castExpression(f, n.CastExpression, t, mode, flags)
  7736  	case cc.MultiplicativeExpressionMul: // MultiplicativeExpression '*' CastExpression
  7737  		panic(todo("", p.pos(n)))
  7738  	case cc.MultiplicativeExpressionDiv: // MultiplicativeExpression '/' CastExpression
  7739  		panic(todo("", p.pos(n)))
  7740  	case cc.MultiplicativeExpressionMod: // MultiplicativeExpression '%' CastExpression
  7741  		panic(todo("", p.pos(n)))
  7742  	default:
  7743  		panic(todo("%v: internal error: %v", n.Position(), n.Case))
  7744  	}
  7745  }
  7746  
  7747  func (p *project) multiplicativeExpressionSelect(f *function, n *cc.MultiplicativeExpression, t cc.Type, mode exprMode, flags flags) {
  7748  	switch n.Case {
  7749  	case cc.MultiplicativeExpressionCast: // CastExpression
  7750  		p.castExpression(f, n.CastExpression, t, mode, flags)
  7751  	case cc.MultiplicativeExpressionMul: // MultiplicativeExpression '*' CastExpression
  7752  		panic(todo("", p.pos(n)))
  7753  	case cc.MultiplicativeExpressionDiv: // MultiplicativeExpression '/' CastExpression
  7754  		panic(todo("", p.pos(n)))
  7755  	case cc.MultiplicativeExpressionMod: // MultiplicativeExpression '%' CastExpression
  7756  		panic(todo("", p.pos(n)))
  7757  	default:
  7758  		panic(todo("%v: internal error: %v", n.Position(), n.Case))
  7759  	}
  7760  }
  7761  
  7762  func (p *project) multiplicativeExpressionFunc(f *function, n *cc.MultiplicativeExpression, t cc.Type, mode exprMode, flags flags) {
  7763  	switch n.Case {
  7764  	case cc.MultiplicativeExpressionCast: // CastExpression
  7765  		p.castExpression(f, n.CastExpression, t, mode, flags)
  7766  	case cc.MultiplicativeExpressionMul: // MultiplicativeExpression '*' CastExpression
  7767  		panic(todo("", p.pos(n)))
  7768  	case cc.MultiplicativeExpressionDiv: // MultiplicativeExpression '/' CastExpression
  7769  		panic(todo("", p.pos(n)))
  7770  	case cc.MultiplicativeExpressionMod: // MultiplicativeExpression '%' CastExpression
  7771  		panic(todo("", p.pos(n)))
  7772  	default:
  7773  		panic(todo("%v: internal error: %v", n.Position(), n.Case))
  7774  	}
  7775  }
  7776  
  7777  func (p *project) multiplicativeExpressionPSelect(f *function, n *cc.MultiplicativeExpression, t cc.Type, mode exprMode, flags flags) {
  7778  	switch n.Case {
  7779  	case cc.MultiplicativeExpressionCast: // CastExpression
  7780  		p.castExpression(f, n.CastExpression, t, mode, flags)
  7781  	case cc.MultiplicativeExpressionMul: // MultiplicativeExpression '*' CastExpression
  7782  		panic(todo("", p.pos(n)))
  7783  	case cc.MultiplicativeExpressionDiv: // MultiplicativeExpression '/' CastExpression
  7784  		panic(todo("", p.pos(n)))
  7785  	case cc.MultiplicativeExpressionMod: // MultiplicativeExpression '%' CastExpression
  7786  		panic(todo("", p.pos(n)))
  7787  	default:
  7788  		panic(todo("%v: internal error: %v", n.Position(), n.Case))
  7789  	}
  7790  }
  7791  
  7792  func (p *project) multiplicativeExpressionLValue(f *function, n *cc.MultiplicativeExpression, t cc.Type, mode exprMode, flags flags) {
  7793  	switch n.Case {
  7794  	case cc.MultiplicativeExpressionCast: // CastExpression
  7795  		p.castExpression(f, n.CastExpression, t, mode, flags)
  7796  	case cc.MultiplicativeExpressionMul: // MultiplicativeExpression '*' CastExpression
  7797  		panic(todo("", p.pos(n)))
  7798  	case cc.MultiplicativeExpressionDiv: // MultiplicativeExpression '/' CastExpression
  7799  		panic(todo("", p.pos(n)))
  7800  	case cc.MultiplicativeExpressionMod: // MultiplicativeExpression '%' CastExpression
  7801  		panic(todo("", p.pos(n)))
  7802  	default:
  7803  		panic(todo("%v: internal error: %v", n.Position(), n.Case))
  7804  	}
  7805  }
  7806  
  7807  func (p *project) multiplicativeExpressionBool(f *function, n *cc.MultiplicativeExpression, t cc.Type, mode exprMode, flags flags) {
  7808  	switch n.Case {
  7809  	case cc.MultiplicativeExpressionCast: // CastExpression
  7810  		p.castExpression(f, n.CastExpression, t, mode, flags)
  7811  	case
  7812  		cc.MultiplicativeExpressionMul, // MultiplicativeExpression '*' CastExpression
  7813  		cc.MultiplicativeExpressionDiv, // MultiplicativeExpression '/' CastExpression
  7814  		cc.MultiplicativeExpressionMod: // MultiplicativeExpression '%' CastExpression
  7815  
  7816  		p.w("(")
  7817  		defer p.w(")")
  7818  		defer p.w(" != 0 ")
  7819  		p.multiplicativeExpression(f, n, t, exprValue, flags)
  7820  	default:
  7821  		panic(todo("%v: internal error: %v", n.Position(), n.Case))
  7822  	}
  7823  }
  7824  
  7825  func (p *project) multiplicativeExpressionAddrOf(f *function, n *cc.MultiplicativeExpression, t cc.Type, mode exprMode, flags flags) {
  7826  	switch n.Case {
  7827  	case cc.MultiplicativeExpressionCast: // CastExpression
  7828  		p.castExpression(f, n.CastExpression, t, mode, flags)
  7829  	case cc.MultiplicativeExpressionMul: // MultiplicativeExpression '*' CastExpression
  7830  		panic(todo("", p.pos(n)))
  7831  	case cc.MultiplicativeExpressionDiv: // MultiplicativeExpression '/' CastExpression
  7832  		panic(todo("", p.pos(n)))
  7833  	case cc.MultiplicativeExpressionMod: // MultiplicativeExpression '%' CastExpression
  7834  		panic(todo("", p.pos(n)))
  7835  	default:
  7836  		panic(todo("%v: internal error: %v", n.Position(), n.Case))
  7837  	}
  7838  }
  7839  
  7840  func (p *project) multiplicativeExpressionVoid(f *function, n *cc.MultiplicativeExpression, t cc.Type, mode exprMode, flags flags) {
  7841  	switch n.Case {
  7842  	case cc.MultiplicativeExpressionCast: // CastExpression
  7843  		p.castExpression(f, n.CastExpression, t, mode, flags)
  7844  	case cc.MultiplicativeExpressionMul: // MultiplicativeExpression '*' CastExpression
  7845  		panic(todo("", p.pos(n)))
  7846  	case cc.MultiplicativeExpressionDiv: // MultiplicativeExpression '/' CastExpression
  7847  		panic(todo("", p.pos(n)))
  7848  	case cc.MultiplicativeExpressionMod: // MultiplicativeExpression '%' CastExpression
  7849  		panic(todo("", p.pos(n)))
  7850  	default:
  7851  		panic(todo("%v: internal error: %v", n.Position(), n.Case))
  7852  	}
  7853  }
  7854  
  7855  func (p *project) multiplicativeExpressionValue(f *function, n *cc.MultiplicativeExpression, t cc.Type, mode exprMode, flags flags) {
  7856  	switch n.Case {
  7857  	case cc.MultiplicativeExpressionCast: // CastExpression
  7858  		p.castExpression(f, n.CastExpression, t, mode, flags)
  7859  	case cc.MultiplicativeExpressionMul: // MultiplicativeExpression '*' CastExpression
  7860  		p.binaryMultiplicativeExpression(f, n, "*", t, mode, flags)
  7861  	case cc.MultiplicativeExpressionDiv: // MultiplicativeExpression '/' CastExpression
  7862  		p.binaryMultiplicativeExpression(f, n, "/", t, mode, flags)
  7863  	case cc.MultiplicativeExpressionMod: // MultiplicativeExpression '%' CastExpression
  7864  		p.binaryMultiplicativeExpression(f, n, "%", t, mode, flags)
  7865  	default:
  7866  		panic(todo("%v: internal error: %v", n.Position(), n.Case))
  7867  	}
  7868  }
  7869  
  7870  func (p *project) binaryMultiplicativeExpression(f *function, n *cc.MultiplicativeExpression, oper string, t cc.Type, mode exprMode, flags flags) {
  7871  	// MultiplicativeExpression '*' CastExpression
  7872  	switch mode {
  7873  	case exprValue:
  7874  		p.binaryMultiplicativeExpressionValue(f, n, oper, t, mode, flags)
  7875  	default:
  7876  		panic(todo("", n.Position(), mode))
  7877  	}
  7878  }
  7879  
  7880  func (p *project) binaryMultiplicativeExpressionValue(f *function, n *cc.MultiplicativeExpression, oper string, t cc.Type, mode exprMode, flags flags) {
  7881  	// MultiplicativeExpression '*' CastExpression
  7882  
  7883  	lt := n.MultiplicativeExpression.Operand.Type()
  7884  	rt := n.CastExpression.Operand.Type()
  7885  	switch lk, rk := lt.Kind(), rt.Kind(); {
  7886  	case
  7887  		lk == cc.UInt128 || rk == cc.UInt128,
  7888  		lk == cc.Int128 || rk == cc.Int128:
  7889  
  7890  		p.binaryMultiplicativeExpressionUint128(f, n, oper, t, mode, flags)
  7891  		return
  7892  	}
  7893  
  7894  	defer p.w("%s", p.artithmeticBinaryExpression(n, n.Operand, t, &mode, flags))
  7895  	switch {
  7896  	case intMulOverflows(n, n.Operand, n.MultiplicativeExpression.Operand, n.CastExpression.Operand, oper, n.Promote()):
  7897  		p.multiplicativeExpression(f, n.MultiplicativeExpression, n.Promote(), exprValue, flags|fForceRuntimeConv)
  7898  		p.w(" %s%s", oper, tidyComment(" ", &n.Token))
  7899  		p.castExpression(f, n.CastExpression, n.Promote(), exprValue, flags|fForceRuntimeConv)
  7900  	default:
  7901  		defer p.w("%s", p.bitFieldPatch2(n, n.MultiplicativeExpression.Operand, n.CastExpression.Operand, n.Promote())) //TODO bit field big endian
  7902  		var s string
  7903  		if isRealType(n.Operand) && n.Operand.Value() != nil {
  7904  			s = p.convertNil(n, n.Promote(), flags)
  7905  		}
  7906  		p.multiplicativeExpression(f, n.MultiplicativeExpression, n.Promote(), exprValue, flags)
  7907  		p.w("%s %s%s", s, oper, tidyComment(" ", &n.Token))
  7908  		if (oper == "/" || oper == "%") && (isZeroReal(n.MultiplicativeExpression.Operand) || isZeroReal(n.CastExpression.Operand)) {
  7909  			p.w("%s%sFrom%[2]s(", p.task.crt, p.helperType(n, n.Promote()))
  7910  			defer p.w(")")
  7911  		}
  7912  		p.castExpression(f, n.CastExpression, n.Promote(), exprValue, flags)
  7913  	}
  7914  }
  7915  
  7916  func (p *project) binaryMultiplicativeExpressionUint128(f *function, n *cc.MultiplicativeExpression, oper string, t cc.Type, mode exprMode, flags flags) {
  7917  	// MultiplicativeExpression '*' CastExpression
  7918  	defer p.w("%s", p.artithmeticBinaryExpression(n, n.Operand, t, &mode, flags))
  7919  	p.multiplicativeExpression(f, n.MultiplicativeExpression, n.Promote(), exprValue, flags)
  7920  	switch oper {
  7921  	case "*":
  7922  		p.w(".Mul(")
  7923  	case "/":
  7924  		p.w(".Div(")
  7925  	case "%":
  7926  		p.w(".Mod(")
  7927  	default:
  7928  		panic(todo("%q", oper))
  7929  	}
  7930  	p.castExpression(f, n.CastExpression, n.Promote(), exprValue, flags)
  7931  	p.w(")")
  7932  }
  7933  
  7934  func isZeroReal(op cc.Operand) bool {
  7935  	switch x := op.Value().(type) {
  7936  	case cc.Float32Value:
  7937  		return x == 0
  7938  	case cc.Float64Value:
  7939  		return x == 0
  7940  	default:
  7941  		return false
  7942  	}
  7943  }
  7944  
  7945  func intMulOverflows(n cc.Node, r, lo, ro cc.Operand, oper string, promote cc.Type) bool {
  7946  	if (isReal(lo) && !isInf(lo) || isReal(ro) && !isInf(ro)) && isInf(r) {
  7947  		return true
  7948  	}
  7949  
  7950  	a, b, ok := getIntOperands(lo, ro)
  7951  	if !ok {
  7952  		return false
  7953  	}
  7954  
  7955  	switch oper {
  7956  	case "*":
  7957  		return overflows(a.Mul(a, b), promote)
  7958  	case "/":
  7959  		if b.Sign() == 0 {
  7960  			return true
  7961  		}
  7962  
  7963  		return overflows(a.Div(a, b), promote)
  7964  	case "%":
  7965  		if b.Sign() == 0 {
  7966  			return true
  7967  		}
  7968  
  7969  		return overflows(a.Mod(a, b), promote)
  7970  	default:
  7971  		panic(todo("", pos(n)))
  7972  	}
  7973  }
  7974  
  7975  func isReal(op cc.Operand) bool {
  7976  	switch op.Value().(type) {
  7977  	case cc.Float32Value, cc.Float64Value:
  7978  		return true
  7979  	default:
  7980  		return false
  7981  	}
  7982  }
  7983  
  7984  func isInf(op cc.Operand) bool {
  7985  	switch x := op.Value().(type) {
  7986  	case cc.Float32Value:
  7987  		return math.IsInf(float64(x), 0)
  7988  	case cc.Float64Value:
  7989  		return math.IsInf(float64(x), 0)
  7990  	default:
  7991  		return false
  7992  	}
  7993  }
  7994  
  7995  func (p *project) castExpression(f *function, n *cc.CastExpression, t cc.Type, mode exprMode, flags flags) {
  7996  	if n.Case == cc.CastExpressionCast {
  7997  		if f != nil && n.CastExpression.Operand.Type().Kind() == cc.Ptr { // void *__ccgo_va_arg(__builtin_va_list ap);
  7998  			sv := f.vaType
  7999  			f.vaType = n.TypeName.Type()
  8000  			defer func() { f.vaType = sv }()
  8001  		}
  8002  	}
  8003  	switch mode {
  8004  	case exprValue:
  8005  		p.castExpressionValue(f, n, t, mode, flags)
  8006  	case exprVoid:
  8007  		p.castExpressionVoid(f, n, t, mode, flags)
  8008  	case exprAddrOf:
  8009  		p.castExpressionAddrOf(f, n, t, mode, flags)
  8010  	case exprBool:
  8011  		p.castExpressionBool(f, n, t, mode, flags)
  8012  	case exprLValue:
  8013  		p.castExpressionLValue(f, n, t, mode, flags)
  8014  	case exprPSelect:
  8015  		p.castExpressionPSelect(f, n, t, mode, flags)
  8016  	case exprFunc:
  8017  		p.castExpressionFunc(f, n, t, mode, flags)
  8018  	case exprSelect:
  8019  		p.castExpressionSelect(f, n, t, mode, flags)
  8020  	case exprDecay:
  8021  		p.castExpressionDecay(f, n, t, mode, flags)
  8022  	default:
  8023  		panic(todo("", n.Position(), mode))
  8024  	}
  8025  }
  8026  
  8027  func (p *project) castExpressionDecay(f *function, n *cc.CastExpression, t cc.Type, mode exprMode, flags flags) {
  8028  	switch n.Case {
  8029  	case cc.CastExpressionUnary: // UnaryExpression
  8030  		p.unaryExpression(f, n.UnaryExpression, t, mode, flags)
  8031  	case cc.CastExpressionCast: // '(' TypeName ')' CastExpression
  8032  		panic(todo("", p.pos(n)))
  8033  	default:
  8034  		panic(todo("%v: internal error: %v", n.Position(), n.Case))
  8035  	}
  8036  }
  8037  
  8038  func (p *project) castExpressionSelect(f *function, n *cc.CastExpression, t cc.Type, mode exprMode, flags flags) {
  8039  	switch n.Case {
  8040  	case cc.CastExpressionUnary: // UnaryExpression
  8041  		p.unaryExpression(f, n.UnaryExpression, t, mode, flags)
  8042  	case cc.CastExpressionCast: // '(' TypeName ')' CastExpression
  8043  		p.castExpression(f, n.CastExpression, n.TypeName.Type(), mode, flags)
  8044  	default:
  8045  		panic(todo("%v: internal error: %v", n.Position(), n.Case))
  8046  	}
  8047  }
  8048  
  8049  func (p *project) castExpressionFunc(f *function, n *cc.CastExpression, t cc.Type, mode exprMode, flags flags) {
  8050  	switch n.Case {
  8051  	case cc.CastExpressionUnary: // UnaryExpression
  8052  		p.unaryExpression(f, n.UnaryExpression, t, mode, flags)
  8053  	case cc.CastExpressionCast: // '(' TypeName ')' CastExpression
  8054  		ot := n.CastExpression.Operand.Type()
  8055  		tn := n.TypeName.Type()
  8056  		var ft cc.Type
  8057  		switch tn.Kind() {
  8058  		case cc.Ptr:
  8059  			switch et := ot.Elem(); et.Kind() {
  8060  			case cc.Function, cc.Void:
  8061  				// ok
  8062  			default:
  8063  				panic(todo("", p.pos(n), et, et.Kind()))
  8064  			}
  8065  		default:
  8066  			panic(todo("%v: %v, %v -> %v, %v -> %v, %v", p.pos(n), ot, ot.Kind(), tn, tn.Kind(), t, t.Kind()))
  8067  		}
  8068  		switch t.Kind() {
  8069  		case cc.Ptr:
  8070  			switch et := t.Elem(); et.Kind() {
  8071  			case cc.Function:
  8072  				ft = et
  8073  			default:
  8074  				panic(todo("", p.pos(n), et, et.Kind()))
  8075  			}
  8076  		default:
  8077  			panic(todo("%v: %v, %v -> %v, %v -> %v, %v", p.pos(n), ot, ot.Kind(), tn, tn.Kind(), t, t.Kind()))
  8078  		}
  8079  		switch ot.Kind() {
  8080  		case cc.Ptr:
  8081  			switch et := ot.Elem(); et.Kind() {
  8082  			case cc.Function, cc.Void:
  8083  				p.w("(*(*")
  8084  				p.functionSignature(n, f, ft, "")
  8085  				p.w(")(unsafe.Pointer(")
  8086  				p.castExpression(f, n.CastExpression, ot, exprAddrOf, flags)
  8087  				p.w(")))")
  8088  			default:
  8089  				panic(todo("", p.pos(n), et, et.Kind()))
  8090  			}
  8091  		default:
  8092  			panic(todo("%v: %v, %v -> %v, %v -> %v, %v", p.pos(n), ot, ot.Kind(), tn, tn.Kind(), t, t.Kind()))
  8093  		}
  8094  	default:
  8095  		panic(todo("%v: internal error: %v", n.Position(), n.Case))
  8096  	}
  8097  }
  8098  
  8099  func (p *project) castExpressionPSelect(f *function, n *cc.CastExpression, t cc.Type, mode exprMode, flags flags) {
  8100  	switch n.Case {
  8101  	case cc.CastExpressionUnary: // UnaryExpression
  8102  		p.unaryExpression(f, n.UnaryExpression, t, mode, flags)
  8103  	case cc.CastExpressionCast: // '(' TypeName ')' CastExpression
  8104  		p.castExpression(f, n.CastExpression, n.TypeName.Type(), mode, flags)
  8105  	default:
  8106  		panic(todo("%v: internal error: %v", n.Position(), n.Case))
  8107  	}
  8108  }
  8109  
  8110  func (p *project) castExpressionLValue(f *function, n *cc.CastExpression, t cc.Type, mode exprMode, flags flags) {
  8111  	switch n.Case {
  8112  	case cc.CastExpressionUnary: // UnaryExpression
  8113  		p.unaryExpression(f, n.UnaryExpression, t, mode, flags)
  8114  	case cc.CastExpressionCast: // '(' TypeName ')' CastExpression
  8115  		panic(todo("", p.pos(n)))
  8116  	default:
  8117  		panic(todo("%v: internal error: %v", n.Position(), n.Case))
  8118  	}
  8119  }
  8120  
  8121  func (p *project) castExpressionBool(f *function, n *cc.CastExpression, t cc.Type, mode exprMode, flags flags) {
  8122  	switch n.Case {
  8123  	case cc.CastExpressionUnary: // UnaryExpression
  8124  		p.unaryExpression(f, n.UnaryExpression, t, mode, flags)
  8125  	case cc.CastExpressionCast: // '(' TypeName ')' CastExpression
  8126  		p.w("(")
  8127  		defer p.w(")")
  8128  		defer p.w(" != 0 ")
  8129  		p.castExpression(f, n, n.Operand.Type(), exprValue, flags)
  8130  	default:
  8131  		panic(todo("%v: internal error: %v", n.Position(), n.Case))
  8132  	}
  8133  }
  8134  
  8135  func (p *project) castExpressionAddrOf(f *function, n *cc.CastExpression, t cc.Type, mode exprMode, flags flags) {
  8136  	switch n.Case {
  8137  	case cc.CastExpressionUnary: // UnaryExpression
  8138  		p.unaryExpression(f, n.UnaryExpression, t, mode, flags)
  8139  	case cc.CastExpressionCast: // '(' TypeName ')' CastExpression
  8140  		p.castExpressionAddrOf(f, n.CastExpression, t, mode, flags)
  8141  	default:
  8142  		panic(todo("%v: internal error: %v", n.Position(), n.Case))
  8143  	}
  8144  }
  8145  
  8146  func (p *project) castExpressionVoid(f *function, n *cc.CastExpression, t cc.Type, mode exprMode, flags flags) {
  8147  	switch n.Case {
  8148  	case cc.CastExpressionUnary: // UnaryExpression
  8149  		p.unaryExpression(f, n.UnaryExpression, t, mode, flags)
  8150  	case cc.CastExpressionCast: // '(' TypeName ')' CastExpression
  8151  		p.castExpression(f, n.CastExpression, t, mode, flags)
  8152  	default:
  8153  		panic(todo("%v: internal error: %v", n.Position(), n.Case))
  8154  	}
  8155  }
  8156  
  8157  func (p *project) castExpressionValue(f *function, n *cc.CastExpression, t cc.Type, mode exprMode, flags flags) {
  8158  	switch n.Case {
  8159  	case cc.CastExpressionUnary: // UnaryExpression
  8160  		p.unaryExpression(f, n.UnaryExpression, t, mode, flags)
  8161  	case cc.CastExpressionCast: // '(' TypeName ')' CastExpression
  8162  		if f != nil && p.pass1 && n.TypeName.Type().IsIntegerType() && n.CastExpression.Operand.Type().Kind() == cc.Array {
  8163  			if d := n.CastExpression.Declarator(); d != nil {
  8164  				f.pin(n, d)
  8165  			}
  8166  		}
  8167  		switch k := p.opKind(f, n.CastExpression, n.CastExpression.Operand.Type()); k {
  8168  		case opNormal, opBitfield:
  8169  			p.castExpressionValueNormal(f, n, t, mode, flags)
  8170  		case opArray:
  8171  			p.castExpressionValueArray(f, n, t, mode, flags)
  8172  		case opFunction:
  8173  			p.castExpressionValueFunction(f, n, t, mode, flags)
  8174  		case opArrayParameter:
  8175  			p.castExpressionValueNormal(f, n, t, mode, flags)
  8176  		default:
  8177  			panic(todo("", n.Position(), k))
  8178  		}
  8179  	default:
  8180  		panic(todo("%v: internal error: %v", n.Position(), n.Case))
  8181  	}
  8182  }
  8183  
  8184  func (p *project) castExpressionValueArrayParameter(f *function, n *cc.CastExpression, t cc.Type, mode exprMode, flags flags) {
  8185  	// '(' TypeName ')' CastExpression
  8186  	tn := n.TypeName.Type()
  8187  	defer p.w("%s", p.convertType(n, tn, t, flags))
  8188  	p.castExpression(f, n.CastExpression, tn, mode, flags)
  8189  }
  8190  
  8191  func (p *project) castExpressionValueFunction(f *function, n *cc.CastExpression, t cc.Type, mode exprMode, flags flags) {
  8192  	// '(' TypeName ')' CastExpression
  8193  	op := n.CastExpression.Operand
  8194  	tn := n.TypeName.Type()
  8195  	switch {
  8196  	case op.Type().Kind() == cc.Function:
  8197  		switch {
  8198  		case tn.Kind() == cc.Ptr && t.Kind() == cc.Ptr:
  8199  			p.castExpression(f, n.CastExpression, op.Type(), exprValue, flags)
  8200  		case tn.IsIntegerType():
  8201  			p.w("%s(", p.typ(n, tn))
  8202  			p.castExpression(f, n.CastExpression, op.Type(), exprValue, flags)
  8203  			p.w(")")
  8204  		default:
  8205  			panic(todo("%v: tn %v expr %v", n.Position(), tn, op.Type()))
  8206  		}
  8207  	default:
  8208  		panic(todo("%v: %v -> %v -> %v", p.pos(n), op.Type(), tn, t))
  8209  	}
  8210  }
  8211  
  8212  func (p *project) castExpressionValueArray(f *function, n *cc.CastExpression, t cc.Type, mode exprMode, flags flags) {
  8213  	// '(' TypeName ')' CastExpression
  8214  	tn := n.TypeName.Type()
  8215  	switch {
  8216  	case tn.IsScalarType():
  8217  		defer p.w("%s", p.convertType(n, nil, t, flags))
  8218  		p.castExpression(f, n.CastExpression, tn, exprDecay, flags)
  8219  	default:
  8220  		panic(todo("", p.pos(n)))
  8221  	}
  8222  }
  8223  
  8224  func (p *project) castExpressionValueNormal(f *function, n *cc.CastExpression, t cc.Type, mode exprMode, flags flags) {
  8225  	// '(' TypeName ')' CastExpression
  8226  	op := n.CastExpression.Operand
  8227  	tn := n.TypeName.Type()
  8228  	switch {
  8229  	case op.Type().Kind() == cc.Ptr && tn.IsArithmeticType():
  8230  		defer p.w("%s", p.convertType(n, nil, t, flags|fForceConv))
  8231  		p.castExpression(f, n.CastExpression, op.Type(), mode, flags)
  8232  	case tn.IsArithmeticType():
  8233  		switch {
  8234  		case (tn.Kind() == cc.Float || tn.Kind() == cc.Double) && op.Type().IsIntegerType() && op.Value() != nil && t.IsIntegerType():
  8235  			panic(todo("", p.pos(n)))
  8236  		case isNegativeInt(op) && isUnsigned(t):
  8237  			defer p.w("%s", p.convertType(n, tn, t, flags|fForceConv))
  8238  			p.castExpression(f, n.CastExpression, tn, exprValue, flags)
  8239  		default:
  8240  			defer p.w("%s", p.convertType(n, tn, t, flags))
  8241  			p.castExpression(f, n.CastExpression, tn, exprValue, flags)
  8242  		}
  8243  	default:
  8244  		switch tn.Kind() {
  8245  		case cc.Ptr:
  8246  			switch {
  8247  			case t.Kind() == cc.Ptr && isNegativeInt(op):
  8248  				p.w("%s(", p.helperType2(n, op.Type(), tn))
  8249  				defer p.w(")")
  8250  				p.castExpression(f, n.CastExpression, op.Type(), mode, flags)
  8251  			default:
  8252  				defer p.w("%s", p.convertType(n, tn, t, flags))
  8253  				p.castExpression(f, n.CastExpression, tn, mode, flags)
  8254  			}
  8255  		case cc.Void:
  8256  			p.castExpression(f, n.CastExpression, tn, exprVoid, flags)
  8257  		default:
  8258  			panic(todo("%s: %s %s -> %s %s -> %s %s", n.Position(), op.Type(), op.Type().Kind(), tn, tn.Kind(), t, t.Kind()))
  8259  		}
  8260  	}
  8261  }
  8262  
  8263  func (p *project) unaryExpression(f *function, n *cc.UnaryExpression, t cc.Type, mode exprMode, flags flags) {
  8264  	switch mode {
  8265  	case exprLValue:
  8266  		p.unaryExpressionLValue(f, n, t, mode, flags)
  8267  	case exprValue:
  8268  		p.unaryExpressionValue(f, n, t, mode, flags)
  8269  	case exprVoid:
  8270  		p.unaryExpressionVoid(f, n, t, mode, flags)
  8271  	case exprAddrOf:
  8272  		p.unaryExpressionAddrOf(f, n, t, mode, flags)
  8273  	case exprBool:
  8274  		p.unaryExpressionBool(f, n, t, mode, flags)
  8275  	case exprPSelect:
  8276  		p.unaryExpressionPSelect(f, n, t, mode, flags)
  8277  	case exprFunc:
  8278  		p.unaryExpressionFunc(f, n, t, mode, flags)
  8279  	case exprSelect:
  8280  		p.unaryExpressionSelect(f, n, t, mode, flags)
  8281  	case exprDecay:
  8282  		p.unaryExpressionDecay(f, n, t, mode, flags)
  8283  	default:
  8284  		panic(todo("", n.Position(), mode))
  8285  	}
  8286  }
  8287  
  8288  func (p *project) unaryExpressionDecay(f *function, n *cc.UnaryExpression, t cc.Type, mode exprMode, flags flags) {
  8289  	switch n.Case {
  8290  	case cc.UnaryExpressionPostfix: // PostfixExpression
  8291  		p.postfixExpression(f, n.PostfixExpression, t, mode, flags)
  8292  	case cc.UnaryExpressionInc: // "++" UnaryExpression
  8293  		panic(todo("", p.pos(n)))
  8294  	case cc.UnaryExpressionDec: // "--" UnaryExpression
  8295  		panic(todo("", p.pos(n)))
  8296  	case cc.UnaryExpressionAddrof: // '&' CastExpression
  8297  		panic(todo("", p.pos(n)))
  8298  	case cc.UnaryExpressionDeref: // '*' CastExpression
  8299  		p.castExpression(f, n.CastExpression, n.CastExpression.Operand.Type(), exprValue, flags)
  8300  	case cc.UnaryExpressionPlus: // '+' CastExpression
  8301  		panic(todo("", p.pos(n)))
  8302  	case cc.UnaryExpressionMinus: // '-' CastExpression
  8303  		panic(todo("", p.pos(n)))
  8304  	case cc.UnaryExpressionCpl: // '~' CastExpression
  8305  		panic(todo("", p.pos(n)))
  8306  	case cc.UnaryExpressionNot: // '!' CastExpression
  8307  		panic(todo("", p.pos(n)))
  8308  	case cc.UnaryExpressionSizeofExpr: // "sizeof" UnaryExpression
  8309  		panic(todo("", p.pos(n)))
  8310  	case cc.UnaryExpressionSizeofType: // "sizeof" '(' TypeName ')'
  8311  		panic(todo("", p.pos(n)))
  8312  	case cc.UnaryExpressionLabelAddr: // "&&" IDENTIFIER
  8313  		panic(todo("", p.pos(n)))
  8314  	case cc.UnaryExpressionAlignofExpr: // "_Alignof" UnaryExpression
  8315  		panic(todo("", p.pos(n)))
  8316  	case cc.UnaryExpressionAlignofType: // "_Alignof" '(' TypeName ')'
  8317  		panic(todo("", p.pos(n)))
  8318  	case cc.UnaryExpressionImag: // "__imag__" UnaryExpression
  8319  		panic(todo("", p.pos(n)))
  8320  	case cc.UnaryExpressionReal: // "__real__" UnaryExpression
  8321  		panic(todo("", p.pos(n)))
  8322  	default:
  8323  		panic(todo("%v: internal error: %v", n.Position(), n.Case))
  8324  	}
  8325  }
  8326  
  8327  func (p *project) unaryExpressionSelect(f *function, n *cc.UnaryExpression, t cc.Type, mode exprMode, flags flags) {
  8328  	switch n.Case {
  8329  	case cc.UnaryExpressionPostfix: // PostfixExpression
  8330  		p.postfixExpression(f, n.PostfixExpression, t, mode, flags)
  8331  	case cc.UnaryExpressionInc: // "++" UnaryExpression
  8332  		panic(todo("", n.Position()))
  8333  	case cc.UnaryExpressionDec: // "--" UnaryExpression
  8334  		panic(todo("", n.Position()))
  8335  	case cc.UnaryExpressionAddrof: // '&' CastExpression
  8336  		panic(todo("", p.pos(n)))
  8337  	case cc.UnaryExpressionDeref: // '*' CastExpression
  8338  		ot := n.CastExpression.Operand.Type()
  8339  		switch ot.Kind() {
  8340  		case cc.Ptr:
  8341  			switch et := ot.Elem(); et.Kind() {
  8342  			case
  8343  				cc.Struct,
  8344  				cc.Union:
  8345  
  8346  				p.w("(*(*%s)(unsafe.Pointer(", p.typ(n, n.Operand.Type()))
  8347  				p.castExpression(f, n.CastExpression, n.CastExpression.Operand.Type(), exprValue, flags)
  8348  				p.w(")))")
  8349  			default:
  8350  				panic(todo("", p.pos(n), et, et.Kind()))
  8351  			}
  8352  		case cc.Array:
  8353  			p.w("(*(*%s)(unsafe.Pointer(", p.typ(n, n.Operand.Type()))
  8354  			p.castExpression(f, n.CastExpression, n.CastExpression.Operand.Type(), exprAddrOf, flags)
  8355  			p.w(")))")
  8356  		default:
  8357  			panic(todo("", p.pos(n), ot, ot.Kind()))
  8358  		}
  8359  	case cc.UnaryExpressionPlus: // '+' CastExpression
  8360  		panic(todo("", p.pos(n)))
  8361  	case cc.UnaryExpressionMinus: // '-' CastExpression
  8362  		panic(todo("", p.pos(n)))
  8363  	case cc.UnaryExpressionCpl: // '~' CastExpression
  8364  		panic(todo("", p.pos(n)))
  8365  	case cc.UnaryExpressionNot: // '!' CastExpression
  8366  		panic(todo("", p.pos(n)))
  8367  	case cc.UnaryExpressionSizeofExpr: // "sizeof" UnaryExpression
  8368  		panic(todo("", p.pos(n)))
  8369  	case cc.UnaryExpressionSizeofType: // "sizeof" '(' TypeName ')'
  8370  		panic(todo("", p.pos(n)))
  8371  	case cc.UnaryExpressionLabelAddr: // "&&" IDENTIFIER
  8372  		panic(todo("", p.pos(n)))
  8373  	case cc.UnaryExpressionAlignofExpr: // "_Alignof" UnaryExpression
  8374  		panic(todo("", p.pos(n)))
  8375  	case cc.UnaryExpressionAlignofType: // "_Alignof" '(' TypeName ')'
  8376  		panic(todo("", p.pos(n)))
  8377  	case cc.UnaryExpressionImag: // "__imag__" UnaryExpression
  8378  		panic(todo("", p.pos(n)))
  8379  	case cc.UnaryExpressionReal: // "__real__" UnaryExpression
  8380  		panic(todo("", p.pos(n)))
  8381  	default:
  8382  		panic(todo("%v: internal error: %v", n.Position(), n.Case))
  8383  	}
  8384  }
  8385  
  8386  func (p *project) unaryExpressionFunc(f *function, n *cc.UnaryExpression, t cc.Type, mode exprMode, flags flags) {
  8387  	switch n.Case {
  8388  	case cc.UnaryExpressionPostfix: // PostfixExpression
  8389  		p.postfixExpression(f, n.PostfixExpression, t, mode, flags)
  8390  	case cc.UnaryExpressionInc: // "++" UnaryExpression
  8391  		panic(todo("", p.pos(n)))
  8392  	case cc.UnaryExpressionDec: // "--" UnaryExpression
  8393  		panic(todo("", p.pos(n)))
  8394  	case cc.UnaryExpressionAddrof: // '&' CastExpression
  8395  		panic(todo("", p.pos(n)))
  8396  	case cc.UnaryExpressionDeref: // '*' CastExpression
  8397  		ot := n.CastExpression.Operand.Type()
  8398  		switch ot.Kind() {
  8399  		case cc.Ptr:
  8400  			switch et := ot.Elem(); et.Kind() {
  8401  			case cc.Function:
  8402  				p.castExpression(f, n.CastExpression, ot, mode, flags|fAddrOfFuncPtrOk)
  8403  			case cc.Ptr:
  8404  				switch et2 := et.Elem(); et2.Kind() {
  8405  				case cc.Function:
  8406  					// C: (**)()
  8407  					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)
  8408  				default:
  8409  					panic(todo("", p.pos(n), et2, et2.Kind()))
  8410  				}
  8411  			default:
  8412  				panic(todo("", p.pos(n), et, et.Kind()))
  8413  			}
  8414  		case cc.Function:
  8415  			p.castExpression(f, n.CastExpression, ot, mode, flags|fAddrOfFuncPtrOk)
  8416  		default:
  8417  			panic(todo("", p.pos(n), ot, ot.Kind(), mode))
  8418  		}
  8419  	case cc.UnaryExpressionPlus: // '+' CastExpression
  8420  		panic(todo("", p.pos(n)))
  8421  	case cc.UnaryExpressionMinus: // '-' CastExpression
  8422  		panic(todo("", p.pos(n)))
  8423  	case cc.UnaryExpressionCpl: // '~' CastExpression
  8424  		panic(todo("", p.pos(n)))
  8425  	case cc.UnaryExpressionNot: // '!' CastExpression
  8426  		panic(todo("", p.pos(n)))
  8427  	case cc.UnaryExpressionSizeofExpr: // "sizeof" UnaryExpression
  8428  		panic(todo("", p.pos(n)))
  8429  	case cc.UnaryExpressionSizeofType: // "sizeof" '(' TypeName ')'
  8430  		panic(todo("", p.pos(n)))
  8431  	case cc.UnaryExpressionLabelAddr: // "&&" IDENTIFIER
  8432  		panic(todo("", p.pos(n)))
  8433  	case cc.UnaryExpressionAlignofExpr: // "_Alignof" UnaryExpression
  8434  		panic(todo("", p.pos(n)))
  8435  	case cc.UnaryExpressionAlignofType: // "_Alignof" '(' TypeName ')'
  8436  		panic(todo("", p.pos(n)))
  8437  	case cc.UnaryExpressionImag: // "__imag__" UnaryExpression
  8438  		panic(todo("", p.pos(n)))
  8439  	case cc.UnaryExpressionReal: // "__real__" UnaryExpression
  8440  		panic(todo("", p.pos(n)))
  8441  	default:
  8442  		panic(todo("%v: internal error: %v", n.Position(), n.Case))
  8443  	}
  8444  }
  8445  
  8446  func (p *project) unaryExpressionPSelect(f *function, n *cc.UnaryExpression, t cc.Type, mode exprMode, flags flags) {
  8447  	switch n.Case {
  8448  	case cc.UnaryExpressionPostfix: // PostfixExpression
  8449  		p.postfixExpression(f, n.PostfixExpression, t, mode, flags)
  8450  	case cc.UnaryExpressionInc: // "++" UnaryExpression
  8451  		panic(todo("", n.Position()))
  8452  	case cc.UnaryExpressionDec: // "--" UnaryExpression
  8453  		panic(todo("", n.Position()))
  8454  	case cc.UnaryExpressionAddrof: // '&' CastExpression
  8455  		panic(todo("", n.Position()))
  8456  		//TODO- p.w("(*%s)(unsafe.Pointer(", p.typ(n, n.Operand.Type().Elem()))
  8457  		//TODO- p.unaryExpression(f, n, t, exprValue, flags)
  8458  		//TODO- p.w("))")
  8459  	case cc.UnaryExpressionDeref: // '*' CastExpression
  8460  		panic(todo("", n.Position()))
  8461  		//TODO- ot := n.CastExpression.Operand.Type()
  8462  		//TODO- switch ot.Kind() {
  8463  		//TODO- case cc.Ptr:
  8464  		//TODO- 	switch et := ot.Elem(); {
  8465  		//TODO- 	case et.Kind() == cc.Ptr:
  8466  		//TODO- 		switch et2 := et.Elem(); et2.Kind() {
  8467  		//TODO- 		case cc.Struct:
  8468  		//TODO- 			if et2.IsIncomplete() {
  8469  		//TODO- 				p.w("(*(**uintptr)(unsafe.Pointer(")
  8470  		//TODO- 				p.castExpression(f, n.CastExpression, t, exprValue, flags)
  8471  		//TODO- 				p.w(")))")
  8472  		//TODO- 				break
  8473  		//TODO- 			}
  8474  
  8475  		//TODO- 			p.w("(*(**%s)(unsafe.Pointer(", p.typ(n, n.Operand.Type().Elem()))
  8476  		//TODO- 			p.castExpression(f, n.CastExpression, t, exprValue, flags)
  8477  		//TODO- 			p.w(")))")
  8478  		//TODO- 		default:
  8479  		//TODO- 			panic(todo("", p.pos(n), et2, et2.Kind()))
  8480  		//TODO- 		}
  8481  		//TODO- 	default:
  8482  		//TODO- 		panic(todo("", p.pos(n), et, et.Kind()))
  8483  		//TODO- 	}
  8484  		//TODO- default:
  8485  		//TODO- 	panic(todo("", p.pos(n), ot, ot.Kind()))
  8486  		//TODO- }
  8487  	case cc.UnaryExpressionPlus: // '+' CastExpression
  8488  		panic(todo("", p.pos(n)))
  8489  	case cc.UnaryExpressionMinus: // '-' CastExpression
  8490  		panic(todo("", p.pos(n)))
  8491  	case cc.UnaryExpressionCpl: // '~' CastExpression
  8492  		panic(todo("", p.pos(n)))
  8493  	case cc.UnaryExpressionNot: // '!' CastExpression
  8494  		panic(todo("", p.pos(n)))
  8495  	case cc.UnaryExpressionSizeofExpr: // "sizeof" UnaryExpression
  8496  		panic(todo("", p.pos(n)))
  8497  	case cc.UnaryExpressionSizeofType: // "sizeof" '(' TypeName ')'
  8498  		panic(todo("", p.pos(n)))
  8499  	case cc.UnaryExpressionLabelAddr: // "&&" IDENTIFIER
  8500  		panic(todo("", p.pos(n)))
  8501  	case cc.UnaryExpressionAlignofExpr: // "_Alignof" UnaryExpression
  8502  		panic(todo("", p.pos(n)))
  8503  	case cc.UnaryExpressionAlignofType: // "_Alignof" '(' TypeName ')'
  8504  		panic(todo("", p.pos(n)))
  8505  	case cc.UnaryExpressionImag: // "__imag__" UnaryExpression
  8506  		panic(todo("", p.pos(n)))
  8507  	case cc.UnaryExpressionReal: // "__real__" UnaryExpression
  8508  		panic(todo("", p.pos(n)))
  8509  	default:
  8510  		panic(todo("%v: internal error: %v", n.Position(), n.Case))
  8511  	}
  8512  }
  8513  
  8514  func (p *project) unaryExpressionBool(f *function, n *cc.UnaryExpression, t cc.Type, mode exprMode, flags flags) {
  8515  	switch n.Case {
  8516  	case cc.UnaryExpressionPostfix: // PostfixExpression
  8517  		p.postfixExpression(f, n.PostfixExpression, t, mode, flags)
  8518  	case cc.UnaryExpressionNot: // '!' CastExpression
  8519  		p.w("!(")
  8520  		p.castExpression(f, n.CastExpression, t, mode, flags)
  8521  		p.w(")")
  8522  	default:
  8523  		p.w("(")
  8524  		defer p.w(")")
  8525  		defer p.w(" != 0 ")
  8526  		p.unaryExpression(f, n, t, exprValue, flags)
  8527  	}
  8528  }
  8529  
  8530  func (p *project) unaryExpressionAddrOf(f *function, n *cc.UnaryExpression, t cc.Type, mode exprMode, flags flags) {
  8531  	switch n.Case {
  8532  	case cc.UnaryExpressionPostfix: // PostfixExpression
  8533  		p.postfixExpression(f, n.PostfixExpression, t, mode, flags)
  8534  	case cc.UnaryExpressionInc: // "++" UnaryExpression
  8535  		panic(todo("", n.Position()))
  8536  	case cc.UnaryExpressionDec: // "--" UnaryExpression
  8537  		panic(todo("", n.Position()))
  8538  	case cc.UnaryExpressionAddrof: // '&' CastExpression
  8539  		panic(todo("", n.Position()))
  8540  	case cc.UnaryExpressionDeref: // '*' CastExpression
  8541  		ot := n.CastExpression.Operand.Type()
  8542  		switch ot.Kind() {
  8543  		case cc.Ptr:
  8544  			switch et := ot.Elem(); {
  8545  			case
  8546  				et.IsScalarType(),
  8547  				et.Kind() == cc.Struct,
  8548  				et.Kind() == cc.Union,
  8549  				et.Kind() == cc.Array:
  8550  
  8551  				p.unaryExpressionDeref(f, n, t, mode, flags)
  8552  			default:
  8553  				panic(todo("", p.pos(n), et, et.Kind()))
  8554  			}
  8555  		default:
  8556  			panic(todo("", p.pos(n), ot, ot.Kind()))
  8557  		}
  8558  	case cc.UnaryExpressionPlus: // '+' CastExpression
  8559  		panic(todo("", n.Position()))
  8560  	case cc.UnaryExpressionMinus: // '-' CastExpression
  8561  		panic(todo("", n.Position()))
  8562  	case cc.UnaryExpressionCpl: // '~' CastExpression
  8563  		panic(todo("", n.Position()))
  8564  	case cc.UnaryExpressionNot: // '!' CastExpression
  8565  		panic(todo("", n.Position()))
  8566  	case cc.UnaryExpressionSizeofExpr: // "sizeof" UnaryExpression
  8567  		panic(todo("", n.Position()))
  8568  	case cc.UnaryExpressionSizeofType: // "sizeof" '(' TypeName ')'
  8569  		panic(todo("", n.Position()))
  8570  	case cc.UnaryExpressionLabelAddr: // "&&" IDENTIFIER
  8571  		panic(todo("", n.Position()))
  8572  	case cc.UnaryExpressionAlignofExpr: // "_Alignof" UnaryExpression
  8573  		panic(todo("", n.Position()))
  8574  	case cc.UnaryExpressionAlignofType: // "_Alignof" '(' TypeName ')'
  8575  		panic(todo("", n.Position()))
  8576  	case cc.UnaryExpressionImag: // "__imag__" UnaryExpression
  8577  		panic(todo("", n.Position()))
  8578  	case cc.UnaryExpressionReal: // "__real__" UnaryExpression
  8579  		panic(todo("", n.Position()))
  8580  	default:
  8581  		panic(todo("%v: internal error: %v", n.Position(), n.Case))
  8582  	}
  8583  }
  8584  
  8585  func (p *project) unaryExpressionVoid(f *function, n *cc.UnaryExpression, t cc.Type, mode exprMode, flags flags) {
  8586  	switch n.Case {
  8587  	case cc.UnaryExpressionPostfix: // PostfixExpression
  8588  		p.postfixExpression(f, n.PostfixExpression, t, mode, flags)
  8589  	case cc.UnaryExpressionInc: // "++" UnaryExpression
  8590  		p.unaryExpressionPreIncDec(f, n, "++", "+=", t, mode, flags)
  8591  	case cc.UnaryExpressionDec: // "--" UnaryExpression
  8592  		p.unaryExpressionPreIncDec(f, n, "--", "-=", t, mode, flags)
  8593  	case cc.UnaryExpressionAddrof: // '&' CastExpression
  8594  		p.w("_ = ")
  8595  		switch {
  8596  		case n.CastExpression.Operand.Type().Kind() == cc.Array:
  8597  			panic(todo("", p.pos(n)))
  8598  		default:
  8599  			p.castExpression(f, n.CastExpression, n.CastExpression.Operand.Type(), exprAddrOf, flags)
  8600  		}
  8601  	case cc.UnaryExpressionDeref: // '*' CastExpression
  8602  		p.w("_ = *(*byte)(unsafe.Pointer(")
  8603  		p.castExpression(f, n.CastExpression, n.CastExpression.Operand.Type(), exprValue, flags)
  8604  		p.w("))")
  8605  	case
  8606  		cc.UnaryExpressionPlus,  // '+' CastExpression
  8607  		cc.UnaryExpressionMinus, // '-' CastExpression
  8608  		cc.UnaryExpressionNot,   // '!' CastExpression
  8609  		cc.UnaryExpressionCpl:   // '~' CastExpression
  8610  
  8611  		p.w("_ = ")
  8612  		defer p.w("%s", p.convert(n, n.CastExpression.Operand, p.intType, flags))
  8613  		p.castExpression(f, n.CastExpression, n.CastExpression.Operand.Type(), exprValue, flags)
  8614  	case cc.UnaryExpressionSizeofExpr: // "sizeof" UnaryExpression
  8615  		// nop
  8616  	case cc.UnaryExpressionSizeofType: // "sizeof" '(' TypeName ')'
  8617  		// nop
  8618  	case cc.UnaryExpressionLabelAddr: // "&&" IDENTIFIER
  8619  		panic(todo("", n.Position()))
  8620  	case cc.UnaryExpressionAlignofExpr: // "_Alignof" UnaryExpression
  8621  		panic(todo("", n.Position()))
  8622  	case cc.UnaryExpressionAlignofType: // "_Alignof" '(' TypeName ')'
  8623  		panic(todo("", n.Position()))
  8624  	case cc.UnaryExpressionImag: // "__imag__" UnaryExpression
  8625  		panic(todo("", n.Position()))
  8626  	case cc.UnaryExpressionReal: // "__real__" UnaryExpression
  8627  		panic(todo("", n.Position()))
  8628  	default:
  8629  		panic(todo("%v: internal error: %v", n.Position(), n.Case))
  8630  	}
  8631  }
  8632  
  8633  func (p *project) unaryExpressionValue(f *function, n *cc.UnaryExpression, t cc.Type, mode exprMode, flags flags) {
  8634  	switch n.Case {
  8635  	case cc.UnaryExpressionPostfix: // PostfixExpression
  8636  		p.postfixExpression(f, n.PostfixExpression, t, mode, flags)
  8637  	case cc.UnaryExpressionInc: // "++" UnaryExpression
  8638  		p.unaryExpressionPreIncDec(f, n, "++", "+=", t, mode, flags)
  8639  	case cc.UnaryExpressionDec: // "--" UnaryExpression
  8640  		p.unaryExpressionPreIncDec(f, n, "--", "-=", t, mode, flags)
  8641  	case cc.UnaryExpressionAddrof: // '&' CastExpression
  8642  		if t.Kind() != cc.Ptr {
  8643  			defer p.w("%s", p.convert(n, n.Operand, t, flags))
  8644  		}
  8645  		switch {
  8646  		case n.CastExpression.Operand.Type().Kind() == cc.Array:
  8647  			panic(todo("", p.pos(n)))
  8648  		default:
  8649  			p.castExpression(f, n.CastExpression, n.CastExpression.Operand.Type(), exprAddrOf, flags)
  8650  		}
  8651  	case cc.UnaryExpressionDeref: // '*' CastExpression
  8652  		ot := n.CastExpression.Operand.Type()
  8653  		switch ot.Kind() {
  8654  		case cc.Ptr, cc.Array:
  8655  			switch et := ot.Elem(); {
  8656  			case
  8657  				et.IsScalarType(),
  8658  				et.Kind() == cc.Array,
  8659  				et.Kind() == cc.Struct,
  8660  				et.Kind() == cc.Union:
  8661  
  8662  				p.unaryExpressionDeref(f, n, t, mode, flags)
  8663  			case et.Kind() == cc.Function:
  8664  				p.castExpression(f, n.CastExpression, t, mode, flags)
  8665  			default:
  8666  				panic(todo("", p.pos(n), et, et.Kind()))
  8667  			}
  8668  		default:
  8669  			panic(todo("", p.pos(n), ot, ot.Kind()))
  8670  		}
  8671  	case cc.UnaryExpressionPlus: // '+' CastExpression
  8672  		p.w(" +")
  8673  		p.castExpression(f, n.CastExpression, t, mode, flags)
  8674  	case cc.UnaryExpressionMinus: // '-' CastExpression
  8675  		switch {
  8676  		case isNonNegativeInt(n.CastExpression.Operand) && t.Kind() == cc.Ptr:
  8677  			p.w(" -%sUintptr(", p.task.crt)
  8678  			p.castExpression(f, n.CastExpression, n.CastExpression.Operand.Type(), exprValue, flags)
  8679  			p.w(")")
  8680  		case isZeroReal(n.CastExpression.Operand):
  8681  			p.w(" -")
  8682  			defer p.w("%s", p.convert(n, n.CastExpression.Operand, t, flags))
  8683  			p.w("%s%sFrom%[2]s(", p.task.crt, p.helperType(n, n.CastExpression.Operand.Type()))
  8684  			p.castExpression(f, n.CastExpression, n.CastExpression.Operand.Type(), exprValue, flags)
  8685  			p.w(")")
  8686  		case isNonNegativeInt(n.CastExpression.Operand) && isUnsigned(n.Operand.Type()):
  8687  			defer p.w("%s", p.convert(n, n.CastExpression.Operand, t, flags))
  8688  			p.w("%sNeg%s(", p.task.crt, p.helperType(n, n.CastExpression.Operand.Type()))
  8689  			p.castExpression(f, n.CastExpression, n.CastExpression.Operand.Type(), exprValue, flags)
  8690  			p.w(")")
  8691  		default:
  8692  			defer p.w("%s", p.convert(n, n.Operand, t, flags))
  8693  			p.w(" -")
  8694  			p.castExpression(f, n.CastExpression, n.Operand.Type(), exprValue, flags)
  8695  		}
  8696  	case cc.UnaryExpressionCpl: // '~' CastExpression
  8697  		defer p.w("%s", p.convert(n, n.Operand, t, flags))
  8698  		switch {
  8699  		case n.CastExpression.Operand.Value() != nil:
  8700  			switch {
  8701  			case !t.IsIntegerType():
  8702  				p.w(" ^")
  8703  				p.castExpression(f, n.CastExpression, n.Operand.Type(), exprValue, flags|fForceRuntimeConv)
  8704  			default:
  8705  				p.w("%sCpl%s(", p.task.crt, p.helperType(n, n.Operand.Type()))
  8706  				p.castExpression(f, n.CastExpression, n.Operand.Type(), exprValue, flags)
  8707  				p.w(")")
  8708  			}
  8709  		default:
  8710  			p.w(" ^")
  8711  			p.castExpression(f, n.CastExpression, n.Operand.Type(), exprValue, flags)
  8712  		}
  8713  	case cc.UnaryExpressionNot: // '!' CastExpression
  8714  		p.w("%sBool%s(!(", p.task.crt, p.helperType(n, t))
  8715  		p.castExpression(f, n.CastExpression, n.CastExpression.Operand.Type(), exprBool, flags)
  8716  		p.w("))")
  8717  	case cc.UnaryExpressionSizeofExpr: // "sizeof" UnaryExpression
  8718  		p.checkSizeof(n.UnaryExpression, n.UnaryExpression.Operand.Type())
  8719  		defer p.w("%s", p.convertNil(n, t, flags))
  8720  		if d := n.UnaryExpression.Declarator(); d != nil {
  8721  			var isLocal bool
  8722  			if f != nil {
  8723  				if local := f.locals[d]; local != nil {
  8724  					isLocal = true
  8725  					if !local.isPinned {
  8726  						p.w("unsafe.Sizeof(%s)", local.name)
  8727  						return
  8728  					}
  8729  				}
  8730  			}
  8731  
  8732  			if !isLocal {
  8733  				if tld := p.tlds[d]; tld != nil {
  8734  					p.w("unsafe.Sizeof(%s)", tld.name)
  8735  					break
  8736  				}
  8737  
  8738  				nm := d.Name().String()
  8739  				if imp := p.imports[nm]; imp != nil {
  8740  					imp.used = true
  8741  					p.w("unsafe.Sizeof(%sX%s)", imp.qualifier, nm)
  8742  					break
  8743  				}
  8744  			}
  8745  		}
  8746  
  8747  		t := n.UnaryExpression.Operand.Type()
  8748  		if p.isArray(f, n.UnaryExpression, t) {
  8749  			p.w("%d", t.Len()*t.Elem().Size())
  8750  			break
  8751  		}
  8752  
  8753  		s := "(0)"
  8754  		if !t.IsArithmeticType() {
  8755  			switch t.Kind() {
  8756  			case cc.Ptr:
  8757  				// ok
  8758  			case cc.Struct, cc.Union, cc.Array:
  8759  				s = "{}"
  8760  			default:
  8761  				panic(todo("", t.Kind()))
  8762  			}
  8763  		}
  8764  		switch t.Kind() {
  8765  		case cc.Int128, cc.UInt128:
  8766  			s = "{}"
  8767  		}
  8768  		p.w("unsafe.Sizeof(%s%s)", p.typ(n, t), s)
  8769  	case cc.UnaryExpressionSizeofType: // "sizeof" '(' TypeName ')'
  8770  		defer p.w("%s", p.convertNil(n, t, flags))
  8771  		t := n.TypeName.Type()
  8772  		p.checkSizeof(n.TypeName, t)
  8773  		if t.Kind() == cc.Array {
  8774  			p.w("%d", t.Len()*t.Elem().Size())
  8775  			break
  8776  		}
  8777  
  8778  		s := "(0)"
  8779  		if !t.IsArithmeticType() {
  8780  			switch t.Kind() {
  8781  			case cc.Ptr:
  8782  				// ok
  8783  			case cc.Struct, cc.Union:
  8784  				s = "{}"
  8785  			default:
  8786  				panic(todo("", t.Kind()))
  8787  			}
  8788  		}
  8789  		switch t.Kind() {
  8790  		case cc.Int128, cc.UInt128:
  8791  			s = "{}"
  8792  		}
  8793  		p.w("unsafe.Sizeof(%s%s)", p.typ(n, t), s)
  8794  	case cc.UnaryExpressionLabelAddr: // "&&" IDENTIFIER
  8795  		panic(todo("", n.Position()))
  8796  	case cc.UnaryExpressionAlignofExpr: // "_Alignof" UnaryExpression
  8797  		if n.TypeName.Type().Kind() == cc.Void {
  8798  			p.intConst(n, "", n.Operand, t, flags)
  8799  			break
  8800  		}
  8801  
  8802  		defer p.w("%s", p.convertNil(n, t, flags))
  8803  		t := n.UnaryExpression.Operand.Type()
  8804  		if p.isArray(f, n.UnaryExpression, t) {
  8805  			p.w("%d", t.Len()*t.Elem().Size())
  8806  			break
  8807  		}
  8808  
  8809  		s := "(0)"
  8810  		if !t.IsArithmeticType() {
  8811  			switch t.Kind() {
  8812  			case cc.Ptr:
  8813  				// ok
  8814  			case cc.Struct, cc.Union:
  8815  				s = "{}"
  8816  			default:
  8817  				panic(todo("", t.Kind()))
  8818  			}
  8819  		}
  8820  		p.w("unsafe.Alignof(%s%s)", p.typ(n, t), s)
  8821  	case cc.UnaryExpressionAlignofType: // "_Alignof" '(' TypeName ')'
  8822  		if n.TypeName.Type().Kind() == cc.Void {
  8823  			p.intConst(n, "", n.Operand, t, flags)
  8824  			break
  8825  		}
  8826  
  8827  		defer p.w("%s", p.convertNil(n, t, flags))
  8828  		t := n.TypeName.Type()
  8829  		if t.Kind() == cc.Array {
  8830  			p.w("%d", t.Len()*t.Elem().Size())
  8831  			break
  8832  		}
  8833  
  8834  		s := "(0)"
  8835  		if !t.IsArithmeticType() {
  8836  			switch t.Kind() {
  8837  			case cc.Ptr:
  8838  				// ok
  8839  			case cc.Struct, cc.Union:
  8840  				s = "{}"
  8841  			default:
  8842  				panic(todo("", t.Kind()))
  8843  			}
  8844  		}
  8845  		p.w("unsafe.Alignof(%s%s)", p.typ(n, t), s)
  8846  	case cc.UnaryExpressionImag: // "__imag__" UnaryExpression
  8847  		panic(todo("", n.Position()))
  8848  	case cc.UnaryExpressionReal: // "__real__" UnaryExpression
  8849  		panic(todo("", n.Position()))
  8850  	default:
  8851  		panic(todo("%v: internal error: %v", n.Position(), n.Case))
  8852  	}
  8853  }
  8854  
  8855  func (p *project) checkSizeof(n cc.Node, t cc.Type) {
  8856  	if !p.checkSizeof0(n, t) {
  8857  		p.err(n, "sizeof type %s: not supported", t.Alias())
  8858  	}
  8859  }
  8860  
  8861  func (p *project) checkSizeof0(n cc.Node, t cc.Type) (ok bool) {
  8862  	switch t.Kind() {
  8863  	case cc.Array:
  8864  		return !t.IsVLA()
  8865  	case cc.Struct, cc.Union:
  8866  		nf := t.NumField()
  8867  		for i := []int{0}; i[0] < nf; i[0]++ {
  8868  			if !p.checkSizeof0(n, t.FieldByIndex(i).Type()) {
  8869  				return false
  8870  			}
  8871  		}
  8872  	}
  8873  	return true
  8874  }
  8875  
  8876  func (p *project) unaryExpressionLValue(f *function, n *cc.UnaryExpression, t cc.Type, mode exprMode, flags flags) {
  8877  	switch n.Case {
  8878  	case cc.UnaryExpressionPostfix: // PostfixExpression
  8879  		p.postfixExpression(f, n.PostfixExpression, t, mode, flags)
  8880  	case cc.UnaryExpressionInc: // "++" UnaryExpression
  8881  		panic(todo("", p.pos(n)))
  8882  	case cc.UnaryExpressionDec: // "--" UnaryExpression
  8883  		panic(todo("", p.pos(n)))
  8884  	case cc.UnaryExpressionAddrof: // '&' CastExpression
  8885  		panic(todo("", n.Position()))
  8886  	case cc.UnaryExpressionDeref: // '*' CastExpression
  8887  		ot := n.CastExpression.Operand.Type()
  8888  		switch ot.Kind() {
  8889  		case cc.Ptr, cc.Array:
  8890  			switch et := ot.Elem(); {
  8891  			case
  8892  				et.IsScalarType(),
  8893  				et.Kind() == cc.Struct,
  8894  				et.Kind() == cc.Union:
  8895  
  8896  				p.unaryExpressionDeref(f, n, t, mode, flags)
  8897  			default:
  8898  				panic(todo("", p.pos(n), et, et.Kind()))
  8899  			}
  8900  		default:
  8901  			panic(todo("", p.pos(n), ot, ot.Kind()))
  8902  		}
  8903  	case cc.UnaryExpressionPlus: // '+' CastExpression
  8904  		panic(todo("", n.Position()))
  8905  	case cc.UnaryExpressionMinus: // '-' CastExpression
  8906  		panic(todo("", n.Position()))
  8907  	case cc.UnaryExpressionCpl: // '~' CastExpression
  8908  		panic(todo("", n.Position()))
  8909  	case cc.UnaryExpressionNot: // '!' CastExpression
  8910  		panic(todo("", n.Position()))
  8911  	case cc.UnaryExpressionSizeofExpr: // "sizeof" UnaryExpression
  8912  		panic(todo("", n.Position()))
  8913  	case cc.UnaryExpressionSizeofType: // "sizeof" '(' TypeName ')'
  8914  		panic(todo("", n.Position()))
  8915  	case cc.UnaryExpressionLabelAddr: // "&&" IDENTIFIER
  8916  		panic(todo("", n.Position()))
  8917  	case cc.UnaryExpressionAlignofExpr: // "_Alignof" UnaryExpression
  8918  		panic(todo("", n.Position()))
  8919  	case cc.UnaryExpressionAlignofType: // "_Alignof" '(' TypeName ')'
  8920  		panic(todo("", n.Position()))
  8921  	case cc.UnaryExpressionImag: // "__imag__" UnaryExpression
  8922  		panic(todo("", n.Position()))
  8923  	case cc.UnaryExpressionReal: // "__real__" UnaryExpression
  8924  		panic(todo("", n.Position()))
  8925  	default:
  8926  		panic(todo("%v: internal error: %v", n.Position(), n.Case))
  8927  	}
  8928  }
  8929  
  8930  func isSigned(t cc.Type) bool   { return t.IsIntegerType() && t.IsSignedType() }
  8931  func isUnsigned(t cc.Type) bool { return t.IsIntegerType() && !t.IsSignedType() }
  8932  
  8933  func isConstInteger(op cc.Operand) bool {
  8934  	switch op.Value().(type) {
  8935  	case cc.Int64Value, cc.Uint64Value:
  8936  		return true
  8937  	default:
  8938  		return false
  8939  	}
  8940  }
  8941  
  8942  func isNegativeInt(op cc.Operand) bool {
  8943  	switch x := op.Value().(type) {
  8944  	case cc.Int64Value:
  8945  		return x < 0
  8946  	default:
  8947  		return false
  8948  	}
  8949  }
  8950  
  8951  func isNonNegativeInt(op cc.Operand) bool {
  8952  	switch x := op.Value().(type) {
  8953  	case cc.Int64Value:
  8954  		return x >= 0
  8955  	case cc.Uint64Value:
  8956  		return true
  8957  	default:
  8958  		return false
  8959  	}
  8960  }
  8961  
  8962  func (p *project) unaryExpressionPreIncDec(f *function, n *cc.UnaryExpression, oper, oper2 string, t cc.Type, mode exprMode, flags flags) {
  8963  	// "++" UnaryExpression etc.
  8964  	switch mode {
  8965  	case exprValue:
  8966  		p.unaryExpressionPreIncDecValue(f, n, oper, oper2, t, mode, flags)
  8967  	case exprVoid:
  8968  		p.unaryExpressionPreIncDecVoid(f, n, oper, oper2, t, mode, flags)
  8969  	default:
  8970  		panic(todo("", p.pos(n), mode))
  8971  	}
  8972  }
  8973  
  8974  func (p *project) unaryExpressionPreIncDecVoid(f *function, n *cc.UnaryExpression, oper, oper2 string, t cc.Type, mode exprMode, flags flags) {
  8975  	// "++" UnaryExpression etc.
  8976  	switch n.UnaryExpression.Operand.Type().Kind() {
  8977  	case cc.Int128, cc.UInt128:
  8978  		p.unaryExpressionLValue(f, n.UnaryExpression, n.UnaryExpression.Operand.Type(), exprLValue, 0)
  8979  		switch oper {
  8980  		case "++":
  8981  			p.w(".LValueInc()")
  8982  		case "--":
  8983  			p.w(".LValueDec()")
  8984  		default:
  8985  			panic(todo("internal error: %q", oper))
  8986  		}
  8987  		return
  8988  	}
  8989  
  8990  	// "++" UnaryExpression etc.
  8991  	switch k := p.opKind(f, n.UnaryExpression, n.UnaryExpression.Operand.Type()); k {
  8992  	case opNormal:
  8993  		p.unaryExpressionPreIncDecVoidNormal(f, n, oper, oper2, t, mode, flags)
  8994  	case opArrayParameter:
  8995  		p.unaryExpressionPreIncDecVoidArrayParameter(f, n, oper, oper2, t, mode, flags)
  8996  	default:
  8997  		panic(todo("", n.Position(), k))
  8998  	}
  8999  }
  9000  
  9001  func (p *project) unaryExpressionPreIncDecVoidArrayParameter(f *function, n *cc.UnaryExpression, oper, oper2 string, t cc.Type, mode exprMode, flags flags) {
  9002  	// "++" UnaryExpression etc.
  9003  	ut := n.UnaryExpression.Operand.Type()
  9004  	p.unaryExpression(f, n.UnaryExpression, n.UnaryExpression.Operand.Type(), exprLValue, flags)
  9005  	switch d := p.incDelta(n, ut); d {
  9006  	case 1:
  9007  		p.w("%s", oper)
  9008  	default:
  9009  		p.w("%s %d", oper2, d)
  9010  	}
  9011  }
  9012  
  9013  func (p *project) unaryExpressionPreIncDecVoidNormal(f *function, n *cc.UnaryExpression, oper, oper2 string, t cc.Type, mode exprMode, flags flags) {
  9014  	// "++" UnaryExpression etc.
  9015  	ut := n.UnaryExpression.Operand.Type()
  9016  	if d := n.UnaryExpression.Declarator(); d != nil && p.isVolatileOrAtomic(d) {
  9017  		x := "Dec"
  9018  		if oper == "++" {
  9019  			x = "Inc"
  9020  		}
  9021  		p.w("%sPre%sAtomic%s(&", p.task.crt, x, p.helperType(n, d.Type()))
  9022  		switch local, tld := f.locals[d], p.tlds[d]; {
  9023  		case local != nil:
  9024  			p.w("%s", local.name)
  9025  		case tld != nil:
  9026  			p.w("%s", tld.name)
  9027  		default:
  9028  			panic(todo(""))
  9029  		}
  9030  		p.w(", %d)", p.incDelta(n.PostfixExpression, ut))
  9031  		return
  9032  	}
  9033  
  9034  	p.unaryExpression(f, n.UnaryExpression, n.UnaryExpression.Operand.Type(), exprLValue, flags)
  9035  	if ut.IsIntegerType() || ut.Kind() == cc.Ptr && p.incDelta(n, ut) == 1 {
  9036  		p.w("%s", oper)
  9037  		return
  9038  	}
  9039  
  9040  	switch ut.Kind() {
  9041  	case cc.Ptr, cc.Double, cc.Float:
  9042  		p.w("%s %d", oper2, p.incDelta(n, ut))
  9043  		return
  9044  	}
  9045  
  9046  	panic(todo("", p.pos(n)))
  9047  }
  9048  
  9049  func (p *project) unaryExpressionPreIncDecValue(f *function, n *cc.UnaryExpression, oper, oper2 string, t cc.Type, mode exprMode, flags flags) {
  9050  	// "++" UnaryExpression etc.
  9051  	switch k := p.opKind(f, n.UnaryExpression, n.UnaryExpression.Operand.Type()); k {
  9052  	case opNormal:
  9053  		p.unaryExpressionPreIncDecValueNormal(f, n, oper, oper2, t, mode, flags)
  9054  	default:
  9055  		panic(todo("", n.Position(), k))
  9056  	}
  9057  }
  9058  
  9059  func (p *project) unaryExpressionPreIncDecValueNormal(f *function, n *cc.UnaryExpression, oper, oper2 string, t cc.Type, mode exprMode, flags flags) {
  9060  	// "++" UnaryExpression etc.
  9061  	defer p.w("%s", p.convert(n, n.UnaryExpression.Operand, t, flags))
  9062  	x := "Dec"
  9063  	if oper == "++" {
  9064  		x = "Inc"
  9065  	}
  9066  	ut := n.UnaryExpression.Operand.Type()
  9067  	if d := n.UnaryExpression.Declarator(); d != nil && p.isVolatileOrAtomic(d) {
  9068  		if !ut.IsIntegerType() {
  9069  			panic(todo("", n.Position(), d.Position(), ut))
  9070  		}
  9071  
  9072  		flags |= fVolatileOk
  9073  		switch ut.Size() {
  9074  		case 4:
  9075  			switch {
  9076  			case ut.IsSignedType():
  9077  				p.w("%sPre%sInt32(&", p.task.crt, x)
  9078  				p.unaryExpression(f, n.UnaryExpression, ut, exprLValue, flags)
  9079  				p.w(", 1)")
  9080  			default:
  9081  				p.w("%sPre%sInt32((*int32)(unsafe.Pointer(&", p.task.crt, x)
  9082  				p.unaryExpression(f, n.UnaryExpression, ut, exprLValue, flags)
  9083  				p.w(")), 1)")
  9084  			}
  9085  		case 8:
  9086  			switch {
  9087  			case ut.IsSignedType():
  9088  				p.w("%sPre%sInt64(&", p.task.crt, x)
  9089  				p.unaryExpression(f, n.UnaryExpression, ut, exprLValue, flags)
  9090  				p.w(", 1)")
  9091  			default:
  9092  				p.w("%sPre%sInt64((*int64)(unsafe.Pointer(&", p.task.crt, x)
  9093  				p.unaryExpression(f, n.UnaryExpression, ut, exprLValue, flags)
  9094  				p.w(")), 1)")
  9095  			}
  9096  		default:
  9097  			panic(todo("", n.Position(), d.Position(), ut))
  9098  		}
  9099  		return
  9100  	}
  9101  
  9102  	p.w("%sPre%s%s(&", p.task.crt, x, p.helperType(n, ut))
  9103  	p.unaryExpression(f, n.UnaryExpression, ut, exprLValue, flags)
  9104  	p.w(", %d)", p.incDelta(n.PostfixExpression, ut))
  9105  }
  9106  
  9107  func (p *project) unaryExpressionDeref(f *function, n *cc.UnaryExpression, t cc.Type, mode exprMode, flags flags) {
  9108  	// '*' CastExpression
  9109  	switch mode {
  9110  	case exprValue:
  9111  		p.unaryExpressionDerefValue(f, n, t, mode, flags)
  9112  	case exprLValue:
  9113  		p.unaryExpressionDerefLValue(f, n, t, mode, flags)
  9114  	case exprAddrOf:
  9115  		p.unaryExpressionDerefAddrOf(f, n, t, mode, flags)
  9116  	case exprBool:
  9117  		p.unaryExpressionDerefBool(f, n, t, mode, flags)
  9118  	default:
  9119  		panic(todo("", n.Position(), mode))
  9120  	}
  9121  }
  9122  
  9123  func (p *project) unaryExpressionDerefBool(f *function, n *cc.UnaryExpression, t cc.Type, mode exprMode, flags flags) {
  9124  	// '*' CastExpression
  9125  	p.w("(")
  9126  	defer p.w(")")
  9127  	p.w("*(*%s)(unsafe.Pointer(", p.typ(n, n.Operand.Type()))
  9128  	p.castExpression(f, n.CastExpression, n.CastExpression.Operand.Type(), exprValue, flags)
  9129  	p.w(")) != 0")
  9130  }
  9131  
  9132  func (p *project) unaryExpressionDerefAddrOf(f *function, n *cc.UnaryExpression, t cc.Type, mode exprMode, flags flags) {
  9133  	// '*' CastExpression
  9134  	p.castExpression(f, n.CastExpression, n.CastExpression.Operand.Type(), exprValue, flags)
  9135  }
  9136  
  9137  func (p *project) unaryExpressionDerefLValue(f *function, n *cc.UnaryExpression, t cc.Type, mode exprMode, flags flags) {
  9138  	// '*' CastExpression
  9139  	switch k := p.opKind(f, n.CastExpression, n.CastExpression.Operand.Type()); k {
  9140  	case opNormal:
  9141  		p.unaryExpressionDerefLValueNormal(f, n, t, mode, flags)
  9142  	case opArray:
  9143  		panic(todo("", p.pos(n)))
  9144  		p.unaryExpressionDerefLValueArray(f, n, t, mode, flags)
  9145  	case opArrayParameter:
  9146  		p.unaryExpressionDerefLValueNormal(f, n, t, mode, flags)
  9147  	default:
  9148  		panic(todo("", n.Position(), k))
  9149  	}
  9150  }
  9151  
  9152  func (p *project) unaryExpressionDerefLValueArray(f *function, n *cc.UnaryExpression, t cc.Type, mode exprMode, flags flags) {
  9153  	defer p.w("))%s", p.convertType(n, n.CastExpression.Operand.Type().Elem(), t, flags))
  9154  	p.w("*(*%s)(unsafe.Pointer(", p.typ(n, n.Operand.Type()))
  9155  	p.castExpression(f, n.CastExpression, n.CastExpression.Operand.Type(), exprValue, flags)
  9156  }
  9157  
  9158  func (p *project) unaryExpressionDerefLValueNormal(f *function, n *cc.UnaryExpression, t cc.Type, mode exprMode, flags flags) {
  9159  	defer p.w("))%s", p.convertType(n, n.CastExpression.Operand.Type().Elem(), t, flags))
  9160  	p.w("*(*%s)(unsafe.Pointer(", p.typ(n, n.Operand.Type()))
  9161  	p.castExpression(f, n.CastExpression, n.CastExpression.Operand.Type(), exprValue, flags)
  9162  }
  9163  
  9164  func (p *project) unaryExpressionDerefValue(f *function, n *cc.UnaryExpression, t cc.Type, mode exprMode, flags flags) {
  9165  	// '*' CastExpression
  9166  	switch k := p.opKind(f, n.CastExpression, n.CastExpression.Operand.Type()); k {
  9167  	case opNormal, opArrayParameter:
  9168  		p.unaryExpressionDerefValueNormal(f, n, t, mode, flags)
  9169  	case opArray:
  9170  		p.unaryExpressionDerefValueArray(f, n, t, mode, flags)
  9171  	default:
  9172  		panic(todo("", n.Position(), k))
  9173  	}
  9174  }
  9175  
  9176  func (p *project) unaryExpressionDerefValueArray(f *function, n *cc.UnaryExpression, t cc.Type, mode exprMode, flags flags) {
  9177  	defer p.w("%s", p.convertType(n, n.CastExpression.Operand.Type().Elem(), t, flags))
  9178  	p.castExpression(f, n.CastExpression, n.CastExpression.Operand.Type(), exprValue, flags)
  9179  	p.w("[0]")
  9180  }
  9181  
  9182  func (p *project) unaryExpressionDerefValueNormal(f *function, n *cc.UnaryExpression, t cc.Type, mode exprMode, flags flags) {
  9183  	// '*' CastExpression
  9184  	switch op := n.Operand.Type(); {
  9185  	case op.Kind() == cc.Array:
  9186  		p.castExpression(f, n.CastExpression, n.CastExpression.Operand.Type(), mode, flags)
  9187  	default:
  9188  		defer p.w("))%s", p.convertType(n, n.CastExpression.Operand.Type().Elem(), t, flags))
  9189  		p.w("*(*%s)(unsafe.Pointer(", p.typ(n, n.Operand.Type()))
  9190  		p.castExpression(f, n.CastExpression, n.CastExpression.Operand.Type(), mode, flags)
  9191  	}
  9192  }
  9193  
  9194  func (p *project) postfixExpression(f *function, n *cc.PostfixExpression, t cc.Type, mode exprMode, flags flags) {
  9195  	switch mode {
  9196  	case exprLValue:
  9197  		p.postfixExpressionLValue(f, n, t, mode, flags)
  9198  	case exprValue:
  9199  		p.postfixExpressionValue(f, n, t, mode, flags)
  9200  	case exprVoid:
  9201  		p.postfixExpressionVoid(f, n, t, mode, flags)
  9202  	case exprFunc:
  9203  		p.postfixExpressionFunc(f, n, t, mode, flags)
  9204  	case exprAddrOf:
  9205  		p.postfixExpressionAddrOf(f, n, t, mode, flags)
  9206  	case exprSelect:
  9207  		p.postfixExpressionSelect(f, n, t, mode, flags)
  9208  	case exprPSelect:
  9209  		p.postfixExpressionPSelect(f, n, t, mode, flags)
  9210  	case exprBool:
  9211  		p.postfixExpressionBool(f, n, t, mode, flags)
  9212  	case exprDecay:
  9213  		p.postfixExpressionDecay(f, n, t, mode, flags)
  9214  	default:
  9215  		panic(todo("", n.Position(), mode))
  9216  	}
  9217  }
  9218  
  9219  func (p *project) postfixExpressionDecay(f *function, n *cc.PostfixExpression, t cc.Type, mode exprMode, flags flags) {
  9220  	switch n.Case {
  9221  	case cc.PostfixExpressionPrimary: // PrimaryExpression
  9222  		p.primaryExpression(f, n.PrimaryExpression, t, mode, flags)
  9223  	case cc.PostfixExpressionIndex: // PostfixExpression '[' Expression ']'
  9224  		defer p.w("%s", p.convert(n, n.Operand, t, flags))
  9225  		pe := n.PostfixExpression.Operand.Type()
  9226  		p.w("(")
  9227  		switch {
  9228  		case pe.Kind() == cc.Array:
  9229  			p.postfixExpression(f, n.PostfixExpression, pe, exprDecay, flags)
  9230  		case pe.Kind() == cc.Ptr:
  9231  			p.postfixExpression(f, n.PostfixExpression, pe, exprValue, flags)
  9232  		default:
  9233  			panic(todo("", p.pos(n)))
  9234  		}
  9235  		if !n.Expression.Operand.IsZero() {
  9236  			p.nzUintptr(n, func() { p.expression(f, n.Expression, n.Expression.Operand.Type(), exprValue, flags) }, n.Expression.Operand)
  9237  			if sz := pe.Elem().Size(); sz != 1 {
  9238  				p.w("*%d", sz)
  9239  			}
  9240  		}
  9241  		p.w(")")
  9242  	case cc.PostfixExpressionCall: // PostfixExpression '(' ArgumentExpressionList ')'
  9243  		panic(todo("", p.pos(n)))
  9244  	case cc.PostfixExpressionSelect: // PostfixExpression '.' IDENTIFIER
  9245  		p.postfixExpression(f, n, t, exprAddrOf, flags)
  9246  	case cc.PostfixExpressionPSelect: // PostfixExpression "->" IDENTIFIER
  9247  		p.postfixExpression(f, n, t, exprAddrOf, flags)
  9248  	case cc.PostfixExpressionInc: // PostfixExpression "++"
  9249  		panic(todo("", p.pos(n)))
  9250  	case cc.PostfixExpressionDec: // PostfixExpression "--"
  9251  		panic(todo("", p.pos(n)))
  9252  	case cc.PostfixExpressionComplit: // '(' TypeName ')' '{' InitializerList ',' '}'
  9253  		panic(todo("", p.pos(n)))
  9254  	case cc.PostfixExpressionTypeCmp: // "__builtin_types_compatible_p" '(' TypeName ',' TypeName ')'
  9255  		panic(todo("", p.pos(n)))
  9256  	case cc.PostfixExpressionChooseExpr:
  9257  		panic(todo("", p.pos(n)))
  9258  	default:
  9259  		panic(todo("%v: internal error: %v", n.Position(), n.Case))
  9260  	}
  9261  }
  9262  
  9263  func (p *project) postfixExpressionBool(f *function, n *cc.PostfixExpression, t cc.Type, mode exprMode, flags flags) {
  9264  	switch n.Case {
  9265  	case cc.PostfixExpressionPrimary: // PrimaryExpression
  9266  		p.primaryExpression(f, n.PrimaryExpression, t, mode, flags)
  9267  	case cc.PostfixExpressionIndex: // PostfixExpression '[' Expression ']'
  9268  		p.w("(")
  9269  		defer p.w(")")
  9270  		defer p.w(" != 0")
  9271  		p.postfixExpression(f, n, t, exprValue, flags)
  9272  	case cc.PostfixExpressionCall: // PostfixExpression '(' ArgumentExpressionList ')'
  9273  		p.postfixExpressionCall(f, n, t, mode, flags)
  9274  	case cc.PostfixExpressionSelect: // PostfixExpression '.' IDENTIFIER
  9275  		p.w("(")
  9276  		defer p.w(")")
  9277  		defer p.w(" != 0")
  9278  		p.postfixExpression(f, n, t, exprValue, flags)
  9279  	case cc.PostfixExpressionPSelect: // PostfixExpression "->" IDENTIFIER
  9280  		p.w("(")
  9281  		defer p.w(")")
  9282  		defer p.w(" != 0")
  9283  		p.postfixExpression(f, n, t, exprValue, flags)
  9284  	case cc.PostfixExpressionInc: // PostfixExpression "++"
  9285  		p.w("(")
  9286  		defer p.w(")")
  9287  		defer p.w(" != 0")
  9288  		p.postfixExpression(f, n, t, exprValue, flags)
  9289  	case cc.PostfixExpressionDec: // PostfixExpression "--"
  9290  		p.w("(")
  9291  		defer p.w(")")
  9292  		defer p.w(" != 0")
  9293  		p.postfixExpression(f, n, t, exprValue, flags)
  9294  	case cc.PostfixExpressionComplit: // '(' TypeName ')' '{' InitializerList ',' '}'
  9295  		panic(todo("", p.pos(n)))
  9296  	case cc.PostfixExpressionTypeCmp: // "__builtin_types_compatible_p" '(' TypeName ',' TypeName ')'
  9297  		panic(todo("", p.pos(n)))
  9298  	case cc.PostfixExpressionChooseExpr:
  9299  		p.w("(")
  9300  		defer p.w(")")
  9301  		defer p.w(" != 0")
  9302  		p.postfixExpression(f, n, t, exprValue, flags)
  9303  	default:
  9304  		panic(todo("%v: internal error: %v", n.Position(), n.Case))
  9305  	}
  9306  }
  9307  
  9308  func (p *project) postfixExpressionPSelect(f *function, n *cc.PostfixExpression, t cc.Type, mode exprMode, flags flags) {
  9309  	// PostfixExpression "->" IDENTIFIER
  9310  	switch n.Case {
  9311  	case cc.PostfixExpressionPrimary: // PrimaryExpression
  9312  		p.primaryExpression(f, n.PrimaryExpression, t, mode, flags)
  9313  	case cc.PostfixExpressionIndex: // PostfixExpression '[' Expression ']'
  9314  		p.postfixExpressionPSelectIndex(f, n, t, mode, flags)
  9315  	case cc.PostfixExpressionCall: // PostfixExpression '(' ArgumentExpressionList ')'
  9316  		p.postfixExpressionPSelectCall(f, n, t, mode, flags)
  9317  	case cc.PostfixExpressionSelect: // PostfixExpression '.' IDENTIFIER
  9318  		p.postfixExpressionPSelectSelect(f, n, t, mode, flags)
  9319  	case cc.PostfixExpressionPSelect: // PostfixExpression "->" IDENTIFIER
  9320  		p.postfixExpressionPSelectPSelect(f, n, t, mode, flags)
  9321  	case cc.PostfixExpressionInc: // PostfixExpression "++"
  9322  		panic(todo("", p.pos(n)))
  9323  	case cc.PostfixExpressionDec: // PostfixExpression "--"
  9324  		panic(todo("", p.pos(n)))
  9325  	case cc.PostfixExpressionComplit: // '(' TypeName ')' '{' InitializerList ',' '}'
  9326  		panic(todo("", p.pos(n)))
  9327  	case cc.PostfixExpressionTypeCmp: // "__builtin_types_compatible_p" '(' TypeName ',' TypeName ')'
  9328  		panic(todo("", p.pos(n)))
  9329  	case cc.PostfixExpressionChooseExpr:
  9330  		panic(todo("", p.pos(n)))
  9331  	default:
  9332  		panic(todo("%v: internal error: %v", n.Position(), n.Case))
  9333  	}
  9334  }
  9335  
  9336  func (p *project) postfixExpressionPSelectSelect(f *function, n *cc.PostfixExpression, t cc.Type, mode exprMode, flags flags) {
  9337  	// PostfixExpression '.' IDENTIFIER
  9338  	switch k := p.opKind(f, n.PostfixExpression, n.PostfixExpression.Operand.Type()); k {
  9339  	case opStruct:
  9340  		p.postfixExpressionPSelectSelectStruct(f, n, t, mode, flags)
  9341  	case opUnion:
  9342  		p.postfixExpressionPSelectSelectUnion(f, n, t, mode, flags)
  9343  	default:
  9344  		panic(todo("", n.Position(), k))
  9345  	}
  9346  }
  9347  
  9348  func (p *project) postfixExpressionPSelectSelectUnion(f *function, n *cc.PostfixExpression, t cc.Type, mode exprMode, flags flags) {
  9349  	// PostfixExpression '.' IDENTIFIER
  9350  	fld := n.Field
  9351  	if fld.Offset() != 0 {
  9352  		p.err(&n.Token2, "internal error, union field with non-zero offset: %s %v", n.Token2.Value, fld.Offset())
  9353  	}
  9354  	switch {
  9355  	case n.Operand.Type().IsBitFieldType():
  9356  		panic(todo("", p.pos(n)))
  9357  	default:
  9358  		if fld.IsBitField() {
  9359  			p.err(&n.Token2, "internal error, wrong function for accessing a bit field: %s", n.Token2.Value)
  9360  		}
  9361  		pe := n.PostfixExpression.Operand.Type()
  9362  		defer p.w("%s", p.convert(n, n.Operand, t, flags))
  9363  		p.w("(*(**%s)(unsafe.Pointer(", p.typ(n, n.Operand.Type().Elem()))
  9364  		p.postfixExpression(f, n.PostfixExpression, pe, exprAddrOf, flags)
  9365  		p.w("/* .%s */", p.fieldName(n, n.Token2.Value))
  9366  		p.w(")))")
  9367  	}
  9368  }
  9369  
  9370  func (p *project) postfixExpressionPSelectSelectStruct(f *function, n *cc.PostfixExpression, t cc.Type, mode exprMode, flags flags) {
  9371  	// PostfixExpression '.' IDENTIFIER
  9372  	fld := n.Field
  9373  	switch {
  9374  	case n.Operand.Type().IsBitFieldType():
  9375  		panic(todo("", p.pos(n)))
  9376  	default:
  9377  		if fld.IsBitField() {
  9378  			p.err(&n.Token2, "internal error, wrong function for accessing a bit field: %s", n.Token2.Value)
  9379  		}
  9380  		pe := n.PostfixExpression.Operand.Type()
  9381  		p.w("(*%s)(unsafe.Pointer(", p.typ(n, t.Elem()))
  9382  		p.postfixExpression(f, n.PostfixExpression, pe, exprSelect, flags)
  9383  		p.w(".%s", p.fieldName(n, n.Token2.Value))
  9384  		p.w("))")
  9385  
  9386  	}
  9387  }
  9388  
  9389  func (p *project) postfixExpressionPSelectCall(f *function, n *cc.PostfixExpression, t cc.Type, mode exprMode, flags flags) {
  9390  	p.w("(*%s)(unsafe.Pointer(", p.typ(n, n.Operand.Type().Elem()))
  9391  	p.postfixExpressionCall(f, n, t, exprValue, flags)
  9392  	p.w("))")
  9393  }
  9394  
  9395  func (p *project) postfixExpressionPSelectIndex(f *function, n *cc.PostfixExpression, t cc.Type, mode exprMode, flags flags) {
  9396  	// PostfixExpression '[' Expression ']'
  9397  	switch k := p.opKind(f, n.PostfixExpression, n.PostfixExpression.Operand.Type()); k {
  9398  	// case opArray:
  9399  	// 	p.postfixExpressionSelectIndexArray(f, n, t, mode, flags)
  9400  	case opNormal:
  9401  		p.postfixExpressionPSelectIndexNormal(f, n, t, mode, flags)
  9402  	case opArrayParameter:
  9403  		p.postfixExpressionSelectIndexArrayParamater(f, n, t, mode, flags)
  9404  	default:
  9405  		panic(todo("", n.Position(), k))
  9406  	}
  9407  }
  9408  
  9409  func (p *project) postfixExpressionPSelectIndexNormal(f *function, n *cc.PostfixExpression, t cc.Type, mode exprMode, flags flags) {
  9410  	pe := n.PostfixExpression.Operand.Type()
  9411  	// PostfixExpression '[' Expression ']'
  9412  	switch {
  9413  	case n.Operand.Type().IsBitFieldType():
  9414  		panic(todo("", p.pos(n)))
  9415  	case n.Operand.Type().Kind() == cc.Array:
  9416  		panic(todo("", p.pos(n)))
  9417  	case pe.Kind() == cc.Array:
  9418  		p.w("(")
  9419  		defer p.w(")")
  9420  		p.w("(*(**%s)(unsafe.Pointer(", p.typ(n, n.Operand.Type().Elem()))
  9421  		p.postfixExpression(f, n.PostfixExpression, pe, exprAddrOf, flags)
  9422  		if !n.Expression.Operand.IsZero() {
  9423  			p.nzUintptr(n, func() { p.expression(f, n.Expression, n.Expression.Operand.Type(), exprValue, flags) }, n.Expression.Operand)
  9424  			if sz := pe.Decay().Elem().Size(); sz != 1 {
  9425  				p.w("*%d", sz)
  9426  			}
  9427  		}
  9428  		p.w(")))")
  9429  	default:
  9430  		p.w("(")
  9431  		defer p.w(")")
  9432  		p.w("(*(**%s)(unsafe.Pointer(", p.typ(n, n.Operand.Type().Elem()))
  9433  		p.postfixExpression(f, n.PostfixExpression, pe, exprValue, flags)
  9434  		if !n.Expression.Operand.IsZero() {
  9435  			p.nzUintptr(n, func() { p.expression(f, n.Expression, n.Expression.Operand.Type(), exprValue, flags) }, n.Expression.Operand)
  9436  			if sz := pe.Decay().Elem().Size(); sz != 1 {
  9437  				p.w("*%d", sz)
  9438  			}
  9439  		}
  9440  		p.w(")))")
  9441  	}
  9442  }
  9443  
  9444  func (p *project) postfixExpressionSelect(f *function, n *cc.PostfixExpression, t cc.Type, mode exprMode, flags flags) {
  9445  	// PostfixExpression '.' IDENTIFIER
  9446  	switch n.Case {
  9447  	case cc.PostfixExpressionPrimary: // PrimaryExpression
  9448  		p.primaryExpression(f, n.PrimaryExpression, t, mode, flags)
  9449  	case cc.PostfixExpressionIndex: // PostfixExpression '[' Expression ']'
  9450  		p.postfixExpressionSelectIndex(f, n, t, mode, flags)
  9451  	case cc.PostfixExpressionCall: // PostfixExpression '(' ArgumentExpressionList ')'
  9452  		p.postfixExpression(f, n, t, exprValue, flags)
  9453  	case cc.PostfixExpressionSelect: // PostfixExpression '.' IDENTIFIER
  9454  		p.postfixExpressionSelectSelect(f, n, t, mode, flags)
  9455  	case cc.PostfixExpressionPSelect: // PostfixExpression "->" IDENTIFIER
  9456  		p.postfixExpressionSelectPSelect(f, n, t, mode, flags)
  9457  	case cc.PostfixExpressionInc: // PostfixExpression "++"
  9458  		panic(todo("", p.pos(n)))
  9459  	case cc.PostfixExpressionDec: // PostfixExpression "--"
  9460  		panic(todo("", p.pos(n)))
  9461  	case cc.PostfixExpressionComplit: // '(' TypeName ')' '{' InitializerList ',' '}'
  9462  		panic(todo("", p.pos(n)))
  9463  	case cc.PostfixExpressionTypeCmp: // "__builtin_types_compatible_p" '(' TypeName ',' TypeName ')'
  9464  		panic(todo("", p.pos(n)))
  9465  	case cc.PostfixExpressionChooseExpr:
  9466  		panic(todo("", p.pos(n)))
  9467  	default:
  9468  		panic(todo("%v: internal error: %v", n.Position(), n.Case))
  9469  	}
  9470  }
  9471  
  9472  func (p *project) postfixExpressionPSelectPSelect(f *function, n *cc.PostfixExpression, t cc.Type, mode exprMode, flags flags) {
  9473  	// PostfixExpression "->" IDENTIFIER
  9474  	switch k := p.opKind(f, n.PostfixExpression, n.PostfixExpression.Operand.Type().Elem()); k {
  9475  	case opStruct:
  9476  		p.postfixExpressionPSelectPSelectStruct(f, n, t, mode, flags)
  9477  	default:
  9478  		panic(todo("", n.Position(), k))
  9479  	}
  9480  }
  9481  
  9482  func (p *project) postfixExpressionPSelectPSelectStruct(f *function, n *cc.PostfixExpression, t cc.Type, mode exprMode, flags flags) {
  9483  	// PostfixExpression "->" IDENTIFIER
  9484  	fld := n.Field
  9485  	switch {
  9486  	case n.Operand.Type().IsBitFieldType():
  9487  		panic(todo("", p.pos(n)))
  9488  	default:
  9489  		if fld.IsBitField() {
  9490  			p.err(&n.Token2, "internal error, wrong function for accessing a bit field: %s", n.Token2.Value)
  9491  		}
  9492  		pe := n.PostfixExpression.Operand.Type()
  9493  		defer p.w("%s", p.convert(n, n.Operand, t, flags))
  9494  		p.w("(*%s)(unsafe.Pointer(", p.typ(n, t.Elem()))
  9495  		p.postfixExpression(f, n.PostfixExpression, pe, exprPSelect, flags)
  9496  		p.w(".%s", p.fieldName(n, n.Token2.Value))
  9497  		p.w("))")
  9498  	}
  9499  }
  9500  
  9501  func (p *project) postfixExpressionSelectPSelect(f *function, n *cc.PostfixExpression, t cc.Type, mode exprMode, flags flags) {
  9502  	// PostfixExpression "->" IDENTIFIER
  9503  	switch k := p.opKind(f, n.PostfixExpression, n.PostfixExpression.Operand.Type().Elem()); k {
  9504  	case opStruct:
  9505  		p.postfixExpressionSelectPSelectStruct(f, n, t, mode, flags)
  9506  	case opUnion:
  9507  		p.postfixExpressionSelectPSelectUnion(f, n, t, mode, flags)
  9508  	default:
  9509  		panic(todo("", n.Position(), k))
  9510  	}
  9511  }
  9512  
  9513  func (p *project) postfixExpressionSelectPSelectUnion(f *function, n *cc.PostfixExpression, t cc.Type, mode exprMode, flags flags) {
  9514  	// PostfixExpression "->" IDENTIFIER
  9515  	fld := n.Field
  9516  	if fld.Offset() != 0 {
  9517  		p.err(&n.Token2, "internal error, union field with non-zero offset: %s %v", n.Token2.Value, fld.Offset())
  9518  	}
  9519  	switch {
  9520  	case n.Operand.Type().IsBitFieldType():
  9521  		panic(todo("", p.pos(n)))
  9522  	case n.Operand.Type().Kind() == cc.Array:
  9523  		panic(todo("", p.pos(n)))
  9524  	default:
  9525  		if fld.IsBitField() {
  9526  			p.err(&n.Token2, "internal error, wrong function for accessing a bit field: %s", n.Token2.Value)
  9527  		}
  9528  		pe := n.PostfixExpression.Operand.Type()
  9529  		defer p.w("%s", p.convert(n, n.Operand, t, flags))
  9530  		p.w("(*%s)(unsafe.Pointer(", p.typ(n, n.Operand.Type()))
  9531  		p.postfixExpression(f, n.PostfixExpression, pe, exprValue, flags)
  9532  		p.w("))")
  9533  	}
  9534  }
  9535  
  9536  func (p *project) postfixExpressionSelectPSelectStruct(f *function, n *cc.PostfixExpression, t cc.Type, mode exprMode, flags flags) {
  9537  	// PostfixExpression "->" IDENTIFIER
  9538  	fld := n.Field
  9539  	switch {
  9540  	case n.Operand.Type().IsBitFieldType():
  9541  		panic(todo("", p.pos(n)))
  9542  	default:
  9543  		if fld.IsBitField() {
  9544  			p.err(&n.Token2, "internal error, wrong function for accessing a bit field: %s", n.Token2.Value)
  9545  		}
  9546  		pe := n.PostfixExpression.Operand.Type()
  9547  		defer p.w("%s", p.convert(n, n.Operand, t, flags))
  9548  		et := n.PostfixExpression.Operand.Type().Elem()
  9549  		fld, path, ok := et.FieldByName2(n.Token2.Value)
  9550  		switch {
  9551  		case !ok:
  9552  			panic(todo("", n.Token.Position()))
  9553  		case fld.InUnion():
  9554  			p.w("(*(*%s)(unsafe.Pointer(", p.typ(n, n.Operand.Type()))
  9555  			p.postfixExpression(f, n.PostfixExpression, pe, exprValue, flags)
  9556  			p.w("%s)))", nonZeroUintptr(pathOff(et, path)))
  9557  		case len(path) != 1:
  9558  			panic(todo("", n.Token.Position()))
  9559  		default:
  9560  			p.w("(*%s)(unsafe.Pointer(", p.typ(n, pe.Elem()))
  9561  			switch {
  9562  			case pe.Kind() == cc.Array:
  9563  				p.postfixExpression(f, n.PostfixExpression, pe, exprAddrOf, flags)
  9564  			default:
  9565  				p.postfixExpression(f, n.PostfixExpression, pe, exprValue, flags)
  9566  			}
  9567  			p.w(")).%s", p.fieldName(n, n.Token2.Value))
  9568  		}
  9569  	}
  9570  }
  9571  
  9572  func (p *project) postfixExpressionSelectSelect(f *function, n *cc.PostfixExpression, t cc.Type, mode exprMode, flags flags) {
  9573  	// PostfixExpression '.' IDENTIFIER
  9574  	switch k := p.structOrUnion(n); k {
  9575  	case opUnion:
  9576  		p.postfixExpressionSelectSelectUnion(f, n, t, mode, flags)
  9577  	case opStruct:
  9578  		p.postfixExpressionSelectSelectStruct(f, n, t, mode, flags)
  9579  	default:
  9580  		panic(todo("", n.Position(), k))
  9581  	}
  9582  }
  9583  
  9584  func (p *project) structOrUnion(n *cc.PostfixExpression) opKind {
  9585  	t := n.PostfixExpression.Operand.Type()
  9586  	switch n.Case {
  9587  	case cc.PostfixExpressionSelect: // PostfixExpression '.' IDENTIFIER
  9588  		// ok
  9589  	case cc.PostfixExpressionPSelect: // PostfixExpression "->" IDENTIFIER
  9590  		if t.Kind() == cc.Ptr {
  9591  			t = t.Elem()
  9592  			break
  9593  		}
  9594  
  9595  		p.err(n, "expected pointer type: %s", t)
  9596  		return opStruct
  9597  	}
  9598  	f, path, ok := t.FieldByName2(n.Token2.Src)
  9599  	if !ok {
  9600  		p.err(&n.Token, "unknown field: %s", n.Token2)
  9601  		return opStruct
  9602  	}
  9603  
  9604  	for len(path) > 1 {
  9605  		f = t.FieldByIndex(path[:1])
  9606  		path = path[1:]
  9607  		t = f.Type()
  9608  	}
  9609  	if t.Kind() == cc.Union {
  9610  		// trc("%v: %q %v", n.Token2.Position(), n.Token2.Src, opUnion)
  9611  		return opUnion
  9612  	}
  9613  
  9614  	// trc("%v: %q %v", n.Token2.Position(), n.Token2.Src, opStruct)
  9615  	return opStruct
  9616  }
  9617  
  9618  func (p *project) postfixExpressionSelectSelectStruct(f *function, n *cc.PostfixExpression, t cc.Type, mode exprMode, flags flags) {
  9619  	// PostfixExpression '.' IDENTIFIER
  9620  	fld := n.Field
  9621  	switch {
  9622  	case n.Operand.Type().IsBitFieldType():
  9623  		panic(todo("", p.pos(n)))
  9624  	case n.Operand.Type().Kind() == cc.Array:
  9625  		panic(todo("", p.pos(n)))
  9626  	default:
  9627  		if fld.IsBitField() {
  9628  			p.err(&n.Token2, "internal error, wrong function for accessing a bit field: %s", n.Token2.Value)
  9629  		}
  9630  		pe := n.PostfixExpression.Operand.Type()
  9631  		p.postfixExpression(f, n.PostfixExpression, pe, exprSelect, flags)
  9632  		p.w(".%s", p.fieldName(n, n.Token2.Value))
  9633  	}
  9634  }
  9635  
  9636  func (p *project) postfixExpressionSelectSelectUnion(f *function, n *cc.PostfixExpression, t cc.Type, mode exprMode, flags flags) {
  9637  	// PostfixExpression '.' IDENTIFIER
  9638  	fld := n.Field
  9639  	if fld.Offset() != 0 {
  9640  		p.err(&n.Token2, "internal error, union field with non-zero offset: %s %v", n.Token2.Value, fld.Offset())
  9641  	}
  9642  	switch {
  9643  	case n.Operand.Type().IsBitFieldType():
  9644  		panic(todo("", p.pos(n)))
  9645  	case n.Operand.Type().Kind() == cc.Array:
  9646  		panic(todo("", p.pos(n)))
  9647  	default:
  9648  		if fld.IsBitField() {
  9649  			p.err(&n.Token2, "internal error, wrong function for accessing a bit field: %s", n.Token2.Value)
  9650  		}
  9651  		pe := n.PostfixExpression.Operand.Type()
  9652  		defer p.w("%s", p.convert(n, n.Operand, t, flags))
  9653  		p.w("(*%s)(unsafe.Pointer(", p.typ(n, n.Operand.Type()))
  9654  		p.postfixExpression(f, n.PostfixExpression, pe, exprAddrOf, flags)
  9655  		p.w("))")
  9656  	}
  9657  }
  9658  
  9659  func (p *project) postfixExpressionSelectIndex(f *function, n *cc.PostfixExpression, t cc.Type, mode exprMode, flags flags) {
  9660  	// PostfixExpression '[' Expression ']'
  9661  	switch k := p.opKind(f, n.PostfixExpression, n.PostfixExpression.Operand.Type()); k {
  9662  	case opArray:
  9663  		p.postfixExpressionSelectIndexArray(f, n, t, mode, flags)
  9664  	case opNormal:
  9665  		p.postfixExpressionSelectIndexNormal(f, n, t, mode, flags)
  9666  	case opArrayParameter:
  9667  		p.postfixExpressionSelectIndexArrayParamater(f, n, t, mode, flags)
  9668  	default:
  9669  		panic(todo("", n.Position(), k))
  9670  	}
  9671  }
  9672  
  9673  func (p *project) postfixExpressionSelectIndexArrayParamater(f *function, n *cc.PostfixExpression, t cc.Type, mode exprMode, flags flags) {
  9674  	pe := n.PostfixExpression.Operand.Type()
  9675  	// PostfixExpression '[' Expression ']'
  9676  	switch {
  9677  	case n.Operand.Type().IsBitFieldType():
  9678  		panic(todo("", p.pos(n)))
  9679  	case n.Operand.Type().Kind() == cc.Array:
  9680  		panic(todo("", p.pos(n)))
  9681  	default:
  9682  		p.w("(*%s)(unsafe.Pointer(", p.typ(n, pe.Elem()))
  9683  		p.postfixExpression(f, n.PostfixExpression, pe, exprValue, flags)
  9684  		if !n.Expression.Operand.IsZero() {
  9685  			p.nzUintptr(n, func() { p.expression(f, n.Expression, n.Expression.Operand.Type(), exprValue, flags) }, n.Expression.Operand)
  9686  			if sz := pe.Decay().Elem().Size(); sz != 1 {
  9687  				p.w("*%d", sz)
  9688  			}
  9689  		}
  9690  		p.w("))")
  9691  	}
  9692  }
  9693  
  9694  func (p *project) postfixExpressionSelectIndexNormal(f *function, n *cc.PostfixExpression, t cc.Type, mode exprMode, flags flags) {
  9695  	pe := n.PostfixExpression.Operand.Type()
  9696  	// PostfixExpression '[' Expression ']'
  9697  	switch {
  9698  	case n.Operand.Type().IsBitFieldType():
  9699  		panic(todo("", p.pos(n)))
  9700  	case n.Operand.Type().Kind() == cc.Array:
  9701  		panic(todo("", p.pos(n)))
  9702  	case pe.Kind() != cc.Ptr:
  9703  		p.w("(*%s)(unsafe.Pointer(", p.typ(n, pe.Elem()))
  9704  		p.postfixExpression(f, n.PostfixExpression, pe, exprAddrOf, flags)
  9705  		if !n.Expression.Operand.IsZero() {
  9706  			p.nzUintptr(n, func() { p.expression(f, n.Expression, n.Expression.Operand.Type(), exprValue, flags) }, n.Expression.Operand)
  9707  			if sz := pe.Decay().Elem().Size(); sz != 1 {
  9708  				p.w("*%d", sz)
  9709  			}
  9710  		}
  9711  		p.w("))")
  9712  	default:
  9713  		p.w("(*%s)(unsafe.Pointer(", p.typ(n, pe.Elem()))
  9714  		p.postfixExpression(f, n.PostfixExpression, pe, exprValue, flags)
  9715  		if !n.Expression.Operand.IsZero() {
  9716  			p.nzUintptr(n, func() { p.expression(f, n.Expression, n.Expression.Operand.Type(), exprValue, flags) }, n.Expression.Operand)
  9717  			if sz := pe.Decay().Elem().Size(); sz != 1 {
  9718  				p.w("*%d", sz)
  9719  			}
  9720  		}
  9721  		p.w("))")
  9722  	}
  9723  }
  9724  
  9725  func (p *project) postfixExpressionSelectIndexArray(f *function, n *cc.PostfixExpression, t cc.Type, mode exprMode, flags flags) {
  9726  	// PostfixExpression '[' Expression ']'
  9727  	switch {
  9728  	case n.Operand.Type().IsBitFieldType():
  9729  		panic(todo("", p.pos(n)))
  9730  	case n.Operand.Type().Kind() == cc.Array:
  9731  		panic(todo("", p.pos(n)))
  9732  	default:
  9733  		pe := n.PostfixExpression.Operand.Type()
  9734  		p.postfixExpression(f, n.PostfixExpression, pe, mode, flags)
  9735  		p.w("[")
  9736  		p.expression(f, n.Expression, n.Expression.Operand.Type(), exprValue, flags)
  9737  		p.w("]")
  9738  	}
  9739  }
  9740  
  9741  func (p *project) postfixExpressionAddrOf(f *function, n *cc.PostfixExpression, t cc.Type, mode exprMode, flags flags) {
  9742  	switch n.Case {
  9743  	case cc.PostfixExpressionPrimary: // PrimaryExpression
  9744  		p.primaryExpression(f, n.PrimaryExpression, t, mode, flags)
  9745  	case cc.PostfixExpressionIndex: // PostfixExpression '[' Expression ']'
  9746  		p.postfixExpressionAddrOfIndex(f, n, t, mode, flags)
  9747  	case cc.PostfixExpressionCall: // PostfixExpression '(' ArgumentExpressionList ')'
  9748  		ot := n.Operand.Type()
  9749  		switch ot.Kind() {
  9750  		case cc.Struct, cc.Union:
  9751  			// ok
  9752  		default:
  9753  			p.err(n, "cannot take address of value of type %v", n.Operand.Type())
  9754  			return
  9755  		}
  9756  
  9757  		if p.pass1 {
  9758  			off := roundup(f.off, uintptr(ot.Align()))
  9759  			f.complits[n] = off
  9760  			f.off += ot.Size()
  9761  			return
  9762  		}
  9763  
  9764  		off := f.complits[n]
  9765  		p.w("func() uintptr { *(*%s)(unsafe.Pointer(%s%s)) = ", p.typ(n, ot), f.bpName, nonZeroUintptr(off))
  9766  		p.postfixExpressionValue(f, n, ot, exprValue, flags)
  9767  		p.w("; return %s%s }()", f.bpName, nonZeroUintptr(off))
  9768  	case cc.PostfixExpressionSelect: // PostfixExpression '.' IDENTIFIER
  9769  		p.postfixExpressionAddrOfSelect(f, n, t, mode, flags)
  9770  	case cc.PostfixExpressionPSelect: // PostfixExpression "->" IDENTIFIER
  9771  		p.postfixExpressionAddrOfPSelect(f, n, t, mode, flags)
  9772  	case cc.PostfixExpressionInc: // PostfixExpression "++"
  9773  		p.postfixExpressionIncDec(f, n, "++", "+=", t, exprLValue, flags)
  9774  	case cc.PostfixExpressionDec: // PostfixExpression "--"
  9775  		panic(todo("", p.pos(n)))
  9776  	case cc.PostfixExpressionComplit: // '(' TypeName ')' '{' InitializerList ',' '}'
  9777  		tn := n.TypeName.Type()
  9778  		switch tn.Decay().Kind() {
  9779  		case cc.Ptr:
  9780  			switch tn.Kind() {
  9781  			case cc.Array:
  9782  				switch {
  9783  				case p.pass1:
  9784  					off := roundup(f.off, uintptr(tn.Elem().Align()))
  9785  					f.complits[n] = off
  9786  					f.off += tn.Size()
  9787  				default:
  9788  					off := f.complits[n]
  9789  					p.w(" func() uintptr { *(*%s)(unsafe.Pointer(%s%s)) = ", p.typ(n, tn), f.bpName, nonZeroUintptr(off))
  9790  					p.initializer(f, &cc.Initializer{Case: cc.InitializerInitList, InitializerList: n.InitializerList}, tn, cc.Automatic, nil)
  9791  					p.w("; return %s%s }()", f.bpName, nonZeroUintptr(off))
  9792  				}
  9793  			default:
  9794  				panic(todo("%v: %v", n.Position(), tn))
  9795  			}
  9796  		default:
  9797  			switch {
  9798  			case p.pass1:
  9799  				off := roundup(f.off, uintptr(tn.Align()))
  9800  				f.complits[n] = off
  9801  				f.off += tn.Size()
  9802  			default:
  9803  				off := f.complits[n]
  9804  				p.w(" func() uintptr { *(*%s)(unsafe.Pointer(%s%s)) = ", p.typ(n, tn), f.bpName, nonZeroUintptr(off))
  9805  				p.initializer(f, &cc.Initializer{Case: cc.InitializerInitList, InitializerList: n.InitializerList}, tn, cc.Automatic, nil)
  9806  				p.w("; return %s%s }()", f.bpName, nonZeroUintptr(off))
  9807  			}
  9808  		}
  9809  	case cc.PostfixExpressionTypeCmp: // "__builtin_types_compatible_p" '(' TypeName ',' TypeName ')'
  9810  		panic(todo("", p.pos(n)))
  9811  	case cc.PostfixExpressionChooseExpr:
  9812  		panic(todo("", p.pos(n)))
  9813  	default:
  9814  		panic(todo("%v: internal error: %v", n.Position(), n.Case))
  9815  	}
  9816  }
  9817  
  9818  func (p *project) postfixExpressionAddrOfPSelect(f *function, n *cc.PostfixExpression, t cc.Type, mode exprMode, flags flags) {
  9819  	// PostfixExpression "->" IDENTIFIER
  9820  	p.w("(")
  9821  	defer p.w(")")
  9822  	pe := n.PostfixExpression.Operand.Type()
  9823  	switch {
  9824  	case n.Operand.Type().IsBitFieldType():
  9825  		p.postfixExpression(f, n.PostfixExpression, pe, exprValue, flags)
  9826  		p.bitFldOff(pe.Elem(), n.Token2)
  9827  	case pe.Kind() == cc.Array:
  9828  		p.postfixExpression(f, n.PostfixExpression, pe, exprDecay, flags)
  9829  		p.fldOff(pe.Elem(), n.Token2)
  9830  	default:
  9831  		p.postfixExpression(f, n.PostfixExpression, pe, exprValue, flags)
  9832  		p.fldOff(pe.Elem(), n.Token2)
  9833  	}
  9834  }
  9835  
  9836  func (p *project) postfixExpressionAddrOfIndex(f *function, n *cc.PostfixExpression, t cc.Type, mode exprMode, flags flags) {
  9837  	// PostfixExpression '[' Expression ']'
  9838  	p.w("(")
  9839  	defer p.w(")")
  9840  	switch {
  9841  	case n.Operand.Type().Kind() == cc.Array:
  9842  		fallthrough
  9843  	default:
  9844  		pe := n.PostfixExpression.Operand.Type()
  9845  		d := n.PostfixExpression.Declarator()
  9846  		switch {
  9847  		case pe.Kind() == cc.Ptr:
  9848  			p.postfixExpression(f, n.PostfixExpression, pe, exprValue, flags)
  9849  		case pe.Kind() == cc.Array && d != nil && d.IsParameter:
  9850  			p.postfixExpression(f, n.PostfixExpression, pe, exprValue, flags)
  9851  		default:
  9852  			p.postfixExpression(f, n.PostfixExpression, pe, mode, flags)
  9853  		}
  9854  		if !n.Expression.Operand.IsZero() {
  9855  			p.nzUintptr(n, func() { p.expression(f, n.Expression, n.Expression.Operand.Type(), exprValue, flags) }, n.Expression.Operand)
  9856  			if sz := pe.Decay().Elem().Size(); sz != 1 {
  9857  				p.w("*%d", sz)
  9858  			}
  9859  		}
  9860  	}
  9861  }
  9862  
  9863  func (p *project) postfixExpressionAddrOfSelect(f *function, n *cc.PostfixExpression, t cc.Type, mode exprMode, flags flags) {
  9864  	// PostfixExpression '.' IDENTIFIER
  9865  	p.w("(")
  9866  	defer p.w(")")
  9867  	switch {
  9868  	case n.Operand.Type().IsBitFieldType():
  9869  		pe := n.PostfixExpression.Operand.Type()
  9870  		p.postfixExpression(f, n.PostfixExpression, nil, mode, flags)
  9871  		p.bitFldOff(pe, n.Token2)
  9872  	case n.Operand.Type().Kind() == cc.Array:
  9873  		fallthrough
  9874  	default:
  9875  		pe := n.PostfixExpression.Operand.Type()
  9876  		p.postfixExpression(f, n.PostfixExpression, nil, mode, flags)
  9877  		p.fldOff(pe, n.Token2)
  9878  	}
  9879  }
  9880  
  9881  func (p *project) postfixExpressionFunc(f *function, n *cc.PostfixExpression, t cc.Type, mode exprMode, flags flags) {
  9882  	switch n.Case {
  9883  	case cc.PostfixExpressionPrimary: // PrimaryExpression
  9884  		p.primaryExpression(f, n.PrimaryExpression, t, mode, flags)
  9885  	case cc.PostfixExpressionIndex: // PostfixExpression '[' Expression ']'
  9886  		switch n.Operand.Type().Kind() {
  9887  		case cc.Ptr:
  9888  			switch et := n.Operand.Type().Elem(); et.Kind() {
  9889  			case cc.Function:
  9890  				p.fnVal(n, f, func() {
  9891  					p.postfixExpression(f, n, n.Operand.Type(), exprValue, flags)
  9892  				}, nil, n.Operand.Type(), 0, mode, flags)
  9893  			default:
  9894  				panic(todo("", p.pos(n), et, et.Kind()))
  9895  			}
  9896  		default:
  9897  			panic(todo("", n.Position(), n.Operand.Type()))
  9898  		}
  9899  	case cc.PostfixExpressionCall: // PostfixExpression '(' ArgumentExpressionList ')'
  9900  		switch n.Operand.Type().Kind() {
  9901  		case cc.Ptr:
  9902  			switch et := n.Operand.Type().Elem(); et.Kind() {
  9903  			case cc.Function:
  9904  				p.fnVal(n, f, func() {
  9905  					p.postfixExpressionCall(f, n, t, exprValue, flags)
  9906  				}, nil, n.Operand.Type(), 0, mode, flags)
  9907  			default:
  9908  				panic(todo("", p.pos(n), et, et.Kind()))
  9909  			}
  9910  		default:
  9911  			panic(todo("", n.Position(), n.Operand.Type()))
  9912  		}
  9913  	case cc.PostfixExpressionSelect: // PostfixExpression '.' IDENTIFIER
  9914  		switch n.Operand.Type().Kind() {
  9915  		case cc.Ptr:
  9916  			switch n.Operand.Type().Kind() {
  9917  			case cc.Ptr:
  9918  				switch et := n.Operand.Type().Elem(); et.Kind() {
  9919  				case cc.Function:
  9920  					p.fnVal(n, f, func() { p.postfixExpression(f, n, p.ptrType, exprValue, flags) }, nil, n.Operand.Type(), 0, mode, flags)
  9921  				default:
  9922  					panic(todo("", p.pos(n), et, et.Kind()))
  9923  				}
  9924  			default:
  9925  				panic(todo("", p.pos(n), n.Operand.Type(), n.Operand.Type().Kind()))
  9926  			}
  9927  		default:
  9928  			panic(todo("", n.Position(), n.Operand.Type()))
  9929  		}
  9930  	case cc.PostfixExpressionPSelect: // PostfixExpression "->" IDENTIFIER
  9931  		p.fnVal(n, f, func() { p.postfixExpression(f, n, p.ptrType, exprValue, flags) }, nil, n.Operand.Type(), 0, mode, flags)
  9932  	case cc.PostfixExpressionInc: // PostfixExpression "++"
  9933  		panic(todo("", p.pos(n)))
  9934  	case cc.PostfixExpressionDec: // PostfixExpression "--"
  9935  		panic(todo("", p.pos(n)))
  9936  	case cc.PostfixExpressionComplit: // '(' TypeName ')' '{' InitializerList ',' '}'
  9937  		panic(todo("", p.pos(n)))
  9938  	case cc.PostfixExpressionTypeCmp: // "__builtin_types_compatible_p" '(' TypeName ',' TypeName ')'
  9939  		panic(todo("", p.pos(n)))
  9940  	case cc.PostfixExpressionChooseExpr:
  9941  		panic(todo("", p.pos(n)))
  9942  	default:
  9943  		panic(todo("%v: internal error: %v", n.Position(), n.Case))
  9944  	}
  9945  }
  9946  
  9947  func (p *project) postfixExpressionVoid(f *function, n *cc.PostfixExpression, t cc.Type, mode exprMode, flags flags) {
  9948  	switch n.Case {
  9949  	case cc.PostfixExpressionPrimary: // PrimaryExpression
  9950  		p.primaryExpression(f, n.PrimaryExpression, t, mode, flags)
  9951  	case cc.PostfixExpressionIndex: // PostfixExpression '[' Expression ']'
  9952  		p.w("_ = ")
  9953  		p.postfixExpression(f, n, n.Operand.Type(), exprValue, flags)
  9954  	case cc.PostfixExpressionCall: // PostfixExpression '(' ArgumentExpressionList ')'
  9955  		p.postfixExpressionCall(f, n, n.Operand.Type(), mode, flags)
  9956  	case cc.PostfixExpressionSelect: // PostfixExpression '.' IDENTIFIER
  9957  		p.w("_ = ")
  9958  		p.postfixExpression(f, n, n.Operand.Type(), exprValue, flags)
  9959  	case cc.PostfixExpressionPSelect: // PostfixExpression "->" IDENTIFIER
  9960  		p.w("_ = ")
  9961  		p.postfixExpression(f, n, n.Operand.Type(), exprValue, flags)
  9962  	case cc.PostfixExpressionInc: // PostfixExpression "++"
  9963  		p.postfixExpressionIncDec(f, n, "++", "+=", t, mode, flags)
  9964  	case cc.PostfixExpressionDec: // PostfixExpression "--"
  9965  		p.postfixExpressionIncDec(f, n, "--", "-=", t, mode, flags)
  9966  	case cc.PostfixExpressionComplit: // '(' TypeName ')' '{' InitializerList ',' '}'
  9967  		tn := n.TypeName.Type()
  9968  		switch tn.Decay().Kind() {
  9969  		case cc.Ptr:
  9970  			switch tn.Kind() {
  9971  			case cc.Array:
  9972  				switch {
  9973  				case p.pass1:
  9974  					off := roundup(f.off, uintptr(tn.Elem().Align()))
  9975  					f.complits[n] = off
  9976  					f.off += tn.Size()
  9977  				default:
  9978  					off := f.complits[n]
  9979  					p.w("*(*%s)(unsafe.Pointer(%s%s)) = ", p.typ(n, tn), f.bpName, nonZeroUintptr(off))
  9980  					p.initializer(f, &cc.Initializer{Case: cc.InitializerInitList, InitializerList: n.InitializerList}, tn, cc.Automatic, nil)
  9981  				}
  9982  				return
  9983  			default:
  9984  				panic(todo("%v: %v", n.Position(), tn))
  9985  			}
  9986  		}
  9987  
  9988  		defer p.w("%s", p.convertType(n, tn, t, flags))
  9989  		p.w("_ = ")
  9990  		p.initializer(f, &cc.Initializer{Case: cc.InitializerInitList, InitializerList: n.InitializerList}, tn, cc.Automatic, nil)
  9991  	case cc.PostfixExpressionTypeCmp: // "__builtin_types_compatible_p" '(' TypeName ',' TypeName ')'
  9992  		panic(todo("", p.pos(n)))
  9993  	case cc.PostfixExpressionChooseExpr:
  9994  		panic(todo("", p.pos(n)))
  9995  	default:
  9996  		panic(todo("%v: internal error: %v", n.Position(), n.Case))
  9997  	}
  9998  }
  9999  
 10000  func (p *project) postfixExpressionValue(f *function, n *cc.PostfixExpression, t cc.Type, mode exprMode, flags flags) {
 10001  	switch n.Case {
 10002  	case cc.PostfixExpressionPrimary: // PrimaryExpression
 10003  		if p.isArray(f, n.PrimaryExpression, n.Operand.Type()) && t.Kind() == cc.Ptr {
 10004  			mode = exprDecay
 10005  		}
 10006  		p.primaryExpression(f, n.PrimaryExpression, t, mode, flags)
 10007  	case cc.PostfixExpressionIndex: // PostfixExpression '[' Expression ']'
 10008  		p.postfixExpressionValueIndex(f, n, t, mode, flags)
 10009  	case cc.PostfixExpressionCall: // PostfixExpression '(' ArgumentExpressionList ')'
 10010  		p.postfixExpressionCall(f, n, t, mode, flags)
 10011  	case cc.PostfixExpressionSelect: // PostfixExpression '.' IDENTIFIER
 10012  		p.postfixExpressionValueSelect(f, n, t, mode, flags)
 10013  	case cc.PostfixExpressionPSelect: // PostfixExpression "->" IDENTIFIER
 10014  		p.postfixExpressionValuePSelect(f, n, t, mode, flags)
 10015  	case cc.PostfixExpressionInc: // PostfixExpression "++"
 10016  		p.postfixExpressionIncDec(f, n, "++", "+=", t, mode, flags)
 10017  	case cc.PostfixExpressionDec: // PostfixExpression "--"
 10018  		p.postfixExpressionIncDec(f, n, "--", "-=", t, mode, flags)
 10019  	case cc.PostfixExpressionComplit: // '(' TypeName ')' '{' InitializerList ',' '}'
 10020  		tn := n.TypeName.Type()
 10021  		switch tn.Decay().Kind() {
 10022  		case cc.Ptr:
 10023  			switch tn.Kind() {
 10024  			case cc.Array:
 10025  				switch {
 10026  				case p.pass1:
 10027  					off := roundup(f.off, uintptr(tn.Elem().Align()))
 10028  					f.complits[n] = off
 10029  					f.off += tn.Size()
 10030  				default:
 10031  					off := f.complits[n]
 10032  					p.w(" func() uintptr { *(*%s)(unsafe.Pointer(%s%s)) = ", p.typ(n, tn), f.bpName, nonZeroUintptr(off))
 10033  					p.initializer(f, &cc.Initializer{Case: cc.InitializerInitList, InitializerList: n.InitializerList}, tn, cc.Automatic, nil)
 10034  					p.w("; return %s%s }()", f.bpName, nonZeroUintptr(off))
 10035  				}
 10036  				return
 10037  			default:
 10038  				panic(todo("%v: %v", n.Position(), tn))
 10039  			}
 10040  		}
 10041  
 10042  		defer p.w("%s", p.convertType(n, tn, t, flags))
 10043  		p.initializer(f, &cc.Initializer{Case: cc.InitializerInitList, InitializerList: n.InitializerList}, tn, cc.Automatic, nil)
 10044  	case cc.PostfixExpressionTypeCmp: // "__builtin_types_compatible_p" '(' TypeName ',' TypeName ')'
 10045  		// Built-in Function: int __builtin_types_compatible_p (type1, type2) You can
 10046  		// use the built-in function __builtin_types_compatible_p to determine whether
 10047  		// two types are the same.
 10048  		//
 10049  		// This built-in function returns 1 if the unqualified versions of the types
 10050  		// type1 and type2 (which are types, not expressions) are compatible, 0
 10051  		// otherwise. The result of this built-in function can be used in integer
 10052  		// constant expressions.
 10053  		//
 10054  		// This built-in function ignores top level qualifiers (e.g., const, volatile).
 10055  		// For example, int is equivalent to const int.
 10056  		//
 10057  		// The type int[] and int[5] are compatible. On the other hand, int and char *
 10058  		// are not compatible, even if the size of their types, on the particular
 10059  		// architecture are the same. Also, the amount of pointer indirection is taken
 10060  		// into account when determining similarity. Consequently, short * is not
 10061  		// similar to short **. Furthermore, two types that are typedefed are
 10062  		// considered compatible if their underlying types are compatible.
 10063  		//
 10064  		// An enum type is not considered to be compatible with another enum type even
 10065  		// if both are compatible with the same integer type; this is what the C
 10066  		// standard specifies. For example, enum {foo, bar} is not similar to enum
 10067  		// {hot, dog}.
 10068  		//
 10069  		// You typically use this function in code whose execution varies depending on
 10070  		// the arguments’ types. For example:
 10071  		//
 10072  		//	#define foo(x)                                                  \
 10073  		//	  ({                                                           \
 10074  		//	    typeof (x) tmp = (x);                                       \
 10075  		//	    if (__builtin_types_compatible_p (typeof (x), long double)) \
 10076  		//	      tmp = foo_long_double (tmp);                              \
 10077  		//	    else if (__builtin_types_compatible_p (typeof (x), double)) \
 10078  		//	      tmp = foo_double (tmp);                                   \
 10079  		//	    else if (__builtin_types_compatible_p (typeof (x), float))  \
 10080  		//	      tmp = foo_float (tmp);                                    \
 10081  		//	    else                                                        \
 10082  		//	      abort ();                                                 \
 10083  		//	    tmp;                                                        \
 10084  		//	  })
 10085  		//
 10086  		// Note: This construct is only available for C.
 10087  		p.w(" %d ", n.Operand.Value())
 10088  	case cc.PostfixExpressionChooseExpr: // "__builtin_choose_expr" '(' AssignmentExpression ',' AssignmentExpression ',' AssignmentExpression ')'
 10089  		// You can use the built-in function __builtin_choose_expr to evaluate code
 10090  		// depending on the value of a constant expression. This built-in function
 10091  		// returns exp1 if const_exp, which is an integer constant expression, is
 10092  		// nonzero. Otherwise it returns exp2.
 10093  		//
 10094  		// This built-in function is analogous to the ‘? :’ operator in C, except that
 10095  		// the expression returned has its type unaltered by promotion rules. Also, the
 10096  		// built-in function does not evaluate the expression that is not chosen. For
 10097  		// example, if const_exp evaluates to true, exp2 is not evaluated even if it
 10098  		// has side effects.
 10099  		//
 10100  		// This built-in function can return an lvalue if the chosen argument is an
 10101  		// lvalue.
 10102  		//
 10103  		// If exp1 is returned, the return type is the same as exp1’s type. Similarly,
 10104  		// if exp2 is returned, its return type is the same as exp2.
 10105  		//
 10106  		// Example:
 10107  		//
 10108  		// 	#define foo(x)                                                \
 10109  		// 	  __builtin_choose_expr (                                     \
 10110  		// 	    __builtin_types_compatible_p (typeof (x), double),        \
 10111  		// 	    foo_double (x),                                           \
 10112  		// 	    __builtin_choose_expr (                                   \
 10113  		// 	      __builtin_types_compatible_p (typeof (x), float),       \
 10114  		// 	      foo_float (x),                                          \
 10115  		// 	      /* The void expression results in a compile-time error  \
 10116  		// 	         when assigning the result to something.  */          \
 10117  		// 	      (void)0))
 10118  		//
 10119  		// Note: This construct is only available for C. Furthermore, the unused
 10120  		// expression (exp1 or exp2 depending on the value of const_exp) may still
 10121  		// generate syntax errors. This may change in future revisions.
 10122  		switch op := n.AssignmentExpression.Operand; {
 10123  		case op.IsNonZero():
 10124  			p.assignmentExpression(f, n.AssignmentExpression2, t, mode, flags)
 10125  		case op.IsZero():
 10126  			p.assignmentExpression(f, n.AssignmentExpression3, t, mode, flags)
 10127  		default:
 10128  			panic(todo(""))
 10129  		}
 10130  	default:
 10131  		panic(todo("%v: internal error: %v", n.Position(), n.Case))
 10132  	}
 10133  }
 10134  
 10135  func (p *project) postfixExpressionValuePSelect(f *function, n *cc.PostfixExpression, t cc.Type, mode exprMode, flags flags) {
 10136  	// PostfixExpression "->" IDENTIFIER
 10137  	switch k := p.opKind(f, n.PostfixExpression, n.PostfixExpression.Operand.Type().Elem()); k {
 10138  	case opStruct:
 10139  		p.postfixExpressionValuePSelectStruct(f, n, t, mode, flags)
 10140  	case opUnion:
 10141  		p.postfixExpressionValuePSelectUnion(f, n, t, mode, flags)
 10142  	default:
 10143  		panic(todo("", n.Position(), k))
 10144  	}
 10145  }
 10146  
 10147  func (p *project) postfixExpressionValuePSelectUnion(f *function, n *cc.PostfixExpression, t cc.Type, mode exprMode, flags flags) {
 10148  	// PostfixExpression "->" IDENTIFIER
 10149  	fld := n.Field
 10150  	if fld.Offset() != 0 {
 10151  		p.err(&n.Token2, "internal error, union field with non-zero offset: %s %v", n.Token2.Value, fld.Offset())
 10152  	}
 10153  	pe := n.PostfixExpression.Operand.Type()
 10154  	switch {
 10155  	case n.Operand.Type().IsBitFieldType():
 10156  		panic(todo("", p.pos(n)))
 10157  	case n.Operand.Type().Kind() == cc.Array:
 10158  		panic(todo("", p.pos(n)))
 10159  	default:
 10160  		if fld.IsBitField() {
 10161  			p.err(&n.Token2, "internal error, wrong function for accessing a bit field: %s", n.Token2.Value)
 10162  		}
 10163  		defer p.w("%s", p.convert(n, n.Operand, t, flags))
 10164  		p.w("*(*%s)(unsafe.Pointer(", p.typ(n, n.Operand.Type()))
 10165  		p.postfixExpression(f, n.PostfixExpression, pe, exprValue, flags)
 10166  		p.w("/* .%s */", p.fieldName(n, n.Token2.Value))
 10167  		p.w("))")
 10168  	}
 10169  }
 10170  
 10171  func (p *project) postfixExpressionValuePSelectStruct(f *function, n *cc.PostfixExpression, t cc.Type, mode exprMode, flags flags) {
 10172  	// PostfixExpression "->" IDENTIFIER
 10173  	fld := n.Field
 10174  	pe := n.PostfixExpression.Operand.Type()
 10175  	k := p.opKind(f, n.PostfixExpression, n.PostfixExpression.Operand.Type())
 10176  	switch {
 10177  	case n.Operand.Type().IsBitFieldType():
 10178  		p.w("(")
 10179  		defer p.w(")")
 10180  		fld := n.Field
 10181  		defer p.w("%s", p.convertType(n, fld.Promote(), t, flags))
 10182  		switch pe.Kind() {
 10183  		case cc.Array:
 10184  			x := p.convertType(n, nil, fld.Promote(), flags)
 10185  			p.w("*(*uint%d)(unsafe.Pointer(", fld.BitFieldBlockWidth())
 10186  			p.postfixExpression(f, n.PostfixExpression, pe, exprDecay, flags)
 10187  			p.bitFldOff(pe.Elem(), n.Token2)
 10188  			p.w("))")
 10189  			p.w("&%#x>>%d%s", fld.Mask(), fld.BitFieldOffset(), x)
 10190  			if fld.Type().IsSignedType() {
 10191  				panic(todo(""))
 10192  				p.w("<<%d>>%[1]d", int(fld.Promote().Size()*8)-fld.BitFieldWidth())
 10193  			}
 10194  		default:
 10195  			x := p.convertType(n, nil, fld.Promote(), flags)
 10196  			p.w("*(*uint%d)(unsafe.Pointer(", fld.BitFieldBlockWidth())
 10197  			p.postfixExpression(f, n.PostfixExpression, pe, exprValue, flags)
 10198  			p.bitFldOff(pe.Elem(), n.Token2)
 10199  			p.w("))&%#x>>%d%s", fld.Mask(), fld.BitFieldOffset(), x)
 10200  			if fld.Type().IsSignedType() {
 10201  				p.w("<<%d>>%[1]d", int(fld.Promote().Size()*8)-fld.BitFieldWidth())
 10202  			}
 10203  		}
 10204  	case n.Operand.Type().Kind() == cc.Array:
 10205  		defer p.w("%s", p.convertType(n, n.Operand.Type().Decay(), t.Decay(), flags))
 10206  		p.postfixExpression(f, n.PostfixExpression, pe, exprValue, flags)
 10207  		p.fldOff(n.PostfixExpression.Operand.Type().Elem(), n.Token2)
 10208  	case k == opArray:
 10209  		defer p.w("%s", p.convert(n, n.Operand, t, flags))
 10210  		p.postfixExpression(f, n.PostfixExpression, pe, exprValue, flags)
 10211  		p.w("[0].%s", p.fieldName(n, n.Token2.Value))
 10212  	default:
 10213  		if fld.IsBitField() {
 10214  			p.err(&n.Token2, "internal error, wrong function for accessing a bit field: %s", n.Token2.Value)
 10215  		}
 10216  		defer p.w("%s", p.convert(n, n.Operand, t, flags))
 10217  		et := pe.Elem()
 10218  		fld, path, ok := et.FieldByName2(n.Token2.Value)
 10219  		switch {
 10220  		case !ok:
 10221  			panic(todo(""))
 10222  		case fld.InUnion():
 10223  			p.w("*(*%s)(unsafe.Pointer(", p.typ(n, n.Operand.Type()))
 10224  			p.postfixExpression(f, n.PostfixExpression, pe, exprValue, flags)
 10225  			p.w("%s))", nonZeroUintptr(pathOff(et, path)))
 10226  		case len(path) != 1:
 10227  			panic(todo(""))
 10228  		default:
 10229  			p.w("(*%s)(unsafe.Pointer(", p.typ(n, pe.Elem()))
 10230  			p.postfixExpression(f, n.PostfixExpression, pe, exprValue, flags)
 10231  			p.w(")).%s", p.fieldName(n, n.Token2.Value))
 10232  		}
 10233  	}
 10234  }
 10235  
 10236  func pathOff(t cc.Type, path []int) (r uintptr) {
 10237  	for len(path) != 0 {
 10238  		f := t.FieldByIndex(path[:1])
 10239  		r += f.Offset()
 10240  		path = path[1:]
 10241  		t = f.Type()
 10242  	}
 10243  	return r
 10244  }
 10245  
 10246  func (p *project) postfixExpressionValueIndex(f *function, n *cc.PostfixExpression, t cc.Type, mode exprMode, flags flags) {
 10247  	// PostfixExpression '[' Expression ']'
 10248  	switch k := p.opKind(f, n.PostfixExpression, n.PostfixExpression.Operand.Type()); k {
 10249  	case opArray:
 10250  		p.postfixExpressionValueIndexArray(f, n, t, mode, flags)
 10251  	case opNormal:
 10252  		p.postfixExpressionValueIndexNormal(f, n, t, mode, flags)
 10253  	case opArrayParameter:
 10254  		p.postfixExpressionValueIndexArrayParameter(f, n, t, mode, flags)
 10255  	default:
 10256  		panic(todo("", n.Position(), k))
 10257  	}
 10258  }
 10259  func (p *project) postfixExpressionValueIndexArrayParameter(f *function, n *cc.PostfixExpression, t cc.Type, mode exprMode, flags flags) {
 10260  	// PostfixExpression '[' Expression ']'
 10261  	pe := n.PostfixExpression.Operand.Type()
 10262  	switch {
 10263  	case n.Operand.Type().Kind() == cc.Array:
 10264  		defer p.w("%s", p.convert(n, n.Operand, t, flags))
 10265  		p.w("(")
 10266  		defer p.w(")")
 10267  		p.postfixExpression(f, n.PostfixExpression, pe, exprValue, flags)
 10268  		if !n.Expression.Operand.IsZero() {
 10269  			p.nzUintptr(n, func() { p.expression(f, n.Expression, n.Expression.Operand.Type(), exprValue, flags) }, n.Expression.Operand)
 10270  			if sz := pe.Elem().Size(); sz != 1 {
 10271  				p.w("*%d", sz)
 10272  			}
 10273  		}
 10274  	default:
 10275  		defer p.w("%s", p.convert(n, n.Operand, t, flags))
 10276  		p.w("*(*%s)(unsafe.Pointer(", p.typ(n, pe.Elem()))
 10277  		p.postfixExpression(f, n.PostfixExpression, pe, exprValue, flags)
 10278  		if !n.Expression.Operand.IsZero() {
 10279  			p.nzUintptr(n, func() { p.expression(f, n.Expression, n.Expression.Operand.Type(), exprValue, flags) }, n.Expression.Operand)
 10280  			if sz := pe.Elem().Size(); sz != 1 {
 10281  				p.w("*%d", sz)
 10282  			}
 10283  		}
 10284  		p.w("))")
 10285  	}
 10286  }
 10287  
 10288  func (p *project) postfixExpressionValueIndexNormal(f *function, n *cc.PostfixExpression, t cc.Type, mode exprMode, flags flags) {
 10289  	// PostfixExpression '[' Expression ']'
 10290  	switch {
 10291  	case n.Operand.Type().Kind() == cc.Array:
 10292  		p.w("(")
 10293  		defer p.w(")")
 10294  		pe := n.PostfixExpression.Operand.Type()
 10295  		defer p.w("%s", p.convert(n, n.Operand, t, flags))
 10296  		p.postfixExpression(f, n.PostfixExpression, pe, exprValue, flags)
 10297  		if !n.Expression.Operand.IsZero() {
 10298  			p.nzUintptr(n, func() { p.expression(f, n.Expression, n.Expression.Operand.Type(), exprValue, flags) }, n.Expression.Operand)
 10299  			if sz := pe.Elem().Size(); sz != 1 {
 10300  				p.w("*%d", sz)
 10301  			}
 10302  		}
 10303  	default:
 10304  		switch pe := n.PostfixExpression.Operand.Type(); pe.Kind() {
 10305  		case cc.Ptr:
 10306  			defer p.w("%s", p.convert(n, n.Operand, t, flags))
 10307  			p.w("*(*%s)(unsafe.Pointer(", p.typ(n, pe.Elem()))
 10308  			p.postfixExpression(f, n.PostfixExpression, pe, exprValue, flags)
 10309  			if !n.Expression.Operand.IsZero() {
 10310  				p.nzUintptr(n, func() { p.expression(f, n.Expression, n.Expression.Operand.Type(), exprValue, flags) }, n.Expression.Operand)
 10311  				if sz := pe.Elem().Size(); sz != 1 {
 10312  					p.w("*%d", sz)
 10313  				}
 10314  			}
 10315  			p.w("))")
 10316  		case cc.Array:
 10317  			defer p.w("%s", p.convert(n, n.Operand, t, flags))
 10318  			p.w("*(*%s)(unsafe.Pointer(", p.typ(n, pe.Elem()))
 10319  			p.postfixExpression(f, n.PostfixExpression, pe, exprDecay, flags)
 10320  			if !n.Expression.Operand.IsZero() {
 10321  				p.nzUintptr(n, func() { p.expression(f, n.Expression, n.Expression.Operand.Type(), exprValue, flags) }, n.Expression.Operand)
 10322  				if sz := pe.Elem().Size(); sz != 1 {
 10323  					p.w("*%d", sz)
 10324  				}
 10325  			}
 10326  			p.w("))")
 10327  		default:
 10328  			panic(todo("", p.pos(n), pe, pe.Kind()))
 10329  		}
 10330  	}
 10331  }
 10332  
 10333  func (p *project) postfixExpressionValueIndexArray(f *function, n *cc.PostfixExpression, t cc.Type, mode exprMode, flags flags) {
 10334  	// PostfixExpression '[' Expression ']'
 10335  	pe := n.PostfixExpression.Operand.Type()
 10336  	switch n.Operand.Type().Kind() {
 10337  	case cc.Array:
 10338  		defer p.w("%s", p.convert(n, n.Operand, t, flags))
 10339  		p.w("(")
 10340  		defer p.w(")")
 10341  		p.postfixExpression(f, n.PostfixExpression, pe, exprDecay, flags)
 10342  		if !n.Expression.Operand.IsZero() {
 10343  			p.nzUintptr(n, func() { p.expression(f, n.Expression, n.Expression.Operand.Type(), exprValue, flags) }, n.Expression.Operand)
 10344  			if sz := pe.Elem().Size(); sz != 1 {
 10345  				p.w("*%d", sz)
 10346  			}
 10347  		}
 10348  	default:
 10349  		defer p.w("%s", p.convert(n, n.Operand, t, flags))
 10350  		p.postfixExpression(f, n.PostfixExpression, pe, mode, flags)
 10351  		p.w("[")
 10352  		p.expression(f, n.Expression, n.Expression.Operand.Type(), exprValue, flags)
 10353  		p.w("]")
 10354  	}
 10355  }
 10356  
 10357  func (p *project) postfixExpressionValueSelect(f *function, n *cc.PostfixExpression, t cc.Type, mode exprMode, flags flags) {
 10358  	// PostfixExpression '.' IDENTIFIER
 10359  	switch k := p.opKind(f, n.PostfixExpression, n.PostfixExpression.Operand.Type()); k {
 10360  	case opStruct:
 10361  		p.postfixExpressionValueSelectStruct(f, n, t, mode, flags)
 10362  	case opUnion:
 10363  		p.postfixExpressionValueSelectUnion(f, n, t, mode, flags)
 10364  	default:
 10365  		panic(todo("", n.Position(), k))
 10366  	}
 10367  }
 10368  
 10369  func (p *project) postfixExpressionValueSelectUnion(f *function, n *cc.PostfixExpression, t cc.Type, mode exprMode, flags flags) {
 10370  	// PostfixExpression '.' IDENTIFIER
 10371  	pe := n.PostfixExpression.Operand.Type()
 10372  	fld := n.Field
 10373  	switch {
 10374  	case n.Operand.Type().IsBitFieldType():
 10375  		p.w("(")
 10376  		defer p.w("%s)", p.convertType(n, fld.Promote(), t, flags))
 10377  		x := p.convertType(n, nil, fld.Promote(), flags)
 10378  		p.w("*(*uint%d)(unsafe.Pointer(", fld.BitFieldBlockWidth())
 10379  		p.postfixExpression(f, n.PostfixExpression, pe, exprAddrOf, flags)
 10380  		p.bitFldOff(pe, n.Token2)
 10381  		p.w("))&%#x>>%d%s", fld.Mask(), fld.BitFieldOffset(), x)
 10382  		if fld.Type().IsSignedType() {
 10383  			p.w("<<%d>>%[1]d", int(fld.Promote().Size()*8)-fld.BitFieldWidth())
 10384  		}
 10385  	case n.Operand.Type().Kind() == cc.Array:
 10386  		p.postfixExpression(f, n.PostfixExpression, pe, exprAddrOf, flags)
 10387  	default:
 10388  		if fld.IsBitField() {
 10389  			p.err(&n.Token2, "internal error, wrong function for accessing a bit field: %s", n.Token2.Value)
 10390  		}
 10391  		defer p.w("%s", p.convert(n, n.Operand, t, flags))
 10392  		p.w("*(*%s)(unsafe.Pointer(", p.typ(n, n.Operand.Type()))
 10393  		p.postfixExpression(f, n.PostfixExpression, pe, exprAddrOf, flags)
 10394  		p.w("))")
 10395  	}
 10396  }
 10397  
 10398  func (p *project) postfixExpressionValueSelectStruct(f *function, n *cc.PostfixExpression, t cc.Type, mode exprMode, flags flags) {
 10399  	// PostfixExpression '.' IDENTIFIER
 10400  	pe := n.PostfixExpression.Operand.Type()
 10401  	fld := n.Field
 10402  	switch {
 10403  	case n.Operand.Type().IsBitFieldType():
 10404  		p.w("(")
 10405  		defer p.w("%s)", p.convertType(n, fld.Promote(), t, flags))
 10406  		x := p.convertType(n, nil, fld.Promote(), flags)
 10407  		p.w("*(*uint%d)(unsafe.Pointer(", fld.BitFieldBlockWidth())
 10408  		p.postfixExpression(f, n.PostfixExpression, pe, exprAddrOf, flags)
 10409  		p.bitFldOff(pe, n.Token2)
 10410  		p.w("))&%#x>>%d%s", fld.Mask(), fld.BitFieldOffset(), x)
 10411  		if fld.Type().IsSignedType() {
 10412  			p.w("<<%d>>%[1]d", int(fld.Promote().Size()*8)-fld.BitFieldWidth())
 10413  		}
 10414  	case n.Operand.Type().Kind() == cc.Array:
 10415  		p.postfixExpression(f, n, t, exprDecay, flags)
 10416  	case fld.InUnion():
 10417  		defer p.w("%s", p.convert(n, n.Operand, t, flags))
 10418  		p.w("*(*%s)(unsafe.Pointer(", p.typ(n, fld.Type()))
 10419  		p.postfixExpression(f, n.PostfixExpression, pe, exprAddrOf, flags)
 10420  		p.fldOff(pe, n.Token2)
 10421  		p.w("))")
 10422  	default:
 10423  		if fld.IsBitField() {
 10424  			p.err(&n.Token2, "internal error, wrong function for accessing a bit field: %s", n.Token2.Value)
 10425  		}
 10426  		defer p.w("%s", p.convert(n, n.Operand, t, flags))
 10427  		p.postfixExpression(f, n.PostfixExpression, pe, exprSelect, flags)
 10428  		p.w(".%s", p.fieldName(n, n.Token2.Value))
 10429  	}
 10430  }
 10431  
 10432  func (p *project) postfixExpressionLValue(f *function, n *cc.PostfixExpression, t cc.Type, mode exprMode, flags flags) {
 10433  	switch n.Case {
 10434  	case cc.PostfixExpressionPrimary: // PrimaryExpression
 10435  		p.primaryExpression(f, n.PrimaryExpression, t, mode, flags)
 10436  	case cc.PostfixExpressionIndex: // PostfixExpression '[' Expression ']'
 10437  		p.postfixExpressionLValueIndex(f, n, t, mode, flags)
 10438  	case cc.PostfixExpressionCall: // PostfixExpression '(' ArgumentExpressionList ')'
 10439  		panic(todo("", p.pos(n)))
 10440  	case cc.PostfixExpressionSelect: // PostfixExpression '.' IDENTIFIER
 10441  		p.postfixExpressionLValueSelect(f, n, t, mode, flags)
 10442  	case cc.PostfixExpressionPSelect: // PostfixExpression "->" IDENTIFIER
 10443  		p.postfixExpressionLValuePSelect(f, n, t, mode, flags)
 10444  	case cc.PostfixExpressionInc: // PostfixExpression "++"
 10445  		p.postfixExpressionIncDec(f, n, "++", "+=", t, mode, flags)
 10446  	case cc.PostfixExpressionDec: // PostfixExpression "--"
 10447  		p.postfixExpressionIncDec(f, n, "--", "-=", t, mode, flags)
 10448  	case cc.PostfixExpressionComplit: // '(' TypeName ')' '{' InitializerList ',' '}'
 10449  		panic(todo("", p.pos(n)))
 10450  	case cc.PostfixExpressionTypeCmp: // "__builtin_types_compatible_p" '(' TypeName ',' TypeName ')'
 10451  		panic(todo("", p.pos(n)))
 10452  	case cc.PostfixExpressionChooseExpr:
 10453  		panic(todo("", p.pos(n)))
 10454  	default:
 10455  		panic(todo("%v: internal error: %v", n.Position(), n.Case))
 10456  	}
 10457  }
 10458  
 10459  func (p *project) postfixExpressionLValuePSelect(f *function, n *cc.PostfixExpression, t cc.Type, mode exprMode, flags flags) {
 10460  	// PostfixExpression "->" IDENTIFIER
 10461  	pe := n.PostfixExpression
 10462  	switch k := p.opKind(f, n.PostfixExpression, n.PostfixExpression.Operand.Type().Elem()); k {
 10463  	case opStruct:
 10464  		if !p.inUnion(n, pe.Operand.Type().Elem(), n.Token2.Value) {
 10465  			p.postfixExpressionLValuePSelectStruct(f, n, t, mode, flags)
 10466  			break
 10467  		}
 10468  
 10469  		p.w("*(*%s)(unsafe.Pointer(", p.typ(n, n.Operand.Type()))
 10470  		p.postfixExpression(f, pe, pe.Operand.Type(), exprValue, flags)
 10471  		p.fldOff(pe.Operand.Type().Elem(), n.Token2)
 10472  		p.w("))")
 10473  	case opUnion:
 10474  		p.postfixExpressionLValuePSelectUnion(f, n, t, mode, flags)
 10475  	default:
 10476  		panic(todo("", n.Position(), k))
 10477  	}
 10478  }
 10479  
 10480  func (p *project) postfixExpressionLValuePSelectUnion(f *function, n *cc.PostfixExpression, t cc.Type, mode exprMode, flags flags) {
 10481  	// PostfixExpression "->" IDENTIFIER
 10482  	fld := n.Field
 10483  	if fld.Offset() != 0 {
 10484  		p.err(&n.Token2, "internal error, union field with non-zero offset: %s %v", n.Token2.Value, fld.Offset())
 10485  	}
 10486  	switch {
 10487  	case n.Operand.Type().IsBitFieldType():
 10488  		panic(todo("", p.pos(n)))
 10489  	default:
 10490  		if fld.IsBitField() {
 10491  			p.err(&n.Token2, "internal error, wrong function for accessing a bit field: %s", n.Token2.Value)
 10492  		}
 10493  		pe := n.PostfixExpression.Operand.Type()
 10494  		defer p.w("%s", p.convert(n, n.Operand, t, flags))
 10495  		p.w("(*(*%s)(unsafe.Pointer(", p.typ(n, n.Operand.Type()))
 10496  		p.postfixExpression(f, n.PostfixExpression, pe, exprValue, flags)
 10497  		p.w("/* .%s */", p.fieldName(n, n.Token2.Value))
 10498  		p.w(")))")
 10499  	}
 10500  }
 10501  
 10502  func (p *project) postfixExpressionLValuePSelectStruct(f *function, n *cc.PostfixExpression, t cc.Type, mode exprMode, flags flags) {
 10503  	// PostfixExpression "->" IDENTIFIER
 10504  	fld := n.Field
 10505  	pe := n.PostfixExpression.Operand.Type()
 10506  	k := p.opKind(f, n.PostfixExpression, n.PostfixExpression.Operand.Type())
 10507  	switch {
 10508  	case n.Operand.Type().IsBitFieldType():
 10509  		panic(todo("", p.pos(n)))
 10510  	case k == opArray:
 10511  		defer p.w("%s", p.convert(n, n.Operand, t, flags))
 10512  		p.postfixExpression(f, n.PostfixExpression, pe, exprValue, flags)
 10513  		p.w("[0].%s", p.fieldName(n, n.Token2.Value))
 10514  	default:
 10515  		if fld.IsBitField() {
 10516  			p.err(&n.Token2, "internal error, wrong function for accessing a bit field: %s", n.Token2.Value)
 10517  		}
 10518  		defer p.w("%s", p.convert(n, n.Operand, t, flags))
 10519  		p.w("(*%s)(unsafe.Pointer(", p.typ(n, pe.Elem()))
 10520  		p.postfixExpression(f, n.PostfixExpression, pe, exprValue, flags)
 10521  		p.w(")).%s", p.fieldName(n, n.Token2.Value))
 10522  	}
 10523  }
 10524  
 10525  func (p *project) postfixExpressionLValueIndex(f *function, n *cc.PostfixExpression, t cc.Type, mode exprMode, flags flags) {
 10526  	// PostfixExpression '[' Expression ']'
 10527  	switch k := p.opKind(f, n.PostfixExpression, n.PostfixExpression.Operand.Type()); k {
 10528  	case opArray:
 10529  		p.postfixExpressionLValueIndexArray(f, n, t, mode, flags)
 10530  	case opNormal:
 10531  		p.postfixExpressionLValueIndexNormal(f, n, t, mode, flags)
 10532  	case opArrayParameter:
 10533  		p.postfixExpressionLValueIndexArrayParameter(f, n, t, mode, flags)
 10534  	default:
 10535  		panic(todo("", n.Position(), k))
 10536  	}
 10537  }
 10538  
 10539  func (p *project) postfixExpressionLValueIndexArrayParameter(f *function, n *cc.PostfixExpression, t cc.Type, mode exprMode, flags flags) {
 10540  	// PostfixExpression '[' Expression ']'
 10541  	defer p.w("%s", p.convert(n, n.Operand, t, flags))
 10542  	pe := n.PostfixExpression.Operand.Type()
 10543  	p.w("*(*%s)(unsafe.Pointer(", p.typ(n, pe.Elem()))
 10544  	p.postfixExpression(f, n.PostfixExpression, pe, exprValue, flags)
 10545  	if !n.Expression.Operand.IsZero() {
 10546  		p.nzUintptr(n, func() { p.expression(f, n.Expression, n.Expression.Operand.Type(), exprValue, flags) }, n.Expression.Operand)
 10547  		if sz := pe.Elem().Size(); sz != 1 {
 10548  			p.w("*%d", sz)
 10549  		}
 10550  	}
 10551  	p.w("))")
 10552  }
 10553  
 10554  func (p *project) postfixExpressionLValueIndexNormal(f *function, n *cc.PostfixExpression, t cc.Type, mode exprMode, flags flags) {
 10555  	// PostfixExpression '[' Expression ']'
 10556  	switch {
 10557  	case n.Operand.Type().Kind() == cc.Array:
 10558  		panic(todo("", p.pos(n)))
 10559  	default:
 10560  		switch pe := n.PostfixExpression.Operand.Type(); pe.Kind() {
 10561  		case cc.Ptr:
 10562  			defer p.w("%s", p.convert(n, n.Operand, t, flags))
 10563  			p.w("*(*%s)(unsafe.Pointer(", p.typ(n, pe.Elem()))
 10564  			p.postfixExpression(f, n.PostfixExpression, pe, exprValue, flags)
 10565  			if !n.Expression.Operand.IsZero() {
 10566  				p.nzUintptr(n, func() { p.expression(f, n.Expression, n.Expression.Operand.Type(), exprValue, flags) }, n.Expression.Operand)
 10567  				if sz := pe.Elem().Size(); sz != 1 {
 10568  					p.w("*%d", sz)
 10569  				}
 10570  			}
 10571  			p.w("))")
 10572  		case cc.Array:
 10573  			defer p.w("%s", p.convert(n, n.Operand, t, flags))
 10574  			p.w("*(*%s)(unsafe.Pointer(", p.typ(n, pe.Elem()))
 10575  			p.postfixExpression(f, n.PostfixExpression, pe, exprDecay, flags)
 10576  			if !n.Expression.Operand.IsZero() {
 10577  				p.nzUintptr(n, func() { p.expression(f, n.Expression, n.Expression.Operand.Type(), exprValue, flags) }, n.Expression.Operand)
 10578  				if sz := pe.Elem().Size(); sz != 1 {
 10579  					p.w("*%d", sz)
 10580  				}
 10581  			}
 10582  			p.w("))")
 10583  		default:
 10584  			panic(todo("", p.pos(n), pe))
 10585  		}
 10586  	}
 10587  }
 10588  
 10589  func (p *project) postfixExpressionLValueIndexArray(f *function, n *cc.PostfixExpression, t cc.Type, mode exprMode, flags flags) {
 10590  	// PostfixExpression '[' Expression ']'
 10591  	pe := n.PostfixExpression.Operand.Type()
 10592  	p.postfixExpression(f, n.PostfixExpression, pe, mode, flags)
 10593  	p.w("[")
 10594  	p.expression(f, n.Expression, n.Expression.Operand.Type(), exprValue, flags)
 10595  	p.w("]")
 10596  }
 10597  
 10598  func (p *project) postfixExpressionLValueSelect(f *function, n *cc.PostfixExpression, t cc.Type, mode exprMode, flags flags) {
 10599  	// PostfixExpression '.' IDENTIFIER
 10600  	pe := n.PostfixExpression
 10601  	switch k := p.opKind(f, pe, pe.Operand.Type()); k {
 10602  	case opStruct:
 10603  		if !p.inUnion(n, pe.Operand.Type(), n.Token2.Value) {
 10604  			p.postfixExpressionLValueSelectStruct(f, n, t, mode, flags)
 10605  			break
 10606  		}
 10607  
 10608  		p.w("*(*%s)(unsafe.Pointer(", p.typ(n, n.Operand.Type()))
 10609  		p.postfixExpression(f, pe, pe.Operand.Type(), exprAddrOf, flags)
 10610  		p.fldOff(pe.Operand.Type(), n.Token2)
 10611  		p.w("))")
 10612  	case opUnion:
 10613  		p.postfixExpressionLValueSelectUnion(f, n, t, mode, flags)
 10614  	default:
 10615  		panic(todo("", n.Position(), k))
 10616  	}
 10617  }
 10618  
 10619  func (p *project) inUnion(n cc.Node, t cc.Type, fname cc.StringID) bool {
 10620  	f, ok := t.FieldByName(fname)
 10621  	if !ok {
 10622  		p.err(n, "unknown field: %s", fname)
 10623  		return false
 10624  	}
 10625  
 10626  	return f.InUnion()
 10627  }
 10628  
 10629  func (p *project) postfixExpressionLValueSelectUnion(f *function, n *cc.PostfixExpression, t cc.Type, mode exprMode, flags flags) {
 10630  	fld := n.Field
 10631  	pe := n.PostfixExpression.Operand.Type()
 10632  	switch {
 10633  	case pe.Kind() == cc.Array:
 10634  		panic(todo("", p.pos(n)))
 10635  	case n.Operand.Type().IsBitFieldType():
 10636  		panic(todo("", p.pos(n)))
 10637  	default:
 10638  		if fld.IsBitField() {
 10639  			p.err(&n.Token2, "internal error, wrong function for accessing a bit field: %s", n.Token2.Value)
 10640  		}
 10641  		p.w("*(*%s)(unsafe.Pointer(", p.typ(n, n.Operand.Type()))
 10642  		p.postfixExpression(f, n.PostfixExpression, pe, exprAddrOf, flags)
 10643  		nonZeroUintptr(fld.Offset())
 10644  		p.w("))")
 10645  	}
 10646  }
 10647  
 10648  func (p *project) postfixExpressionLValueSelectStruct(f *function, n *cc.PostfixExpression, t cc.Type, mode exprMode, flags flags) {
 10649  	// PostfixExpression '.' IDENTIFIER
 10650  	fld := n.Field
 10651  	switch {
 10652  	case n.Operand.Type().IsBitFieldType():
 10653  		panic(todo("", p.pos(n)))
 10654  	default:
 10655  		if fld.IsBitField() {
 10656  			p.err(&n.Token2, "internal error, wrong function for accessing a bit field: %s", n.Token2.Value)
 10657  		}
 10658  		pe := n.PostfixExpression.Operand.Type()
 10659  		p.postfixExpression(f, n.PostfixExpression, pe, exprSelect, flags)
 10660  		p.w(".%s", p.fieldName(n, n.Token2.Value))
 10661  	}
 10662  }
 10663  
 10664  func (p *project) postfixExpressionIncDec(f *function, n *cc.PostfixExpression, oper, oper2 string, t cc.Type, mode exprMode, flags flags) {
 10665  	switch mode {
 10666  	case exprVoid:
 10667  		p.postfixExpressionIncDecVoid(f, n, oper, oper2, t, mode, flags)
 10668  	case exprLValue:
 10669  		p.postfixExpressionIncDecLValue(f, n, oper, oper2, t, mode, flags)
 10670  	case exprValue:
 10671  		p.postfixExpressionIncDecValue(f, n, oper, oper2, t, mode, flags)
 10672  	default:
 10673  		panic(todo("", mode))
 10674  	}
 10675  }
 10676  
 10677  func (p *project) postfixExpressionIncDecValue(f *function, n *cc.PostfixExpression, oper, oper2 string, t cc.Type, mode exprMode, flags flags) {
 10678  	// PostfixExpression "++"
 10679  	pe := n.PostfixExpression.Operand.Type()
 10680  	switch k := p.opKind(f, n.PostfixExpression, pe); k {
 10681  	case opNormal:
 10682  		p.postfixExpressionIncDecValueNormal(f, n, oper, oper2, t, mode, flags)
 10683  	case opBitfield:
 10684  		p.postfixExpressionIncDecValueBitfield(f, n, oper, oper2, t, mode, flags)
 10685  	case opArrayParameter:
 10686  		p.postfixExpressionIncDecValueArrayParameter(f, n, oper, oper2, t, mode, flags)
 10687  	default:
 10688  		panic(todo("", n.Position(), pe, pe.Kind(), k))
 10689  	}
 10690  }
 10691  
 10692  func (p *project) postfixExpressionIncDecValueArrayParameter(f *function, n *cc.PostfixExpression, oper, oper2 string, t cc.Type, mode exprMode, flags flags) {
 10693  	// PostfixExpression "++"
 10694  	pe := n.PostfixExpression.Operand.Type()
 10695  	defer p.w("%s", p.convert(n, n.PostfixExpression.Operand, t, flags))
 10696  	x := "Dec"
 10697  	if oper == "++" {
 10698  		x = "Inc"
 10699  	}
 10700  	p.w("%sPost%s%s(&", p.task.crt, x, p.helperType(n, pe.Decay()))
 10701  	p.postfixExpression(f, n.PostfixExpression, pe, exprLValue, flags)
 10702  	p.w(", %d)", p.incDelta(n.PostfixExpression, pe))
 10703  }
 10704  
 10705  func (p *project) postfixExpressionIncDecValueBitfield(f *function, n *cc.PostfixExpression, oper, oper2 string, t cc.Type, mode exprMode, flags flags) {
 10706  	// PostfixExpression "++"
 10707  	pe := n.PostfixExpression.Operand.Type()
 10708  	defer p.w("%s", p.convert(n, n.PostfixExpression.Operand, t, flags))
 10709  	x := "Dec"
 10710  	if oper == "++" {
 10711  		x = "Inc"
 10712  	}
 10713  	bf := pe.BitField()
 10714  	p.w("%sPost%sBitFieldPtr%d%s(", p.task.crt, x, bf.BitFieldBlockWidth(), p.bfHelperType(pe))
 10715  	p.postfixExpression(f, n.PostfixExpression, pe, exprAddrOf, flags)
 10716  	p.w(", %d, %d, %d, %#x)", p.incDelta(n.PostfixExpression, pe), bf.BitFieldBlockWidth(), bf.BitFieldOffset(), bf.Mask())
 10717  }
 10718  
 10719  func (p *project) postfixExpressionIncDecValueNormal(f *function, n *cc.PostfixExpression, oper, oper2 string, t cc.Type, mode exprMode, flags flags) {
 10720  	// PostfixExpression "++"
 10721  	pe := n.PostfixExpression.Operand.Type()
 10722  	defer p.w("%s", p.convert(n, n.PostfixExpression.Operand, t, flags))
 10723  	x := "Dec"
 10724  	if oper == "++" {
 10725  		x = "Inc"
 10726  	}
 10727  	if d := n.PostfixExpression.Declarator(); d != nil && p.isVolatileOrAtomic(d) {
 10728  		p.w("%sPost%sAtomic%s(&", p.task.crt, x, p.helperType(n, pe))
 10729  		var local *local
 10730  		var tld *tld
 10731  		if f != nil {
 10732  			local = f.locals[d]
 10733  		}
 10734  		if local == nil {
 10735  			tld = p.tlds[d]
 10736  		}
 10737  		switch {
 10738  		case local != nil:
 10739  			p.w("%s", local.name)
 10740  		case tld != nil:
 10741  			p.w("%s", tld.name)
 10742  		default:
 10743  			panic(todo(""))
 10744  		}
 10745  		p.w(", %d)", p.incDelta(n.PostfixExpression, pe))
 10746  		return
 10747  	}
 10748  
 10749  	p.w("%sPost%s%s(&", p.task.crt, x, p.helperType(n, pe))
 10750  	p.postfixExpression(f, n.PostfixExpression, pe, exprLValue, flags)
 10751  	p.w(", %d)", p.incDelta(n.PostfixExpression, pe))
 10752  }
 10753  
 10754  func (p *project) postfixExpressionIncDecLValue(f *function, n *cc.PostfixExpression, oper, oper2 string, t cc.Type, mode exprMode, flags flags) {
 10755  	switch k := p.opKind(f, n, n.Operand.Type()); k {
 10756  	case opNormal:
 10757  		p.postfixExpressionIncDecLValueNormal(f, n, oper, oper2, t, mode, flags)
 10758  	default:
 10759  		panic(todo("", n.Position(), k))
 10760  	}
 10761  }
 10762  
 10763  func (p *project) postfixExpressionIncDecLValueNormal(f *function, n *cc.PostfixExpression, oper, oper2 string, t cc.Type, mode exprMode, flags flags) {
 10764  	pe := n.PostfixExpression.Operand.Type()
 10765  	defer p.w("%s", p.convert(n, n.PostfixExpression.Operand, t, flags))
 10766  	x := "Dec"
 10767  	if oper == "++" {
 10768  		x = "Inc"
 10769  	}
 10770  	p.w("%sPost%s%s(&", p.task.crt, x, p.helperType(n, pe))
 10771  	p.postfixExpression(f, n.PostfixExpression, pe, exprLValue, flags)
 10772  	p.w(", %d)", p.incDelta(n.PostfixExpression, pe))
 10773  }
 10774  
 10775  func (p *project) postfixExpressionIncDecVoid(f *function, n *cc.PostfixExpression, oper, oper2 string, t cc.Type, mode exprMode, flags flags) {
 10776  	switch k := p.opKind(f, n, n.Operand.Type()); k {
 10777  	case opNormal:
 10778  		p.postfixExpressionIncDecVoidNormal(f, n, oper, oper2, t, mode, flags)
 10779  	case opBitfield:
 10780  		p.postfixExpressionIncDec(f, n, oper, oper2, t, exprValue, flags)
 10781  	default:
 10782  		panic(todo("", n.Position(), k))
 10783  	}
 10784  }
 10785  
 10786  func (p *project) postfixExpressionIncDecVoidNormal(f *function, n *cc.PostfixExpression, oper, oper2 string, t cc.Type, mode exprMode, flags flags) {
 10787  	if d := n.PostfixExpression.Declarator(); d != nil && p.isVolatileOrAtomic(d) {
 10788  		switch d.Type().Size() {
 10789  		case 4, 8:
 10790  			if !d.Type().IsIntegerType() {
 10791  				p.err(n, "unsupported volatile declarator type: %v", d.Type())
 10792  				return
 10793  			}
 10794  
 10795  			if f != nil {
 10796  				if local := f.locals[d]; local != nil {
 10797  					if local.isPinned {
 10798  						panic(todo(""))
 10799  					}
 10800  
 10801  					p.w("atomic.Add%s(&%s, ", p.helperType(n, d.Type()), local.name)
 10802  					switch oper {
 10803  					case "++":
 10804  						// ok
 10805  					case "--":
 10806  						p.w("-")
 10807  					default:
 10808  						p.err(n, "unsupported volatile declarator operation: %v", oper)
 10809  					}
 10810  					p.w("%d)", p.incDelta(n, d.Type()))
 10811  					return
 10812  				}
 10813  			}
 10814  
 10815  			if tld := p.tlds[d]; tld != nil {
 10816  				p.w("atomic.Add%s(&%s, ", p.helperType(n, d.Type()), tld.name)
 10817  				switch oper {
 10818  				case "++":
 10819  					// ok
 10820  				case "--":
 10821  					p.w("-")
 10822  				default:
 10823  					p.err(n, "unsupported volatile declarator operation: %v", oper)
 10824  				}
 10825  				p.w("%d)", p.incDelta(n, d.Type()))
 10826  				return
 10827  			}
 10828  
 10829  			panic(todo("", n.Position(), d.Position()))
 10830  		default:
 10831  			p.err(n, "unsupported volatile declarator size: %v", d.Type().Size())
 10832  			return
 10833  		}
 10834  	}
 10835  
 10836  	pe := n.PostfixExpression.Operand.Type().Decay()
 10837  	p.postfixExpression(f, n.PostfixExpression, pe, exprLValue, flags)
 10838  	if pe.IsIntegerType() || pe.Kind() == cc.Ptr && p.incDelta(n, pe) == 1 {
 10839  		p.w("%s", oper)
 10840  		return
 10841  	}
 10842  
 10843  	switch pe.Kind() {
 10844  	case cc.Ptr, cc.Float, cc.Double:
 10845  		p.w("%s %d", oper2, p.incDelta(n, pe))
 10846  		return
 10847  	}
 10848  
 10849  	panic(todo("", n.Position(), pe, pe.Kind()))
 10850  }
 10851  
 10852  func (p *project) incDelta(n cc.Node, t cc.Type) uintptr {
 10853  	if t.IsArithmeticType() {
 10854  		return 1
 10855  	}
 10856  
 10857  	if t.Kind() == cc.Ptr || t.Kind() == cc.Array {
 10858  		return t.Elem().Size()
 10859  	}
 10860  
 10861  	panic(todo("", n.Position(), t.Kind()))
 10862  }
 10863  
 10864  func (p *project) bitFldOff(t cc.Type, tok cc.Token) {
 10865  	var off uintptr
 10866  	fld, ok := t.FieldByName(tok.Value)
 10867  	switch {
 10868  	case ok && !fld.IsBitField():
 10869  		panic(todo("%v: internal error: bitFdlOff must not be used with non bit fields", origin(2)))
 10870  	case !ok:
 10871  		p.err(&tok, "uknown field: %s", tok.Value)
 10872  	default:
 10873  		off = fld.BitFieldBlockFirst().Offset()
 10874  	}
 10875  	if off != 0 {
 10876  		p.w("+%d", off)
 10877  	}
 10878  	p.w("/* &.%s */", tok.Value)
 10879  }
 10880  
 10881  func (p *project) fldOff(t cc.Type, tok cc.Token) {
 10882  	if t.Kind() == cc.Ptr {
 10883  		t = t.Elem()
 10884  	}
 10885  	var off uintptr
 10886  	fld, ok := t.FieldByName(tok.Value)
 10887  	switch {
 10888  	case ok && fld.IsBitField():
 10889  		panic(todo("%v: internal error: fdlOff must not be used with bit fields", origin(2)))
 10890  	case !ok:
 10891  		p.err(&tok, "uknown field: %s", tok.Value)
 10892  	default:
 10893  		off = fld.Offset()
 10894  	}
 10895  	if off != 0 {
 10896  		p.w("+%d", off)
 10897  	}
 10898  	p.w("/* &.%s */", tok.Value)
 10899  }
 10900  
 10901  func (p *project) postfixExpressionCall(f *function, n *cc.PostfixExpression, t cc.Type, mode exprMode, flags flags) {
 10902  	// PostfixExpression '(' ArgumentExpressionList ')'
 10903  	switch mode {
 10904  	case exprVoid:
 10905  		p.postfixExpressionCallVoid(f, n, t, mode, flags)
 10906  	case exprValue:
 10907  		p.postfixExpressionCallValue(f, n, t, mode, flags)
 10908  	case exprBool:
 10909  		p.postfixExpressionCallBool(f, n, t, mode, flags)
 10910  	default:
 10911  		panic(todo("", mode))
 10912  	}
 10913  }
 10914  
 10915  func (p *project) postfixExpressionCallBool(f *function, n *cc.PostfixExpression, t cc.Type, mode exprMode, flags flags) {
 10916  	// PostfixExpression '(' ArgumentExpressionList ')'
 10917  	p.w("(")
 10918  	defer p.w(")")
 10919  	defer p.w(" != 0")
 10920  	if d := n.PostfixExpression.Declarator(); d != nil {
 10921  		switch d.Name() {
 10922  		case idVaArg:
 10923  			if !f.vaType.IsScalarType() {
 10924  				panic(todo("", f.vaType))
 10925  			}
 10926  
 10927  			lhs := n.ArgumentExpressionList.AssignmentExpression
 10928  			p.w("%sVa%s(&", p.task.crt, p.helperType(n, f.vaType))
 10929  			p.assignmentExpression(f, lhs, lhs.Operand.Type(), exprLValue, flags)
 10930  			p.w(")")
 10931  			return
 10932  		case idAtomicLoadN:
 10933  			p.atomicLoadN(f, n, t, mode, flags)
 10934  			return
 10935  		case idBuiltinConstantPImpl:
 10936  			p.w("%v", n.Operand.Value())
 10937  			return
 10938  		}
 10939  	}
 10940  
 10941  	var va uintptr
 10942  	if f != nil {
 10943  		va = f.vaLists[n]
 10944  	}
 10945  	p.postfixExpression(f, n.PostfixExpression, n.PostfixExpression.Operand.Type(), exprFunc, flags)
 10946  	p.argumentExpressionList(f, n.PostfixExpression, n.ArgumentExpressionList, va)
 10947  }
 10948  
 10949  func (p *project) postfixExpressionCallValue(f *function, n *cc.PostfixExpression, t cc.Type, mode exprMode, flags flags) {
 10950  	// PostfixExpression '(' ArgumentExpressionList ')'
 10951  	defer p.w("%s", p.convert(n, n.Operand, t, flags))
 10952  	if d := n.PostfixExpression.Declarator(); d != nil {
 10953  		switch d.Name() {
 10954  		case idVaEnd:
 10955  			p.w("_ = ")
 10956  			arg := n.ArgumentExpressionList.AssignmentExpression
 10957  			p.assignmentExpression(f, arg, arg.Operand.Type(), exprValue, flags)
 10958  			return
 10959  		case idVaStart:
 10960  			lhs := n.ArgumentExpressionList.AssignmentExpression
 10961  			p.assignmentExpression(f, lhs, lhs.Operand.Type(), exprLValue, flags)
 10962  			p.w(" = %s", f.vaName)
 10963  			return
 10964  		case idVaArg:
 10965  			if !f.vaType.IsScalarType() {
 10966  				panic(todo("", f.vaType))
 10967  			}
 10968  
 10969  			lhs := n.ArgumentExpressionList.AssignmentExpression
 10970  			p.w("%sVa%s(&", p.task.crt, p.helperType(n, f.vaType))
 10971  			p.assignmentExpression(f, lhs, lhs.Operand.Type(), exprLValue, flags)
 10972  			p.w(")")
 10973  			return
 10974  		case idAtomicLoadN:
 10975  			p.atomicLoadN(f, n, t, mode, flags)
 10976  			return
 10977  		case idAddOverflow:
 10978  			p.addOverflow(f, n, t, mode, flags)
 10979  			return
 10980  		case idSubOverflow:
 10981  			p.subOverflow(f, n, t, mode, flags)
 10982  			return
 10983  		case idMulOverflow:
 10984  			p.mulOverflow(f, n, t, mode, flags)
 10985  			return
 10986  		case idBuiltinConstantPImpl:
 10987  			p.w("%v", n.Operand.Value())
 10988  			return
 10989  		}
 10990  	}
 10991  	var va uintptr
 10992  	if f != nil {
 10993  		va = f.vaLists[n]
 10994  	}
 10995  	p.postfixExpression(f, n.PostfixExpression, n.PostfixExpression.Operand.Type(), exprFunc, flags)
 10996  	p.argumentExpressionList(f, n.PostfixExpression, n.ArgumentExpressionList, va)
 10997  }
 10998  
 10999  // bool __builtin_mul_overflow (type1 a, type2 b, type3 *res)
 11000  func (p *project) mulOverflow(f *function, n *cc.PostfixExpression, t cc.Type, mode exprMode, flags flags) {
 11001  	args := p.argList(n.ArgumentExpressionList)
 11002  	if len(args) != 3 {
 11003  		p.err(n, "expected 3 arguments in call to __builtin_mul_overflow")
 11004  		return
 11005  	}
 11006  
 11007  	pt := args[2].Operand.Type()
 11008  	if pt.Kind() != cc.Ptr {
 11009  		p.err(n, "invalid argument of __builtin_mul_overflow (expected pointer): %s", pt)
 11010  		return
 11011  	}
 11012  
 11013  	vt := pt.Elem()
 11014  	switch {
 11015  	case vt.IsIntegerType():
 11016  		switch vt.Size() {
 11017  		case 1, 2, 4, 8, 16:
 11018  			p.w("%sX__builtin_mul_overflow%s", p.task.crt, p.helperType(n, vt))
 11019  		default:
 11020  			p.err(n, "invalid argument of __builtin_mul_overflow: %v, elem kind %v", pt, vt.Kind())
 11021  			return
 11022  		}
 11023  		p.w("(%s", f.tlsName)
 11024  		types := []cc.Type{vt, vt, pt}
 11025  		for i, v := range args[:3] {
 11026  			p.w(", ")
 11027  			p.assignmentExpression(f, v, types[i], exprValue, flags)
 11028  		}
 11029  		p.w(")")
 11030  		return
 11031  	}
 11032  
 11033  	p.err(n, "invalid arguments of __builtin_mul_overflow: (%v, %v, %v)", args[0].Operand.Type(), args[1].Operand.Type(), args[2].Operand.Type())
 11034  }
 11035  
 11036  // bool __builtin_sub_overflow (type1 a, type2 b, type3 *res)
 11037  func (p *project) subOverflow(f *function, n *cc.PostfixExpression, t cc.Type, mode exprMode, flags flags) {
 11038  	args := p.argList(n.ArgumentExpressionList)
 11039  	if len(args) != 3 {
 11040  		p.err(n, "expected 3 arguments in call to __builtin_sub_overflow")
 11041  		return
 11042  	}
 11043  
 11044  	pt := args[2].Operand.Type()
 11045  	if pt.Kind() != cc.Ptr {
 11046  		p.err(n, "invalid argument of __builtin_sub_overflow (expected pointer): %s", pt)
 11047  		return
 11048  	}
 11049  
 11050  	vt := pt.Elem()
 11051  	switch {
 11052  	case vt.IsIntegerType():
 11053  		switch vt.Size() {
 11054  		case 1, 2, 4, 8:
 11055  			p.w("%sX__builtin_sub_overflow%s", p.task.crt, p.helperType(n, vt))
 11056  		default:
 11057  			p.err(n, "invalid argument of __builtin_sub_overflow: %v, elem kind %v", pt, vt.Kind())
 11058  			return
 11059  		}
 11060  		p.w("(%s", f.tlsName)
 11061  		types := []cc.Type{vt, vt, pt}
 11062  		for i, v := range args[:3] {
 11063  			p.w(", ")
 11064  			p.assignmentExpression(f, v, types[i], exprValue, flags)
 11065  		}
 11066  		p.w(")")
 11067  		return
 11068  	}
 11069  
 11070  	p.err(n, "invalid arguments of __builtin_sub_overflow: (%v, %v, %v)", args[0].Operand.Type(), args[1].Operand.Type(), args[2].Operand.Type())
 11071  }
 11072  
 11073  // bool __builtin_add_overflow (type1 a, type2 b, type3 *res)
 11074  func (p *project) addOverflow(f *function, n *cc.PostfixExpression, t cc.Type, mode exprMode, flags flags) {
 11075  	args := p.argList(n.ArgumentExpressionList)
 11076  	if len(args) != 3 {
 11077  		p.err(n, "expected 3 arguments in call to __builtin_add_overflow")
 11078  		return
 11079  	}
 11080  
 11081  	pt := args[2].Operand.Type()
 11082  	if pt.Kind() != cc.Ptr {
 11083  		p.err(n, "invalid argument of __builtin_add_overflow (expected pointer): %s", pt)
 11084  		return
 11085  	}
 11086  
 11087  	vt := pt.Elem()
 11088  	switch {
 11089  	case vt.IsIntegerType():
 11090  		switch vt.Size() {
 11091  		case 1, 2, 4, 8:
 11092  			p.w("%sX__builtin_add_overflow%s", p.task.crt, p.helperType(n, vt))
 11093  		default:
 11094  			p.err(n, "invalid argument of __builtin_add_overflow: %v, elem kind %v", pt, vt.Kind())
 11095  			return
 11096  		}
 11097  		p.w("(%s", f.tlsName)
 11098  		types := []cc.Type{vt, vt, pt}
 11099  		for i, v := range args[:3] {
 11100  			p.w(", ")
 11101  			p.assignmentExpression(f, v, types[i], exprValue, flags)
 11102  		}
 11103  		p.w(")")
 11104  		return
 11105  	}
 11106  
 11107  	p.err(n, "invalid arguments of __builtin_add_overflow: (%v, %v, %v)", args[0].Operand.Type(), args[1].Operand.Type(), args[2].Operand.Type())
 11108  }
 11109  
 11110  // type __atomic_load_n (type *ptr, int memorder)
 11111  func (p *project) atomicLoadN(f *function, n *cc.PostfixExpression, t cc.Type, mode exprMode, flags flags) {
 11112  	args := p.argList(n.ArgumentExpressionList)
 11113  	if len(args) != 2 {
 11114  		p.err(n, "expected 2 arguments in call to __atomic_load_n")
 11115  		return
 11116  	}
 11117  
 11118  	pt := args[0].Operand.Type()
 11119  	if pt.Kind() != cc.Ptr {
 11120  		p.err(n, "invalid argument of __atomic_load_n (expected pointer): %s", pt)
 11121  		return
 11122  	}
 11123  
 11124  	vt := pt.Elem()
 11125  	switch {
 11126  	case vt.IsIntegerType():
 11127  		var s, sb string
 11128  		switch {
 11129  		case vt.IsSignedType():
 11130  			s = "Int"
 11131  			sb = "int8"
 11132  		default:
 11133  			s = "Uint"
 11134  			sb = "byte"
 11135  		}
 11136  		switch vt.Size() {
 11137  		case 1:
 11138  			switch {
 11139  			case p.task.ignoreUnsupportedAligment:
 11140  				p.w("(*(*%s)(unsafe.Pointer(", sb)
 11141  				p.assignmentExpression(f, args[0], pt, exprValue, flags)
 11142  				p.w(")))")
 11143  			default:
 11144  				p.err(n, "invalid argument of __atomic_load_n: %v, elem kind %v", pt, vt.Kind())
 11145  			}
 11146  			return
 11147  		case 2, 4, 8:
 11148  			p.w("%sAtomicLoadN%s%d", p.task.crt, s, 8*vt.Size())
 11149  		default:
 11150  			p.err(n, "invalid argument of __atomic_load_n: %v, elem kind %v", pt, vt.Kind())
 11151  			return
 11152  		}
 11153  		types := []cc.Type{pt, p.intType}
 11154  		p.w("(")
 11155  		for i, v := range args[:2] {
 11156  			if i != 0 {
 11157  				p.w(", ")
 11158  			}
 11159  			p.assignmentExpression(f, v, types[i], exprValue, flags)
 11160  		}
 11161  		p.w(")")
 11162  		return
 11163  	case vt.Kind() == cc.Ptr:
 11164  		panic(todo("", pt, vt))
 11165  	}
 11166  
 11167  	p.err(n, "invalid first argument of __atomic_load_n: %v, elem kind %v", pt, vt.Kind())
 11168  }
 11169  
 11170  func (p *project) postfixExpressionCallVoid(f *function, n *cc.PostfixExpression, t cc.Type, mode exprMode, flags flags) {
 11171  	// PostfixExpression '(' ArgumentExpressionList ')'
 11172  	if d := n.PostfixExpression.Declarator(); d != nil {
 11173  		switch d.Name() {
 11174  		case idVaEnd:
 11175  			p.w("_ = ")
 11176  			arg := n.ArgumentExpressionList.AssignmentExpression
 11177  			p.assignmentExpression(f, arg, arg.Operand.Type(), exprValue, flags)
 11178  			return
 11179  		case idVaStart:
 11180  			lhs := n.ArgumentExpressionList.AssignmentExpression
 11181  			p.assignmentExpression(f, lhs, lhs.Operand.Type(), exprLValue, flags)
 11182  			p.w(" = %s", f.vaName)
 11183  			return
 11184  		case idVaArg:
 11185  			if !f.vaType.IsScalarType() {
 11186  				panic(todo("", f.vaType))
 11187  			}
 11188  
 11189  			lhs := n.ArgumentExpressionList.AssignmentExpression
 11190  			p.w("%sVa%s(&", p.task.crt, p.helperType(n, f.vaType))
 11191  			p.assignmentExpression(f, lhs, lhs.Operand.Type(), exprLValue, flags)
 11192  			p.w(")")
 11193  			return
 11194  		case idAtomicStoreN:
 11195  			p.atomicStoreN(f, n, t, mode, flags)
 11196  			return
 11197  		case idMulOverflow:
 11198  			p.mulOverflow(f, n, t, mode, flags)
 11199  			return
 11200  		}
 11201  	}
 11202  	var va uintptr
 11203  	if f != nil {
 11204  		va = f.vaLists[n]
 11205  	}
 11206  	p.postfixExpression(f, n.PostfixExpression, n.PostfixExpression.Operand.Type(), exprFunc, flags)
 11207  	p.argumentExpressionList(f, n.PostfixExpression, n.ArgumentExpressionList, va)
 11208  }
 11209  
 11210  // void __atomic_store_n (type *ptr, type val, int memorder)
 11211  func (p *project) atomicStoreN(f *function, n *cc.PostfixExpression, t cc.Type, mode exprMode, flags flags) {
 11212  	args := p.argList(n.ArgumentExpressionList)
 11213  	if len(args) != 3 {
 11214  		p.err(n, "expected 3 arguments in call to __atomic_store_n")
 11215  		return
 11216  	}
 11217  
 11218  	pt := args[0].Operand.Type()
 11219  	if pt.Kind() != cc.Ptr {
 11220  		p.err(n, "invalid first argument of __atomic_store_n (expected pointer): %s", pt)
 11221  		return
 11222  	}
 11223  
 11224  	vt := args[1].Operand.Type()
 11225  	switch {
 11226  	case vt.IsIntegerType():
 11227  		var s string
 11228  		switch {
 11229  		case vt.IsSignedType():
 11230  			s = "Int"
 11231  		default:
 11232  			s = "Uint"
 11233  		}
 11234  		switch vt.Size() {
 11235  		case 2, 4, 8:
 11236  			p.w("%sAtomicStoreN%s%d", p.task.crt, s, 8*vt.Size())
 11237  		default:
 11238  			p.err(n, "invalid arguments of __atomic_store_n: (%v, %v), element kind %v", pt, vt, vt.Kind())
 11239  			return
 11240  		}
 11241  		p.w("(")
 11242  		types := []cc.Type{pt, vt, p.intType}
 11243  		for i, v := range args[:3] {
 11244  			if i != 0 {
 11245  				p.w(", ")
 11246  			}
 11247  			if i == 1 {
 11248  				p.w("%s(", strings.ToLower(p.helperType(n, vt)))
 11249  			}
 11250  			p.assignmentExpression(f, v, types[i], exprValue, flags)
 11251  			if i == 1 {
 11252  				p.w(")")
 11253  			}
 11254  		}
 11255  		p.w(")")
 11256  		return
 11257  	case vt.Kind() == cc.Ptr:
 11258  		p.w("%sAtomicStoreNUintptr", p.task.crt)
 11259  		p.w("(")
 11260  		types := []cc.Type{pt, vt, p.intType}
 11261  		for i, v := range args[:3] {
 11262  			if i != 0 {
 11263  				p.w(", ")
 11264  			}
 11265  			if i == 1 {
 11266  				p.w("%s(", strings.ToLower(p.helperType(n, vt)))
 11267  			}
 11268  			p.assignmentExpression(f, v, types[i], exprValue, flags)
 11269  			if i == 1 {
 11270  				p.w(")")
 11271  			}
 11272  		}
 11273  		p.w(")")
 11274  		return
 11275  	}
 11276  
 11277  	p.err(n, "invalid arguments of __atomic_store_n: (%v, %v), element kind %v", pt, vt, vt.Kind())
 11278  }
 11279  
 11280  func (p *project) argList(n *cc.ArgumentExpressionList) (r []*cc.AssignmentExpression) {
 11281  	for ; n != nil; n = n.ArgumentExpressionList {
 11282  		r = append(r, n.AssignmentExpression)
 11283  	}
 11284  	return r
 11285  }
 11286  
 11287  func (p *project) argumentExpressionList(f *function, pe *cc.PostfixExpression, n *cc.ArgumentExpressionList, bpOff uintptr) {
 11288  	switch {
 11289  	case f == nil:
 11290  		p.w("(nil")
 11291  	default:
 11292  		p.w("(%s", f.tlsName)
 11293  	}
 11294  	ft := funcType(pe.Operand.Type())
 11295  	isVariadic := ft.IsVariadic()
 11296  	params := ft.Parameters()
 11297  	if len(params) == 1 && params[0].Type().Kind() == cc.Void {
 11298  		params = nil
 11299  	}
 11300  	var args []*cc.AssignmentExpression
 11301  	for ; n != nil; n = n.ArgumentExpressionList {
 11302  		args = append(args, n.AssignmentExpression)
 11303  	}
 11304  	if len(args) < len(params) {
 11305  		panic(todo("", p.pos(n)))
 11306  	}
 11307  
 11308  	va := true
 11309  	if len(args) > len(params) && !isVariadic {
 11310  		var a []string
 11311  		for _, v := range args {
 11312  			a = append(a, v.Operand.Type().String())
 11313  		}
 11314  		sargs := strings.Join(a, ",")
 11315  		switch d := pe.Declarator(); {
 11316  		case d == nil:
 11317  			p.err(pe, "too many arguments (%s) in call to %s", sargs, ft)
 11318  		default:
 11319  			p.err(pe, "too many arguments (%s) in call to %s of type %s", sargs, d.Name(), ft)
 11320  		}
 11321  		va = false
 11322  	}
 11323  
 11324  	paren := ""
 11325  	for i, arg := range args {
 11326  		p.w(",%s", tidyComment(" ", arg))
 11327  		mode := exprValue
 11328  		if at := arg.Operand.Type(); at.Kind() == cc.Array {
 11329  			mode = exprDecay
 11330  		}
 11331  		switch {
 11332  		case i < len(params):
 11333  			switch pt := params[i].Type(); {
 11334  			case isTransparentUnion(params[i].Type()):
 11335  				p.callArgTransparentUnion(f, arg, pt)
 11336  			default:
 11337  				p.assignmentExpression(f, arg, arg.Promote(), mode, 0)
 11338  			}
 11339  		case va && i == len(params):
 11340  			p.w("%sVaList(%s%s, ", p.task.crt, f.bpName, nonZeroUintptr(bpOff))
 11341  			paren = ")"
 11342  			fallthrough
 11343  		default:
 11344  			var flags flags
 11345  			if arg.Promote().IsIntegerType() {
 11346  				switch x := arg.Operand.Value().(type) {
 11347  				case cc.Int64Value:
 11348  					if x < mathutil.MinInt || x > mathutil.MaxInt {
 11349  						flags |= fForceConv
 11350  					}
 11351  				case cc.Uint64Value:
 11352  					if x > mathutil.MaxInt {
 11353  						flags |= fForceConv
 11354  					}
 11355  				}
 11356  			}
 11357  			p.assignmentExpression(f, arg, arg.Promote(), mode, flags)
 11358  		}
 11359  	}
 11360  	if isVariadic && len(args) == len(params) {
 11361  		p.w(", 0")
 11362  	}
 11363  	p.w("%s)", paren)
 11364  }
 11365  
 11366  // https://gcc.gnu.org/onlinedocs/gcc-3.3/gcc/Type-Attributes.html
 11367  //
 11368  // transparent_union
 11369  //
 11370  // This attribute, attached to a union type definition, indicates that any
 11371  // function parameter having that union type causes calls to that function to
 11372  // be treated in a special way.
 11373  //
 11374  // First, the argument corresponding to a transparent union type can be of any
 11375  // type in the union; no cast is required. Also, if the union contains a
 11376  // pointer type, the corresponding argument can be a null pointer constant or a
 11377  // void pointer expression; and if the union contains a void pointer type, the
 11378  // corresponding argument can be any pointer expression. If the union member
 11379  // type is a pointer, qualifiers like const on the referenced type must be
 11380  // respected, just as with normal pointer conversions.
 11381  //
 11382  // Second, the argument is passed to the function using the calling conventions
 11383  // of first member of the transparent union, not the calling conventions of the
 11384  // union itself. All members of the union must have the same machine
 11385  // representation; this is necessary for this argument passing to work
 11386  // properly.
 11387  //
 11388  // Transparent unions are designed for library functions that have multiple
 11389  // interfaces for compatibility reasons. For example, suppose the wait function
 11390  // must accept either a value of type int * to comply with Posix, or a value of
 11391  // type union wait * to comply with the 4.1BSD interface. If wait's parameter
 11392  // were void *, wait would accept both kinds of arguments, but it would also
 11393  // accept any other pointer type and this would make argument type checking
 11394  // less useful. Instead, <sys/wait.h> might define the interface as follows:
 11395  //
 11396  //	typedef union
 11397  //		{
 11398  //			int *__ip;
 11399  //			union wait *__up;
 11400  //		} wait_status_ptr_t __attribute__ ((__transparent_union__));
 11401  //
 11402  //	pid_t wait (wait_status_ptr_t);
 11403  //
 11404  // This interface allows either int * or union wait * arguments to be passed,
 11405  // using the int * calling convention. The program can call wait with arguments
 11406  // of either type:
 11407  //
 11408  //	int w1 () { int w; return wait (&w); }
 11409  //	int w2 () { union wait w; return wait (&w); }
 11410  //
 11411  // With this interface, wait's implementation might look like this:
 11412  //
 11413  //	pid_t wait (wait_status_ptr_t p)
 11414  //	{
 11415  //		return waitpid (-1, p.__ip, 0);
 11416  //	}
 11417  func (p *project) callArgTransparentUnion(f *function, n *cc.AssignmentExpression, pt cc.Type) {
 11418  	if pt.Kind() != cc.Union {
 11419  		panic(todo("internal error"))
 11420  	}
 11421  
 11422  	ot := n.Operand.Type()
 11423  	switch k := pt.UnionCommon(); k {
 11424  	case cc.Ptr:
 11425  		if ot.Kind() != k {
 11426  			panic(todo("", n.Position(), k, pt))
 11427  		}
 11428  
 11429  		p.assignmentExpression(f, n, ot, exprValue, 0)
 11430  	default:
 11431  		panic(todo("", n.Position(), k, pt))
 11432  	}
 11433  }
 11434  
 11435  func isTransparentUnion(t cc.Type) (r bool) {
 11436  	for _, v := range attrs(t) {
 11437  		cc.Inspect(v, func(n cc.Node, _ bool) bool {
 11438  			if x, ok := n.(*cc.AttributeValue); ok && x.Token.Value == idTransparentUnion {
 11439  				r = true
 11440  				return false
 11441  			}
 11442  
 11443  			return true
 11444  		})
 11445  	}
 11446  	return r
 11447  }
 11448  
 11449  func attrs(t cc.Type) []*cc.AttributeSpecifier {
 11450  	if a := t.Attributes(); len(a) != 0 {
 11451  		return a
 11452  	}
 11453  
 11454  	if t.IsAliasType() {
 11455  		if a := t.Alias().Attributes(); len(a) != 0 {
 11456  			return a
 11457  		}
 11458  
 11459  		return t.AliasDeclarator().Type().Attributes()
 11460  	}
 11461  
 11462  	return nil
 11463  }
 11464  
 11465  func (p *project) nzUintptr(n cc.Node, f func(), op cc.Operand) {
 11466  	if op.Type().IsIntegerType() {
 11467  		switch {
 11468  		case op.IsZero():
 11469  			return
 11470  		case op.Value() != nil:
 11471  			switch x := op.Value().(type) {
 11472  			case cc.Int64Value:
 11473  				if x > 0 && uint64(x) <= 1<<(8*p.ptrSize)-1 {
 11474  					p.w("+%d", x)
 11475  					return
 11476  				}
 11477  			case cc.Uint64Value:
 11478  				if uint64(x) <= 1<<(8*p.ptrSize)-1 {
 11479  					p.w("+%d", x)
 11480  					return
 11481  				}
 11482  			}
 11483  
 11484  			p.w(" +%sUintptrFrom%s(", p.task.crt, p.helperType(n, op.Type()))
 11485  		default:
 11486  			p.w(" +uintptr(")
 11487  		}
 11488  
 11489  		f()
 11490  		p.w(")")
 11491  		return
 11492  	}
 11493  
 11494  	panic(todo("", p.pos(n)))
 11495  }
 11496  
 11497  func (p *project) primaryExpression(f *function, n *cc.PrimaryExpression, t cc.Type, mode exprMode, flags flags) {
 11498  	switch mode {
 11499  	case exprLValue:
 11500  		p.primaryExpressionLValue(f, n, t, mode, flags)
 11501  	case exprValue:
 11502  		p.primaryExpressionValue(f, n, t, mode, flags)
 11503  	case exprFunc:
 11504  		p.primaryExpressionFunc(f, n, t, mode, flags)
 11505  	case exprAddrOf:
 11506  		p.primaryExpressionAddrOf(f, n, t, mode, flags)
 11507  	case exprSelect:
 11508  		p.primaryExpressionSelect(f, n, t, mode, flags)
 11509  	case exprPSelect:
 11510  		p.primaryExpressionPSelect(f, n, t, mode, flags)
 11511  	case exprBool:
 11512  		p.primaryExpressionBool(f, n, t, mode, flags)
 11513  	case exprVoid:
 11514  		p.primaryExpressionVoid(f, n, t, mode, flags)
 11515  	case exprDecay:
 11516  		p.primaryExpressionDecay(f, n, t, mode, flags)
 11517  	default:
 11518  		panic(todo("", n.Position(), mode))
 11519  	}
 11520  }
 11521  
 11522  func (p *project) primaryExpressionDecay(f *function, n *cc.PrimaryExpression, t cc.Type, mode exprMode, flags flags) {
 11523  	switch n.Case {
 11524  	case cc.PrimaryExpressionIdent: // IDENTIFIER
 11525  		switch d := n.Declarator(); {
 11526  		case d != nil:
 11527  			p.declarator(n, f, d, t, mode, flags)
 11528  		default:
 11529  			panic(todo("", p.pos(n)))
 11530  		}
 11531  	case cc.PrimaryExpressionInt: // INTCONST
 11532  		p.intConst(n, n.Token.Src.String(), n.Operand, t, flags)
 11533  	case cc.PrimaryExpressionFloat: // FLOATCONST
 11534  		panic(todo("", p.pos(n)))
 11535  	case cc.PrimaryExpressionEnum: // ENUMCONST
 11536  		panic(todo("", p.pos(n)))
 11537  	case cc.PrimaryExpressionChar: // CHARCONST
 11538  		panic(todo("", p.pos(n)))
 11539  	case cc.PrimaryExpressionLChar: // LONGCHARCONST
 11540  		panic(todo("", p.pos(n)))
 11541  	case cc.PrimaryExpressionString: // STRINGLITERAL
 11542  		p.w("%s", p.stringLiteral(n.Operand.Value()))
 11543  	case cc.PrimaryExpressionLString: // LONGSTRINGLITERAL
 11544  		p.w("%s", p.wideStringLiteral(n.Operand.Value(), 0))
 11545  	case cc.PrimaryExpressionExpr: // '(' Expression ')'
 11546  		p.expression(f, n.Expression, t, mode, flags)
 11547  	case cc.PrimaryExpressionStmt: // '(' CompoundStatement ')'
 11548  		p.err(n, "statement expressions not supported")
 11549  	default:
 11550  		panic(todo("%v: internal error: %v", n.Position(), n.Case))
 11551  	}
 11552  }
 11553  
 11554  func (p *project) primaryExpressionVoid(f *function, n *cc.PrimaryExpression, t cc.Type, mode exprMode, flags flags) {
 11555  
 11556  	switch n.Case {
 11557  	case cc.PrimaryExpressionIdent: // IDENTIFIER
 11558  		p.w("_ = ")
 11559  		p.primaryExpression(f, n, n.Operand.Type(), exprValue, flags)
 11560  	case cc.PrimaryExpressionInt, // INTCONST
 11561  		cc.PrimaryExpressionFloat,   // FLOATCONST
 11562  		cc.PrimaryExpressionEnum,    // ENUMCONST
 11563  		cc.PrimaryExpressionChar,    // CHARCONST
 11564  		cc.PrimaryExpressionLChar,   // LONGCHARCONST
 11565  		cc.PrimaryExpressionString,  // STRINGLITERAL
 11566  		cc.PrimaryExpressionLString: // LONGSTRINGLITERAL
 11567  
 11568  		// nop
 11569  	case cc.PrimaryExpressionExpr: // '(' Expression ')'
 11570  		p.expression(f, n.Expression, n.Expression.Operand.Type(), mode, flags)
 11571  	case cc.PrimaryExpressionStmt: // '(' CompoundStatement ')'
 11572  		p.compoundStatement(f, n.CompoundStatement, "", true, false, 0)
 11573  	default:
 11574  		panic(todo("%v: internal error: %v", n.Position(), n.Case))
 11575  	}
 11576  }
 11577  
 11578  func (p *project) primaryExpressionBool(f *function, n *cc.PrimaryExpression, t cc.Type, mode exprMode, flags flags) {
 11579  	if n.Case != cc.PrimaryExpressionExpr {
 11580  		p.w("(")
 11581  		defer p.w(")")
 11582  	}
 11583  
 11584  	if n.Case != cc.PrimaryExpressionExpr {
 11585  		defer p.w(" != 0")
 11586  	}
 11587  	switch n.Case {
 11588  	case cc.PrimaryExpressionIdent: // IDENTIFIER
 11589  		switch d := n.Declarator(); {
 11590  		case d != nil:
 11591  			p.declarator(n, f, d, d.Type(), exprValue, flags)
 11592  		default:
 11593  			panic(todo("", p.pos(n)))
 11594  		}
 11595  	case cc.PrimaryExpressionInt: // INTCONST
 11596  		p.intConst(n, n.Token.Src.String(), n.Operand, n.Operand.Type(), flags)
 11597  	case cc.PrimaryExpressionFloat: // FLOATCONST
 11598  		panic(todo("", p.pos(n)))
 11599  	case cc.PrimaryExpressionEnum: // ENUMCONST
 11600  		panic(todo("", p.pos(n)))
 11601  	case cc.PrimaryExpressionChar: // CHARCONST
 11602  		panic(todo("", p.pos(n)))
 11603  	case cc.PrimaryExpressionLChar: // LONGCHARCONST
 11604  		p.charConst(n, n.Token.Src.String(), n.Operand, t, flags)
 11605  	case cc.PrimaryExpressionString: // STRINGLITERAL
 11606  		p.w(" 1 ")
 11607  	case cc.PrimaryExpressionLString: // LONGSTRINGLITERAL
 11608  		panic(todo("", p.pos(n)))
 11609  	case cc.PrimaryExpressionExpr: // '(' Expression ')'
 11610  		p.w("(")
 11611  		defer p.w(")")
 11612  		p.expression(f, n.Expression, t, mode, flags)
 11613  	case cc.PrimaryExpressionStmt: // '(' CompoundStatement ')'
 11614  		p.w("func() %v {", p.typ(n, n.CompoundStatement.Operand.Type()))
 11615  		p.compoundStatement(f, n.CompoundStatement, "", true, false, exprValue)
 11616  		p.w("}()")
 11617  	default:
 11618  		panic(todo("%v: internal error: %v", n.Position(), n.Case))
 11619  	}
 11620  }
 11621  
 11622  func (p *project) primaryExpressionPSelect(f *function, n *cc.PrimaryExpression, t cc.Type, mode exprMode, flags flags) {
 11623  	switch n.Case {
 11624  	case cc.PrimaryExpressionIdent: // IDENTIFIER
 11625  		switch d := n.Declarator(); {
 11626  		case d != nil:
 11627  			switch k := p.declaratorKind(d); k {
 11628  			case opArray:
 11629  				panic(todo("", p.pos(n)))
 11630  				p.primaryExpression(f, n, t, exprDecay, flags)
 11631  			default:
 11632  				p.declarator(n, f, d, t, mode, flags)
 11633  			}
 11634  		default:
 11635  			panic(todo("", p.pos(n)))
 11636  		}
 11637  	case cc.PrimaryExpressionInt: // INTCONST
 11638  		panic(todo("", p.pos(n)))
 11639  	case cc.PrimaryExpressionFloat: // FLOATCONST
 11640  		panic(todo("", p.pos(n)))
 11641  	case cc.PrimaryExpressionEnum: // ENUMCONST
 11642  		panic(todo("", p.pos(n)))
 11643  	case cc.PrimaryExpressionChar: // CHARCONST
 11644  		panic(todo("", p.pos(n)))
 11645  	case cc.PrimaryExpressionLChar: // LONGCHARCONST
 11646  		panic(todo("", p.pos(n)))
 11647  	case cc.PrimaryExpressionString: // STRINGLITERAL
 11648  		panic(todo("", p.pos(n)))
 11649  	case cc.PrimaryExpressionLString: // LONGSTRINGLITERAL
 11650  		panic(todo("", p.pos(n)))
 11651  	case cc.PrimaryExpressionExpr: // '(' Expression ')'
 11652  		p.expression(f, n.Expression, t, mode, flags)
 11653  	case cc.PrimaryExpressionStmt: // '(' CompoundStatement ')'
 11654  		p.err(n, "statement expressions not supported")
 11655  	default:
 11656  		panic(todo("%v: internal error: %v", n.Position(), n.Case))
 11657  	}
 11658  }
 11659  
 11660  func (p *project) primaryExpressionSelect(f *function, n *cc.PrimaryExpression, t cc.Type, mode exprMode, flags flags) {
 11661  	switch n.Case {
 11662  	case cc.PrimaryExpressionIdent: // IDENTIFIER
 11663  		switch d := n.Declarator(); {
 11664  		case d != nil:
 11665  			p.declarator(n, f, d, t, mode, flags)
 11666  		default:
 11667  			panic(todo("", p.pos(n)))
 11668  		}
 11669  	case cc.PrimaryExpressionInt: // INTCONST
 11670  		panic(todo("", p.pos(n)))
 11671  	case cc.PrimaryExpressionFloat: // FLOATCONST
 11672  		panic(todo("", p.pos(n)))
 11673  	case cc.PrimaryExpressionEnum: // ENUMCONST
 11674  		panic(todo("", p.pos(n)))
 11675  	case cc.PrimaryExpressionChar: // CHARCONST
 11676  		panic(todo("", p.pos(n)))
 11677  	case cc.PrimaryExpressionLChar: // LONGCHARCONST
 11678  		panic(todo("", p.pos(n)))
 11679  	case cc.PrimaryExpressionString: // STRINGLITERAL
 11680  		panic(todo("", p.pos(n)))
 11681  	case cc.PrimaryExpressionLString: // LONGSTRINGLITERAL
 11682  		panic(todo("", p.pos(n)))
 11683  	case cc.PrimaryExpressionExpr: // '(' Expression ')'
 11684  		p.expression(f, n.Expression, t, mode, flags)
 11685  	case cc.PrimaryExpressionStmt: // '(' CompoundStatement ')'
 11686  		p.err(n, "statement expressions not supported")
 11687  	default:
 11688  		panic(todo("%v: internal error: %v", n.Position(), n.Case))
 11689  	}
 11690  }
 11691  
 11692  func (p *project) primaryExpressionAddrOf(f *function, n *cc.PrimaryExpression, t cc.Type, mode exprMode, flags flags) {
 11693  	switch n.Case {
 11694  	case cc.PrimaryExpressionIdent: // IDENTIFIER
 11695  		switch d := n.Declarator(); {
 11696  		case d != nil:
 11697  			p.declarator(n, f, d, t, mode, flags)
 11698  		default:
 11699  			panic(todo("", p.pos(n)))
 11700  		}
 11701  	case cc.PrimaryExpressionInt: // INTCONST
 11702  		panic(todo("", p.pos(n)))
 11703  	case cc.PrimaryExpressionFloat: // FLOATCONST
 11704  		panic(todo("", p.pos(n)))
 11705  	case cc.PrimaryExpressionEnum: // ENUMCONST
 11706  		panic(todo("", p.pos(n)))
 11707  	case cc.PrimaryExpressionChar: // CHARCONST
 11708  		panic(todo("", p.pos(n)))
 11709  	case cc.PrimaryExpressionLChar: // LONGCHARCONST
 11710  		panic(todo("", p.pos(n)))
 11711  	case cc.PrimaryExpressionString: // STRINGLITERAL
 11712  		p.w("%s", p.stringLiteral(n.Operand.Value()))
 11713  	case cc.PrimaryExpressionLString: // LONGSTRINGLITERAL
 11714  		p.w("%s", p.wideStringLiteral(n.Operand.Value(), 0))
 11715  	case cc.PrimaryExpressionExpr: // '(' Expression ')'
 11716  		p.expression(f, n.Expression, t, mode, flags)
 11717  	case cc.PrimaryExpressionStmt: // '(' CompoundStatement ')'
 11718  		p.err(n, "statement expressions not supported")
 11719  	default:
 11720  		panic(todo("%v: internal error: %v", n.Position(), n.Case))
 11721  	}
 11722  }
 11723  
 11724  func (p *project) primaryExpressionFunc(f *function, n *cc.PrimaryExpression, t cc.Type, mode exprMode, flags flags) {
 11725  	switch n.Case {
 11726  	case cc.PrimaryExpressionIdent: // IDENTIFIER
 11727  		p.fnVal(n, f, func() { p.primaryExpression(f, n, n.Operand.Type(), exprValue, flags) }, n.Declarator(), n.Operand.Type(), 0, mode, flags)
 11728  	case cc.PrimaryExpressionInt: // INTCONST
 11729  		panic(todo("", p.pos(n)))
 11730  	case cc.PrimaryExpressionFloat: // FLOATCONST
 11731  		panic(todo("", p.pos(n)))
 11732  	case cc.PrimaryExpressionEnum: // ENUMCONST
 11733  		panic(todo("", p.pos(n)))
 11734  	case cc.PrimaryExpressionChar: // CHARCONST
 11735  		panic(todo("", p.pos(n)))
 11736  	case cc.PrimaryExpressionLChar: // LONGCHARCONST
 11737  		panic(todo("", p.pos(n)))
 11738  	case cc.PrimaryExpressionString: // STRINGLITERAL
 11739  		panic(todo("", p.pos(n)))
 11740  	case cc.PrimaryExpressionLString: // LONGSTRINGLITERAL
 11741  		panic(todo("", p.pos(n)))
 11742  	case cc.PrimaryExpressionExpr: // '(' Expression ')'
 11743  		p.expression(f, n.Expression, t, mode, flags)
 11744  	case cc.PrimaryExpressionStmt: // '(' CompoundStatement ')'
 11745  		p.err(n, "statement expressions not supported")
 11746  	default:
 11747  		panic(todo("%v: internal error: %v", n.Position(), n.Case))
 11748  	}
 11749  }
 11750  
 11751  func cmpNormalizeValue(v cc.Value) cc.Value {
 11752  	switch x := v.(type) {
 11753  	case cc.Int64Value:
 11754  		if x >= 0 {
 11755  			return cc.Uint64Value(x)
 11756  		}
 11757  	}
 11758  	return v
 11759  }
 11760  
 11761  func (p *project) primaryExpressionValue(f *function, n *cc.PrimaryExpression, t cc.Type, mode exprMode, flags flags) {
 11762  	switch n.Case {
 11763  	case cc.PrimaryExpressionIdent: // IDENTIFIER
 11764  		switch d := n.Declarator(); {
 11765  		case d != nil:
 11766  			p.declarator(n, f, d, t, mode, flags)
 11767  		default:
 11768  			panic(todo("", p.pos(n)))
 11769  		}
 11770  	case cc.PrimaryExpressionInt: // INTCONST
 11771  		if m := n.Token.Macro(); m != 0 {
 11772  			if d := p.defines[m]; d.name != "" {
 11773  				if cmpNormalizeValue(n.Operand.Value()) == cmpNormalizeValue(d.value) {
 11774  					defer p.w("%s", p.convert(n, n.Operand, t, flags))
 11775  					p.w(" %s ", d.name)
 11776  					break
 11777  				}
 11778  
 11779  				p.w("/* %s */", m)
 11780  			}
 11781  		}
 11782  
 11783  		p.intConst(n, n.Token.Src.String(), n.Operand, t, flags)
 11784  	case cc.PrimaryExpressionFloat: // FLOATCONST
 11785  		//TODO use #define
 11786  		p.floatConst(n, n.Token.Src.String(), n.Operand, t, flags)
 11787  	case cc.PrimaryExpressionEnum: // ENUMCONST
 11788  		en := n.ResolvedTo().(*cc.Enumerator)
 11789  		if n.ResolvedIn().Parent() == nil {
 11790  			if nm := p.enumConsts[en.Token.Value]; nm != "" {
 11791  				p.w(" %s ", nm)
 11792  				break
 11793  			}
 11794  		}
 11795  
 11796  		p.intConst(n, "", n.Operand, t, flags)
 11797  		p.w("/* %s */", en.Token.Value)
 11798  	case cc.PrimaryExpressionChar: // CHARCONST
 11799  		p.charConst(n, n.Token.Src.String(), n.Operand, t, flags)
 11800  	case cc.PrimaryExpressionLChar: // LONGCHARCONST
 11801  		p.charConst(n, n.Token.Src.String(), n.Operand, t, flags)
 11802  	case cc.PrimaryExpressionString: // STRINGLITERAL
 11803  		p.w("%s", p.stringLiteral(n.Operand.Value()))
 11804  	case cc.PrimaryExpressionLString: // LONGSTRINGLITERAL
 11805  		p.w("%s", p.wideStringLiteral(n.Operand.Value(), 0))
 11806  	case cc.PrimaryExpressionExpr: // '(' Expression ')'
 11807  		p.w("(")
 11808  		defer p.w(")")
 11809  		p.expression(f, n.Expression, t, mode, flags)
 11810  	case cc.PrimaryExpressionStmt: // '(' CompoundStatement ')'
 11811  		p.statementExpression(f, n.CompoundStatement, t, mode, flags)
 11812  	default:
 11813  		panic(todo("%v: internal error: %v", n.Position(), n.Case))
 11814  	}
 11815  }
 11816  
 11817  func (p *project) statementExpression(f *function, n *cc.CompoundStatement, t cc.Type, mode exprMode, flags flags) {
 11818  	defer p.w("%s", p.convert(n, n.Operand, t, flags))
 11819  	p.w(" func() %v {", p.typ(n, n.Operand.Type()))
 11820  	p.compoundStatement(f, n, "", true, false, mode)
 11821  	p.w("}()")
 11822  }
 11823  
 11824  func (p *project) primaryExpressionLValue(f *function, n *cc.PrimaryExpression, t cc.Type, mode exprMode, flags flags) {
 11825  	switch n.Case {
 11826  	case cc.PrimaryExpressionIdent: // IDENTIFIER
 11827  		switch d := n.Declarator(); {
 11828  		case d != nil:
 11829  			p.declarator(n, f, d, t, mode, flags)
 11830  		default:
 11831  			panic(todo("", p.pos(n)))
 11832  		}
 11833  	case cc.PrimaryExpressionInt: // INTCONST
 11834  		panic(todo("", p.pos(n)))
 11835  	case cc.PrimaryExpressionFloat: // FLOATCONST
 11836  		panic(todo("", p.pos(n)))
 11837  	case cc.PrimaryExpressionEnum: // ENUMCONST
 11838  		panic(todo("", p.pos(n)))
 11839  	case cc.PrimaryExpressionChar: // CHARCONST
 11840  		panic(todo("", p.pos(n)))
 11841  	case cc.PrimaryExpressionLChar: // LONGCHARCONST
 11842  		panic(todo("", p.pos(n)))
 11843  	case cc.PrimaryExpressionString: // STRINGLITERAL
 11844  		panic(todo("", p.pos(n)))
 11845  	case cc.PrimaryExpressionLString: // LONGSTRINGLITERAL
 11846  		panic(todo("", p.pos(n)))
 11847  	case cc.PrimaryExpressionExpr: // '(' Expression ')'
 11848  		p.w("(")
 11849  		defer p.w(")")
 11850  		p.expression(f, n.Expression, t, mode, flags)
 11851  	case cc.PrimaryExpressionStmt: // '(' CompoundStatement ')'
 11852  		p.err(n, "statement expressions not supported")
 11853  	default:
 11854  		panic(todo("%v: internal error: %v", n.Position(), n.Case))
 11855  	}
 11856  }
 11857  
 11858  func (p *project) stringLiteralString(s string) string {
 11859  	if p.pass1 {
 11860  		return ""
 11861  	}
 11862  
 11863  	id := cc.String(s)
 11864  	off, ok := p.tsOffs[id]
 11865  	if !ok {
 11866  		off = uintptr(p.ts.Len())
 11867  		p.ts.WriteString(s)
 11868  		p.ts.WriteByte(0)
 11869  		p.tsOffs[id] = off
 11870  	}
 11871  	return fmt.Sprintf("(%s%s)%s", p.tsNameP, nonZeroUintptr(off), p.stringSnippet(s))
 11872  }
 11873  
 11874  func (p *project) stringLiteral(v cc.Value) string {
 11875  	if p.pass1 {
 11876  		return ""
 11877  	}
 11878  
 11879  	switch x := v.(type) {
 11880  	case cc.StringValue:
 11881  		id := cc.StringID(x)
 11882  		off, ok := p.tsOffs[id]
 11883  		s := id.String()
 11884  		if !ok {
 11885  			off = uintptr(p.ts.Len())
 11886  			p.ts.WriteString(s)
 11887  			p.ts.WriteByte(0)
 11888  			p.tsOffs[id] = off
 11889  		}
 11890  		return fmt.Sprintf("(%s%s)%s", p.tsNameP, nonZeroUintptr(off), p.stringSnippet(s))
 11891  	default:
 11892  		panic(todo("%T", x))
 11893  	}
 11894  }
 11895  
 11896  func (p *project) stringSnippet(s string) string {
 11897  	s = strings.ReplaceAll(s, "*/", "*\\/")
 11898  	const max = 16
 11899  	switch {
 11900  	case len(s) <= max:
 11901  		return fmt.Sprintf("/* %q */", s)
 11902  	default:
 11903  		return fmt.Sprintf("/* %q */", s[:16]+"...")
 11904  	}
 11905  }
 11906  
 11907  func (p *project) wideStringLiteral(v cc.Value, pad int) string {
 11908  	if p.pass1 {
 11909  		return ""
 11910  	}
 11911  
 11912  	switch x := v.(type) {
 11913  	case cc.WideStringValue:
 11914  		id := cc.StringID(x)
 11915  		off, ok := p.tsWOffs[id]
 11916  		if !ok {
 11917  			off = p.wcharSize * uintptr(len(p.tsW))
 11918  			s := []rune(id.String())
 11919  			if pad != 0 {
 11920  				s = append(s, make([]rune, pad)...)
 11921  			}
 11922  			p.tsW = append(p.tsW, s...)
 11923  			p.tsW = append(p.tsW, 0)
 11924  			p.tsWOffs[id] = off
 11925  		}
 11926  		return fmt.Sprintf("(%s%s)", p.tsWNameP, nonZeroUintptr(off))
 11927  	default:
 11928  		panic(todo("%T", x))
 11929  	}
 11930  }
 11931  
 11932  func (p *project) charConst(n cc.Node, src string, op cc.Operand, to cc.Type, flags flags) {
 11933  	switch {
 11934  	case to.IsArithmeticType():
 11935  		defer p.w("%s", p.convert(n, op, to, flags))
 11936  	case to.Kind() == cc.Ptr && op.IsZero():
 11937  		p.w(" 0 ")
 11938  		return
 11939  	default:
 11940  		panic(todo("%v: t %v, to %v, to.Alias() %v", n.Position(), op.Type(), to, to.Alias()))
 11941  	}
 11942  
 11943  	r, mb, _, err := strconv.UnquoteChar(src[1:len(src)-1], '\'')
 11944  	rValid := !mb && err == nil
 11945  	var on uint64
 11946  	switch x := op.Value().(type) {
 11947  	case cc.Int64Value:
 11948  		on = uint64(x)
 11949  	case cc.Uint64Value:
 11950  		on = uint64(x)
 11951  	default:
 11952  		panic(todo("%T(%v)", x, x))
 11953  	}
 11954  	var mask uint64
 11955  	switch {
 11956  	case !to.IsIntegerType():
 11957  		// ok
 11958  		if rValid { // Prefer original form
 11959  			p.w("%s", src)
 11960  			return
 11961  		}
 11962  
 11963  		p.w("%d", on)
 11964  		return
 11965  	case to.IsSignedType():
 11966  		var in int64
 11967  		var ok bool
 11968  		switch to.Size() {
 11969  		case 1:
 11970  			in = int64(int8(on))
 11971  			ok = int8(on) >= 0
 11972  		case 2:
 11973  			in = int64(int16(on))
 11974  			ok = int16(on) >= 0
 11975  		case 4:
 11976  			in = int64(int32(on))
 11977  			ok = int32(on) >= 0
 11978  		case 8:
 11979  			in = int64(int64(on))
 11980  			ok = in >= 0
 11981  		default:
 11982  			panic(todo("", op.Type().Size()))
 11983  		}
 11984  		if ok && rValid && uint64(in) == on { // Prefer original form
 11985  			p.w("%s", src)
 11986  			return
 11987  		}
 11988  
 11989  		p.w("%d", in)
 11990  	default:
 11991  		switch to.Size() {
 11992  		case 1:
 11993  			mask = 0xff
 11994  		case 2:
 11995  			mask = 0xffff
 11996  		case 4:
 11997  			mask = 0xffffffff
 11998  		case 8:
 11999  			mask = 0xffffffffffffffff
 12000  		default:
 12001  			panic(todo("", op.Type().Size()))
 12002  		}
 12003  		if rValid && uint64(r)&mask == on { // Prefer original form
 12004  			p.w("%s", src)
 12005  			return
 12006  		}
 12007  
 12008  		p.w("%d", on&mask)
 12009  	}
 12010  }
 12011  
 12012  func (p *project) floatConst(n cc.Node, src string, op cc.Operand, to cc.Type, flags flags) {
 12013  	if flags&fForceRuntimeConv != 0 {
 12014  		p.w("%s(", p.helperType2(n, op.Type(), to))
 12015  		defer p.w(")")
 12016  	}
 12017  
 12018  	bits := 64
 12019  	switch to.Kind() {
 12020  	case cc.Float:
 12021  		bits = 32
 12022  	}
 12023  	src = strings.TrimRight(src, "flFL")
 12024  	sn, err := strconv.ParseFloat(src, bits)
 12025  	snValid := err == nil
 12026  	switch x := op.Value().(type) {
 12027  	case cc.Float64Value:
 12028  		switch to.Kind() {
 12029  		case cc.Double:
 12030  			if snValid && sn == float64(x) { // Prefer original form.
 12031  				p.w("%s", src)
 12032  				return
 12033  			}
 12034  
 12035  			p.w("math.Float64frombits(%#x)", math.Float64bits(float64(x)))
 12036  		case cc.Float:
 12037  			if snValid && float32(sn) == float32(x) { // Prefer original form.
 12038  				p.w("%s", src)
 12039  				return
 12040  			}
 12041  
 12042  			p.w("math.Float32frombits(%#x)", math.Float32bits(float32(x)))
 12043  		default:
 12044  			defer p.w("%s", p.convert(n, op, to, 0))
 12045  			if snValid && sn == float64(x) { // Prefer original form.
 12046  				p.w("%s", src)
 12047  				return
 12048  			}
 12049  
 12050  			p.w("math.Float64frombits(%#x)", math.Float64bits(float64(x)))
 12051  		}
 12052  	case cc.Float32Value:
 12053  		switch to.Kind() {
 12054  		case cc.Double:
 12055  			if snValid && float32(sn) == float32(x) { // Prefer original form.
 12056  				p.w("%s", src)
 12057  				return
 12058  			}
 12059  
 12060  			p.w("math.Float64frombits(%#x)", math.Float64bits(float64(x)))
 12061  		case cc.Float:
 12062  			if snValid && float32(sn) == float32(x) { // Prefer original form.
 12063  				p.w("%s", src)
 12064  				return
 12065  			}
 12066  
 12067  			p.w("math.Float32frombits(%#x)", math.Float32bits(float32(x)))
 12068  		default:
 12069  			if to.IsIntegerType() {
 12070  				if s := p.float2Int(n, x, to); s != "" {
 12071  					defer p.w("%s%s", s, p.convertType(n, op.Type(), to, 0))
 12072  					break
 12073  				}
 12074  			}
 12075  
 12076  			defer p.w("%s", p.convert(n, op, to, 0))
 12077  			if snValid && float32(sn) == float32(x) { // Prefer original form.
 12078  				p.w("%s", src)
 12079  				return
 12080  			}
 12081  
 12082  			p.w("math.Float32frombits(%#x)", math.Float32bits(float32(x)))
 12083  		}
 12084  	default:
 12085  		panic(todo("%T(%v)", x, x))
 12086  	}
 12087  }
 12088  
 12089  func (p *project) float2Int(n cc.Node, x cc.Float32Value, to cc.Type) string {
 12090  	switch {
 12091  	case to.IsSignedType():
 12092  		limits := &signedSaturationLimits[to.Size()]
 12093  		v := float64(x)
 12094  		switch {
 12095  		case math.IsNaN(v):
 12096  			panic(todo("", p.pos(n)))
 12097  		case math.IsInf(v, -1):
 12098  			panic(todo("", p.pos(n)))
 12099  		case math.IsInf(v, 1):
 12100  			panic(todo("", p.pos(n)))
 12101  		case v < limits.fmin:
 12102  			return fmt.Sprint(limits.min)
 12103  		case v > limits.fmax:
 12104  			return fmt.Sprint(limits.max)
 12105  		}
 12106  	default:
 12107  		limits := &unsignedSaturationLimits[to.Size()]
 12108  		v := float64(x)
 12109  		switch {
 12110  		case math.IsNaN(v):
 12111  			panic(todo("", p.pos(n)))
 12112  		case math.IsInf(v, -1):
 12113  			panic(todo("", p.pos(n)))
 12114  		case math.IsInf(v, 1):
 12115  			panic(todo("", p.pos(n)))
 12116  		case v < 0:
 12117  			return "0"
 12118  		case v > limits.fmax:
 12119  			return fmt.Sprint(limits.max)
 12120  		}
 12121  	}
 12122  	return ""
 12123  }
 12124  
 12125  type signedSaturationLimit struct {
 12126  	fmin, fmax float64
 12127  	min, max   int64
 12128  }
 12129  
 12130  type unsignedSaturationLimit struct {
 12131  	fmax float64
 12132  	max  uint64
 12133  }
 12134  
 12135  var (
 12136  	signedSaturationLimits = [...]signedSaturationLimit{
 12137  		1: {math.Nextafter(math.MinInt32, 0), math.Nextafter(math.MaxInt32, 0), math.MinInt32, math.MaxInt32},
 12138  		2: {math.Nextafter(math.MinInt32, 0), math.Nextafter(math.MaxInt32, 0), math.MinInt32, math.MaxInt32},
 12139  		4: {math.Nextafter(math.MinInt32, 0), math.Nextafter(math.MaxInt32, 0), math.MinInt32, math.MaxInt32},
 12140  		8: {math.Nextafter(math.MinInt64, 0), math.Nextafter(math.MaxInt64, 0), math.MinInt64, math.MaxInt64},
 12141  	}
 12142  
 12143  	unsignedSaturationLimits = [...]unsignedSaturationLimit{
 12144  		1: {math.Nextafter(math.MaxUint32, 0), math.MaxUint32},
 12145  		2: {math.Nextafter(math.MaxUint32, 0), math.MaxUint32},
 12146  		4: {math.Nextafter(math.MaxUint32, 0), math.MaxUint32},
 12147  		8: {math.Nextafter(math.MaxUint64, 0), math.MaxUint64},
 12148  	}
 12149  )
 12150  
 12151  func (p *project) intConst(n cc.Node, src string, op cc.Operand, to cc.Type, flags flags) {
 12152  	ptr := to.Kind() == cc.Ptr
 12153  	switch {
 12154  	case to.IsArithmeticType():
 12155  		// p.w("/*10568 %T(%#[1]x) %v -> %v */", op.Value(), op.Type(), to) //TODO-
 12156  		if flags&fForceNoConv != 0 {
 12157  			break
 12158  		}
 12159  
 12160  		if !op.Type().IsSignedType() && op.Type().Size() == 8 && op.Value().(cc.Uint64Value) > math.MaxInt64 {
 12161  			flags |= fForceRuntimeConv
 12162  		}
 12163  		defer p.w("%s", p.convert(n, op, to, flags))
 12164  	case ptr:
 12165  		p.w(" uintptr(")
 12166  		defer p.w(")")
 12167  		// ok
 12168  	default:
 12169  		panic(todo("%v: %v -> %v", p.pos(n), op.Type(), to))
 12170  	}
 12171  
 12172  	src = strings.TrimRight(src, "luLU")
 12173  	sn, err := strconv.ParseUint(src, 0, 64)
 12174  	snValid := err == nil
 12175  	var on uint64
 12176  	switch x := op.Value().(type) {
 12177  	case cc.Int64Value:
 12178  		if x < 0 {
 12179  			sn, err := strconv.ParseInt(src, 0, 64)
 12180  			snValid := err == nil
 12181  			if snValid && sn == int64(x) { // Prefer original form
 12182  				p.w("%s", src)
 12183  				return
 12184  			}
 12185  
 12186  			p.w("%d", x)
 12187  			return
 12188  		}
 12189  
 12190  		on = uint64(x)
 12191  	case cc.Uint64Value:
 12192  		on = uint64(x)
 12193  	default:
 12194  		panic(todo("%T(%v)", x, x))
 12195  	}
 12196  
 12197  	if snValid && sn == on { // Prefer original form
 12198  		p.w("%s", src)
 12199  		return
 12200  	}
 12201  
 12202  	p.w("%d", on)
 12203  }
 12204  
 12205  func (p *project) assignShiftOp(f *function, n *cc.AssignmentExpression, t cc.Type, mode exprMode, oper, oper2 string, flags flags) {
 12206  	// UnaryExpression "<<=" AssignmentExpression etc.
 12207  	switch mode {
 12208  	case exprVoid:
 12209  		p.assignShiftOpVoid(f, n, t, mode, oper, oper2, flags)
 12210  	default:
 12211  		panic(todo("", mode))
 12212  	}
 12213  }
 12214  
 12215  func (p *project) assignShiftOpVoid(f *function, n *cc.AssignmentExpression, t cc.Type, mode exprMode, oper, oper2 string, flags flags) {
 12216  	// UnaryExpression "<<=" AssignmentExpression etc.
 12217  	switch k := p.opKind(f, n.UnaryExpression, n.UnaryExpression.Operand.Type()); k {
 12218  	case opNormal:
 12219  		p.assignShiftOpVoidNormal(f, n, t, mode, oper, oper2, flags)
 12220  	default:
 12221  		panic(todo("", n.Position(), k))
 12222  	}
 12223  }
 12224  
 12225  func (p *project) assignShiftOpVoidNormal(f *function, n *cc.AssignmentExpression, t cc.Type, mode exprMode, oper, oper2 string, flags flags) {
 12226  	switch {
 12227  	case n.Operand.Type().IsBitFieldType():
 12228  		panic(todo("", p.pos(n)))
 12229  	default:
 12230  		if d := n.UnaryExpression.Declarator(); d != nil {
 12231  			switch d.Type().Kind() {
 12232  			case cc.Int128, cc.UInt128:
 12233  				p.declarator(n, f, d, d.Type(), exprLValue, flags)
 12234  				p.w(".LValue%s(", oper2)
 12235  				p.assignmentExpression(f, n.AssignmentExpression, p.intType, exprValue, flags)
 12236  				p.w(")")
 12237  				return
 12238  			default:
 12239  				p.declarator(n, f, d, d.Type(), exprLValue, flags)
 12240  				p.w(" %s= ", oper)
 12241  				p.assignmentExpression(f, n.AssignmentExpression, n.Promote(), exprValue, flags)
 12242  				return
 12243  			}
 12244  		}
 12245  
 12246  		lhs := n.UnaryExpression
 12247  		switch {
 12248  		case lhs.Operand.Type().IsArithmeticType():
 12249  			p.w("%sAssign%sPtr%s(", p.task.crt, oper2, p.helperType(n, lhs.Operand.Type()))
 12250  			p.unaryExpression(f, lhs, lhs.Operand.Type(), exprAddrOf, flags)
 12251  			p.w(", int(")
 12252  			p.assignmentExpression(f, n.AssignmentExpression, n.Promote(), exprValue, flags)
 12253  			p.w("))")
 12254  		default:
 12255  			panic(todo("", p.pos(n), lhs.Operand.Type()))
 12256  		}
 12257  	}
 12258  }
 12259  
 12260  func (p *project) assignOp(f *function, n *cc.AssignmentExpression, t cc.Type, mode exprMode, oper, oper2 string, flags flags) {
 12261  	// UnaryExpression "*=" AssignmentExpression etc.
 12262  	switch mode {
 12263  	case exprVoid:
 12264  		p.assignOpVoid(f, n, t, mode, oper, oper2, flags)
 12265  	case exprValue, exprCondReturn:
 12266  		p.assignOpValue(f, n, t, mode, oper, oper2, flags)
 12267  	default:
 12268  		panic(todo("", n.Position(), mode))
 12269  	}
 12270  }
 12271  
 12272  func (p *project) assignOpValue(f *function, n *cc.AssignmentExpression, t cc.Type, mode exprMode, oper, oper2 string, flags flags) {
 12273  	// UnaryExpression "*=" AssignmentExpression etc.
 12274  	switch k := p.opKind(f, n.UnaryExpression, n.UnaryExpression.Operand.Type()); k {
 12275  	case opNormal:
 12276  		p.assignOpValueNormal(f, n, t, oper, oper2, mode, flags)
 12277  	case opBitfield:
 12278  		p.assignOpValueBitfield(f, n, t, oper, oper2, mode, flags)
 12279  	default:
 12280  		panic(todo("", n.Position(), k))
 12281  	}
 12282  }
 12283  
 12284  func (p *project) assignOpValueBitfield(f *function, n *cc.AssignmentExpression, t cc.Type, oper, oper2 string, mode exprMode, flags flags) {
 12285  	// UnaryExpression "*=" AssignmentExpression etc.
 12286  
 12287  	asInt := oper2 == "Shl" || oper2 == "Shr"
 12288  	if asInt {
 12289  		panic(todo(""))
 12290  	}
 12291  
 12292  	ot := n.Operand.Type()
 12293  	lhs := n.UnaryExpression
 12294  	bf := lhs.Operand.Type().BitField()
 12295  	defer p.w("%s", p.convertType(n, ot, t, flags))
 12296  	p.w(" func() %v {", p.typ(n, ot))
 12297  	switch lhs.Case {
 12298  	case cc.UnaryExpressionPostfix: // PostfixExpression
 12299  		pe := n.UnaryExpression.PostfixExpression
 12300  		switch pe.Case {
 12301  		case cc.PostfixExpressionSelect: // PostfixExpression '.' IDENTIFIER
 12302  			p.w("__p := ")
 12303  			p.postfixExpression(f, pe, pe.Operand.Type(), exprAddrOf, flags)
 12304  			p.w("; __v := ")
 12305  			p.readBitfield(lhs, "__p", bf, ot)
 12306  			p.w(" %s (", oper)
 12307  			p.assignmentExpression(f, n.AssignmentExpression, ot, exprValue, flags)
 12308  			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())
 12309  		case cc.PostfixExpressionPSelect: // PostfixExpression "->" IDENTIFIER
 12310  			panic(todo("", p.pos(n)))
 12311  		default:
 12312  			panic(todo("", n.Position(), pe.Case))
 12313  		}
 12314  	default:
 12315  		panic(todo("", n.Position(), lhs.Case))
 12316  	}
 12317  	p.w("}()")
 12318  }
 12319  
 12320  func (p *project) readBitfield(n cc.Node, ptr string, bf cc.Field, promote cc.Type) {
 12321  	bw := bf.BitFieldBlockWidth()
 12322  	m := bf.Mask()
 12323  	o := bf.BitFieldOffset()
 12324  	w := bf.BitFieldWidth()
 12325  	p.w("(%s(*(*uint%d)(unsafe.Pointer(%s))&%#x)", p.typ(n, promote), bw, ptr, m)
 12326  	switch {
 12327  	case bf.Type().IsSignedType():
 12328  		bits := int(promote.Size()) * 8
 12329  		p.w("<<%d>>%d)", bits-w-o, bits-w)
 12330  	default:
 12331  		p.w(">>%d)", o)
 12332  	}
 12333  }
 12334  
 12335  func (p *project) assignOpValueNormal(f *function, n *cc.AssignmentExpression, t cc.Type, oper, oper2 string, mode exprMode, flags flags) {
 12336  	if mode == exprCondReturn {
 12337  		p.w("return ")
 12338  	}
 12339  	asInt := oper2 == "Shl" || oper2 == "Shr"
 12340  	lhs := n.UnaryExpression
 12341  	// UnaryExpression "*=" AssignmentExpression etc.
 12342  	if d := lhs.Declarator(); d != nil {
 12343  		if local := f.locals[d]; local != nil && local.isPinned {
 12344  			switch {
 12345  			case lhs.Operand.Type().IsArithmeticType():
 12346  				defer p.w("%s", p.convertType(n, lhs.Operand.Type(), t, flags))
 12347  				p.w("%sAssign%sPtr%s(", p.task.crt, oper2, p.helperType(n, lhs.Operand.Type()))
 12348  				p.unaryExpression(f, lhs, lhs.Operand.Type(), exprAddrOf, flags)
 12349  				p.w(", ")
 12350  				if asInt {
 12351  					p.w("int(")
 12352  				}
 12353  				p.assignmentExpression(f, n.AssignmentExpression, lhs.Operand.Type(), exprValue, flags)
 12354  				if asInt {
 12355  					p.w(")")
 12356  				}
 12357  				p.w(")")
 12358  			default:
 12359  				panic(todo("", lhs.Operand.Type()))
 12360  			}
 12361  			return
 12362  		}
 12363  
 12364  		switch {
 12365  		case d.Type().Kind() == cc.Ptr:
 12366  			defer p.w("%s", p.convertType(n, d.Type(), t, flags))
 12367  			p.w("%sAssign%s%s(&", p.task.crt, oper2, p.helperType(n, d.Type()))
 12368  			p.declarator(n, f, d, d.Type(), exprLValue, flags)
 12369  			p.w(", ")
 12370  			if dd := p.incDelta(d, d.Type()); dd != 1 {
 12371  				p.w("%d*(", dd)
 12372  				defer p.w(")")
 12373  			}
 12374  			p.assignmentExpression(f, n.AssignmentExpression, d.Type(), exprValue, flags)
 12375  			p.w(")")
 12376  		case d.Type().IsArithmeticType():
 12377  			defer p.w("%s", p.convertType(n, d.Type(), t, flags))
 12378  			p.w("%sAssign%s%s(&", p.task.crt, oper2, p.helperType(n, d.Type()))
 12379  			p.declarator(n, f, d, d.Type(), exprLValue, flags)
 12380  			p.w(", ")
 12381  			if asInt {
 12382  				p.w("int(")
 12383  			}
 12384  			p.assignmentExpression(f, n.AssignmentExpression, d.Type(), exprValue, flags)
 12385  			p.w(")")
 12386  			if asInt {
 12387  				p.w(")")
 12388  			}
 12389  		default:
 12390  			panic(todo("", p.pos(n), p.pos(d), d.Name()))
 12391  		}
 12392  		return
 12393  	}
 12394  
 12395  	switch {
 12396  	case lhs.Operand.Type().IsArithmeticType():
 12397  		defer p.w("%s", p.convertType(n, lhs.Operand.Type(), t, flags))
 12398  		p.w("%sAssign%sPtr%s(", p.task.crt, oper2, p.helperType(n, lhs.Operand.Type()))
 12399  		p.unaryExpression(f, lhs, lhs.Operand.Type(), exprAddrOf, flags)
 12400  		p.w(", ")
 12401  		if asInt {
 12402  			p.w("int(")
 12403  		}
 12404  		p.assignmentExpression(f, n.AssignmentExpression, lhs.Operand.Type(), exprValue, flags)
 12405  		if asInt {
 12406  			p.w(")")
 12407  		}
 12408  		p.w(")")
 12409  	default:
 12410  		panic(todo("", lhs.Operand.Type()))
 12411  	}
 12412  }
 12413  
 12414  func (p *project) assignOpVoid(f *function, n *cc.AssignmentExpression, t cc.Type, mode exprMode, oper, oper2 string, flags flags) {
 12415  	// UnaryExpression "*=" AssignmentExpression etc.
 12416  	switch k := p.opKind(f, n.UnaryExpression, n.UnaryExpression.Operand.Type()); k {
 12417  	case opNormal:
 12418  		p.assignOpVoidNormal(f, n, t, oper, oper2, mode, flags)
 12419  	case opBitfield:
 12420  		p.assignOpVoidBitfield(f, n, t, oper, oper2, mode, flags)
 12421  	case opArrayParameter:
 12422  		p.assignOpVoidArrayParameter(f, n, t, oper, oper2, mode, flags)
 12423  	default:
 12424  		panic(todo("", n.Position(), k))
 12425  	}
 12426  }
 12427  
 12428  func (p *project) assignOpVoidArrayParameter(f *function, n *cc.AssignmentExpression, t cc.Type, oper, oper2 string, mode exprMode, flags flags) {
 12429  	// UnaryExpression "*=" AssignmentExpression etc.
 12430  	if oper != "+" && oper != "-" {
 12431  		panic(todo("", p.pos(n)))
 12432  	}
 12433  
 12434  	d := n.UnaryExpression.Declarator()
 12435  	switch local := f.locals[d]; {
 12436  	case local != nil && local.isPinned:
 12437  		p.w("*(*uintptr)(unsafe.Pointer(%s%s))", f.bpName, nonZeroUintptr(local.off))
 12438  	default:
 12439  		p.declarator(n, f, d, d.Type(), exprLValue, flags)
 12440  	}
 12441  
 12442  	p.w(" %s= ", oper)
 12443  	if dd := p.incDelta(d, d.Type()); dd != 1 {
 12444  		p.w("%d*", dd)
 12445  	}
 12446  	p.w("uintptr(")
 12447  	p.assignmentExpression(f, n.AssignmentExpression, n.AssignmentExpression.Operand.Type(), exprValue, flags)
 12448  	p.w(")")
 12449  }
 12450  
 12451  func (p *project) assignOpVoidBitfield(f *function, n *cc.AssignmentExpression, t cc.Type, oper, oper2 string, mode exprMode, flags flags) {
 12452  	// UnaryExpression "*=" AssignmentExpression etc.
 12453  	lhs := n.UnaryExpression
 12454  	lt := lhs.Operand.Type()
 12455  	switch lhs.Case {
 12456  	case cc.UnaryExpressionPostfix: // PostfixExpression
 12457  		pe := n.UnaryExpression.PostfixExpression
 12458  		switch pe.Case {
 12459  		case cc.PostfixExpressionSelect: // PostfixExpression '.' IDENTIFIER
 12460  			bf := lt.BitField()
 12461  			p.w("%sSetBitFieldPtr%d%s(", p.task.crt, bf.BitFieldBlockWidth(), p.bfHelperType(n.Promote()))
 12462  			p.unaryExpression(f, lhs, lt, exprAddrOf, flags)
 12463  			p.w(", (")
 12464  			s := p.convertType(n, lt, n.Promote(), flags)
 12465  			p.unaryExpression(f, lhs, lt, exprValue, flags)
 12466  			p.w(")%s %s ", s, oper)
 12467  			s = p.convertType(n, lt, n.Promote(), flags)
 12468  			p.assignmentExpression(f, n.AssignmentExpression, n.Promote(), exprValue, flags)
 12469  			p.w("%s", s)
 12470  			p.w(", %d, %#x)", bf.BitFieldOffset(), bf.Mask())
 12471  		case cc.PostfixExpressionPSelect: // PostfixExpression "->" IDENTIFIER
 12472  			switch d := pe.PostfixExpression.Declarator(); {
 12473  			case d != nil:
 12474  				panic(todo("", p.pos(n)))
 12475  			default:
 12476  				panic(todo("", p.pos(n)))
 12477  			}
 12478  		default:
 12479  			panic(todo("", n.Position(), pe.Case))
 12480  		}
 12481  	default:
 12482  		panic(todo("", n.Position(), lhs.Case))
 12483  	}
 12484  }
 12485  
 12486  func (p *project) assignOpVoidNormal(f *function, n *cc.AssignmentExpression, t cc.Type, oper, oper2 string, mode exprMode, flags flags) {
 12487  	// UnaryExpression "*=" AssignmentExpression etc.
 12488  	rop := n.AssignmentExpression.Operand
 12489  	if d := n.UnaryExpression.Declarator(); d != nil {
 12490  		if local := f.locals[d]; local != nil && local.isPinned {
 12491  			if p.isVolatileOrAtomic(d) {
 12492  				panic(todo(""))
 12493  			}
 12494  
 12495  			p.declarator(n, f, d, d.Type(), exprLValue, flags)
 12496  			switch {
 12497  			case d.Type().Kind() == cc.Ptr:
 12498  				p.w(" %s= ", oper)
 12499  				if dd := p.incDelta(d, d.Type()); dd != 1 {
 12500  					p.w("%d*(", dd)
 12501  					defer p.w(")")
 12502  				}
 12503  				defer p.w("%s", p.convert(n, rop.ConvertTo(n.Promote()), d.Type(), flags))
 12504  				p.assignmentExpression(f, n.AssignmentExpression, n.Promote(), exprValue, flags)
 12505  			case d.Type().IsArithmeticType():
 12506  				p.w(" %s= ", oper)
 12507  				defer p.w("%s", p.convert(n, rop.ConvertTo(n.Promote()), d.Type(), flags))
 12508  				p.assignmentExpression(f, n.AssignmentExpression, n.Promote(), exprValue, flags)
 12509  			default:
 12510  				panic(todo("", n.Position(), d.Type().Kind()))
 12511  			}
 12512  			return
 12513  		}
 12514  
 12515  		if p.isVolatileOrAtomic(d) {
 12516  			var local *local
 12517  			var tld *tld
 12518  			var nm string
 12519  			if f != nil {
 12520  				if local = f.locals[d]; local != nil {
 12521  					nm = local.name
 12522  				}
 12523  			}
 12524  
 12525  			if local == nil {
 12526  				if tld = p.tlds[d]; tld == nil {
 12527  					p.err(n, "%v: internal error (%v: %v)", n.Position(), d.Position(), d.Name())
 12528  					return
 12529  				}
 12530  
 12531  				nm = tld.name
 12532  			}
 12533  			var sign string
 12534  			switch oper {
 12535  			case "-":
 12536  				sign = oper
 12537  				fallthrough
 12538  			case "+":
 12539  				sz := d.Type().Size()
 12540  				var ht string
 12541  				switch sz {
 12542  				case 4, 8:
 12543  					if !d.Type().IsScalarType() {
 12544  						p.err(n, "unsupported volatile declarator type: %v", d.Type())
 12545  						break
 12546  					}
 12547  
 12548  					ht = p.helperType(n, d.Type())
 12549  				default:
 12550  					p.err(n, "unsupported volatile declarator size: %v", sz)
 12551  					return
 12552  				}
 12553  
 12554  				if local != nil {
 12555  					if local.isPinned {
 12556  						panic(todo(""))
 12557  					}
 12558  				}
 12559  
 12560  				p.w("%sAtomicAdd%s(&%s, %s%s(", p.task.crt, ht, nm, sign, p.typ(n, d.Type()))
 12561  				p.assignmentExpression(f, n.AssignmentExpression, n.Promote(), exprValue, flags)
 12562  				p.w("))")
 12563  				return
 12564  			default:
 12565  				p.warn(n, "unsupported volatile declarator operation: %v", oper)
 12566  				p.w("%s = ", nm)
 12567  				defer p.w("%s", p.convert(n, rop.ConvertTo(n.Promote()), d.Type(), flags))
 12568  				p.declarator(n, f, d, n.Promote(), exprValue, flags)
 12569  				p.w(" %s (", oper)
 12570  				p.assignmentExpression(f, n.AssignmentExpression, n.Promote(), exprValue, flags)
 12571  				p.w(")")
 12572  				return
 12573  			}
 12574  		}
 12575  
 12576  		p.declarator(n, f, d, d.Type(), exprLValue, flags)
 12577  		switch d.Type().Kind() {
 12578  		case cc.Ptr:
 12579  			if oper != "+" && oper != "-" {
 12580  				panic(todo("", p.pos(n)))
 12581  			}
 12582  
 12583  			p.w(" %s= ", oper)
 12584  			if dd := p.incDelta(d, d.Type()); dd != 1 {
 12585  				p.w("%d*(", dd)
 12586  				defer p.w(")")
 12587  			}
 12588  			defer p.w("%s", p.convert(n, rop.ConvertTo(n.Promote()), d.Type(), flags))
 12589  			p.assignmentExpression(f, n.AssignmentExpression, n.Promote(), exprValue, flags)
 12590  		case cc.Int128, cc.UInt128:
 12591  			p.w(" = ")
 12592  			p.declarator(n, f, d, n.Promote(), exprValue, flags)
 12593  			p.w(".%s(", oper2)
 12594  			p.assignmentExpression(f, n.AssignmentExpression, n.Promote(), exprValue, flags)
 12595  			p.w(")")
 12596  		default:
 12597  			p.w(" = ")
 12598  			defer p.w("%s", p.convert(n, rop.ConvertTo(n.Promote()), d.Type(), flags))
 12599  			p.declarator(n, f, d, n.Promote(), exprValue, flags)
 12600  			p.w(" %s (", oper)
 12601  			p.assignmentExpression(f, n.AssignmentExpression, n.Promote(), exprValue, flags)
 12602  			p.w(")")
 12603  		}
 12604  		return
 12605  	}
 12606  
 12607  	lhs := n.UnaryExpression
 12608  	switch {
 12609  	case lhs.Operand.Type().IsArithmeticType():
 12610  		p.w("*(*%s)(unsafe.Pointer(", p.typ(n, lhs.Operand.Type()))
 12611  		p.unaryExpression(f, lhs, lhs.Operand.Type(), exprAddrOf, flags)
 12612  		p.w(")) %s= ", oper)
 12613  		defer p.w("%s", p.convert(n, rop.ConvertTo(n.Promote()), lhs.Operand.Type(), flags))
 12614  		p.w("(")
 12615  		p.assignmentExpression(f, n.AssignmentExpression, n.Promote(), exprValue, flags)
 12616  		p.w(")")
 12617  	case lhs.Operand.Type().Kind() == cc.Ptr:
 12618  		p.w("*(*%s)(unsafe.Pointer(", p.typ(n, lhs.Operand.Type()))
 12619  		p.unaryExpression(f, lhs, lhs.Operand.Type(), exprAddrOf, flags)
 12620  		p.w(")) %s= (", oper)
 12621  		p.assignmentExpression(f, n.AssignmentExpression, lhs.Operand.Type(), exprValue, flags)
 12622  		p.w(")")
 12623  		if dd := p.incDelta(n, lhs.Operand.Type()); dd != 1 {
 12624  			p.w("*%d", dd)
 12625  		}
 12626  	default:
 12627  		panic(todo("", lhs.Operand.Type()))
 12628  	}
 12629  }
 12630  
 12631  func (p *project) warn(n cc.Node, s string, args ...interface{}) {
 12632  	s = fmt.Sprintf(s, args...)
 12633  	s = strings.TrimRight(s, "\t\n\r")
 12634  	fmt.Fprintf(os.Stderr, "%v: warning: %s\n", n.Position(), s)
 12635  }
 12636  
 12637  func (p *project) iterationStatement(f *function, n *cc.IterationStatement) {
 12638  	sv := f.switchCtx
 12639  	sv2 := f.continueCtx
 12640  	sv3 := f.breakCtx
 12641  	f.switchCtx = 0
 12642  	f.continueCtx = 0
 12643  	f.breakCtx = 0
 12644  	defer func() {
 12645  		f.breakCtx = sv3
 12646  		f.continueCtx = sv2
 12647  		f.switchCtx = sv
 12648  	}()
 12649  	p.w("%s", tidyComment("\n", n))
 12650  	switch n.Case {
 12651  	case cc.IterationStatementWhile: // "while" '(' Expression ')' Statement
 12652  		if f.hasJumps {
 12653  			// a:	if !expr goto b
 12654  			//	stmt
 12655  			//	goto a
 12656  			// b:
 12657  			a := f.flatLabel()
 12658  			b := f.flatLabel()
 12659  			f.continueCtx = a
 12660  			f.breakCtx = b
 12661  			p.w("__%d: if !(", a)
 12662  			p.expression(f, n.Expression, n.Expression.Operand.Type(), exprBool, 0)
 12663  			p.w(") { goto __%d };", b)
 12664  			p.statement(f, n.Statement, false, false, false, 0)
 12665  			p.w("; goto __%d; __%d:", a, b)
 12666  			break
 12667  		}
 12668  
 12669  		p.w("for ")
 12670  		p.expression(f, n.Expression, n.Expression.Operand.Type(), exprBool, 0)
 12671  		p.statement(f, n.Statement, true, false, false, 0)
 12672  	case cc.IterationStatementDo: // "do" Statement "while" '(' Expression ')' ';'
 12673  		if f.hasJumps {
 12674  			// a:	stmt
 12675  			// b:	if expr goto a // b is the continue label
 12676  			// c:
 12677  			a := f.flatLabel()
 12678  			b := f.flatLabel()
 12679  			c := f.flatLabel()
 12680  			f.continueCtx = b
 12681  			f.breakCtx = c
 12682  			p.w("__%d:", a)
 12683  			p.statement(f, n.Statement, false, false, false, 0)
 12684  			p.w(";goto __%d; __%[1]d: if ", b)
 12685  			p.expression(f, n.Expression, n.Expression.Operand.Type(), exprBool, 0)
 12686  			p.w("{goto __%d};goto __%d;__%[2]d:", a, c)
 12687  			break
 12688  		}
 12689  
 12690  		v := "__ccgo"
 12691  		if !p.pass1 {
 12692  			v = f.scope.take(cc.String(v))
 12693  		}
 12694  		p.w("for %v := true; %[1]v; %[1]v = ", v)
 12695  		p.expression(f, n.Expression, n.Expression.Operand.Type(), exprBool, 0)
 12696  		p.statement(f, n.Statement, true, false, false, 0)
 12697  	case cc.IterationStatementFor: // "for" '(' Expression ';' Expression ';' Expression ')' Statement
 12698  		if f.hasJumps || n.Expression3 != nil && n.Expression3.Case == cc.ExpressionComma {
 12699  			//	expr
 12700  			// a:	if !expr2 goto c
 12701  			//	stmt
 12702  			// b: 	expr3 // label for continue
 12703  			//	goto a
 12704  			// c:
 12705  			a := f.flatLabel()
 12706  			b := f.flatLabel()
 12707  			f.continueCtx = b
 12708  			c := f.flatLabel()
 12709  			f.breakCtx = c
 12710  			if n.Expression != nil {
 12711  				p.expression(f, n.Expression, n.Expression.Operand.Type(), exprVoid, fNoCondAssignment)
 12712  			}
 12713  			semi := ""
 12714  			if n.Expression != nil || n.Expression2 != nil || n.Expression3 != nil {
 12715  				semi = ";"
 12716  			}
 12717  			p.w("%s__%d:", semi, a)
 12718  			if n.Expression2 != nil {
 12719  				p.w("if !(")
 12720  				p.expression(f, n.Expression2, n.Expression2.Operand.Type(), exprBool, 0)
 12721  				p.w(") { goto __%d }", c)
 12722  			}
 12723  			p.w("%s", semi)
 12724  			p.statement(f, n.Statement, false, false, false, 0)
 12725  			p.w(";goto __%d; __%[1]d:", b)
 12726  			if n.Expression3 != nil {
 12727  				p.expression(f, n.Expression3, n.Expression3.Operand.Type(), exprVoid, fNoCondAssignment)
 12728  			}
 12729  			p.w("%sgoto __%d; goto __%d;__%[3]d:", semi, a, c)
 12730  			break
 12731  		}
 12732  
 12733  		expr := true
 12734  		if n.Expression != nil && n.Expression.Case == cc.ExpressionComma {
 12735  			p.expression(f, n.Expression, n.Expression.Operand.Type(), exprVoid, 0)
 12736  			p.w(";")
 12737  			expr = false
 12738  		}
 12739  		p.w("for ")
 12740  		if expr && n.Expression != nil {
 12741  			p.expression(f, n.Expression, n.Expression.Operand.Type(), exprVoid, fNoCondAssignment)
 12742  		}
 12743  		p.w("; ")
 12744  		if n.Expression2 != nil {
 12745  			p.expression(f, n.Expression2, n.Expression2.Operand.Type(), exprBool, 0)
 12746  		}
 12747  		p.w("; ")
 12748  		if n.Expression3 != nil {
 12749  			p.expression(f, n.Expression3, n.Expression3.Operand.Type(), exprVoid, fNoCondAssignment)
 12750  		}
 12751  		p.statement(f, n.Statement, true, false, false, 0)
 12752  	case cc.IterationStatementForDecl: // "for" '(' Declaration Expression ';' Expression ')' Statement
 12753  		if !(f.hasJumps || n.Expression2 != nil && n.Expression2.Case == cc.ExpressionComma) {
 12754  			p.w("{")
 12755  			p.declaration(f, n.Declaration, false)
 12756  			p.w("for ;")
 12757  			if n.Expression != nil {
 12758  				p.expression(f, n.Expression, n.Expression.Operand.Type(), exprBool, 0)
 12759  			}
 12760  			p.w(";")
 12761  			if n.Expression2 != nil {
 12762  				p.expression(f, n.Expression2, n.Expression2.Operand.Type(), exprVoid, fNoCondAssignment)
 12763  			}
 12764  			p.w("{")
 12765  			p.statement(f, n.Statement, false, true, false, 0)
 12766  			p.w("}};")
 12767  			break
 12768  		}
 12769  
 12770  		var ids []*cc.InitDeclarator
 12771  		for list := n.Declaration.InitDeclaratorList; list != nil; list = list.InitDeclaratorList {
 12772  			ids = append(ids, list.InitDeclarator)
 12773  		}
 12774  
 12775  		//	declaration
 12776  		// a:	if !expr goto c
 12777  		//	stmt
 12778  		// b: 	expr2 // label for continue
 12779  		//	goto a
 12780  		// c:
 12781  		a := f.flatLabel()
 12782  		b := f.flatLabel()
 12783  		f.continueCtx = b
 12784  		c := f.flatLabel()
 12785  		f.breakCtx = c
 12786  		p.w("{")
 12787  		p.declaration(f, n.Declaration, false)
 12788  		p.w(";")
 12789  		p.w("__%d:", a)
 12790  		if n.Expression != nil {
 12791  			p.w("if !(")
 12792  			p.expression(f, n.Expression, n.Expression.Operand.Type(), exprBool, 0)
 12793  			p.w(") { goto __%d }", c)
 12794  		}
 12795  		p.w(";")
 12796  		p.statement(f, n.Statement, false, false, false, 0)
 12797  		p.w(";goto __%d; __%[1]d:", b)
 12798  		if n.Expression2 != nil {
 12799  			p.expression(f, n.Expression2, n.Expression2.Operand.Type(), exprVoid, fNoCondAssignment)
 12800  		}
 12801  		p.w("; goto __%d; goto __%d;__%[2]d:\n}", a, c)
 12802  	default:
 12803  		panic(todo("%v: internal error: %v", n.Position(), n.Case))
 12804  	}
 12805  }
 12806  
 12807  func (p *project) selectionStatement(f *function, n *cc.SelectionStatement) {
 12808  	p.w("%s", tidyComment("\n", n))
 12809  	switch n.Case {
 12810  	case cc.SelectionStatementIf: // "if" '(' Expression ')' Statement
 12811  		sv := f.ifCtx
 12812  		f.ifCtx = n
 12813  		defer func() { f.ifCtx = sv }()
 12814  		if f.hasJumps {
 12815  			// if !expr goto a
 12816  			// stmt
 12817  			// a:
 12818  			f.ifCtx = n
 12819  			a := f.flatLabel()
 12820  			p.w("if !(")
 12821  			p.expression(f, n.Expression, n.Expression.Operand.Type(), exprBool, 0)
 12822  			p.w(") { goto __%d };", a)
 12823  			p.statement(f, n.Statement, false, false, false, 0)
 12824  			p.w(";__%d: ", a)
 12825  			break
 12826  		}
 12827  
 12828  		p.w("if ")
 12829  		p.expression(f, n.Expression, n.Expression.Operand.Type(), exprBool, 0)
 12830  		p.statement(f, n.Statement, true, false, false, 0)
 12831  	case cc.SelectionStatementIfElse: // "if" '(' Expression ')' Statement "else" Statement
 12832  		sv := f.ifCtx
 12833  		f.ifCtx = n
 12834  		defer func() { f.ifCtx = sv }()
 12835  		if f.hasJumps {
 12836  			// if !expr goto a
 12837  			// stmt
 12838  			// goto b
 12839  			// a:
 12840  			// stmt2
 12841  			// b:
 12842  			a := f.flatLabel()
 12843  			b := f.flatLabel()
 12844  			p.w("if !(")
 12845  			p.expression(f, n.Expression, n.Expression.Operand.Type(), exprBool, 0)
 12846  			p.w(") { goto __%d };", a)
 12847  			p.statement(f, n.Statement, false, false, false, 0)
 12848  			p.w(";goto __%d; __%d:", b, a)
 12849  			p.statement(f, n.Statement2, false, false, false, 0)
 12850  			p.w(";__%d:", b)
 12851  			break
 12852  		}
 12853  
 12854  		p.w("if ")
 12855  		p.expression(f, n.Expression, n.Expression.Operand.Type(), exprBool, 0)
 12856  		p.statement(f, n.Statement, true, false, false, 0)
 12857  		p.w(" else ")
 12858  		switch {
 12859  		case p.isIfStmt(n.Statement2):
 12860  			p.statement(f, n.Statement2, false, true, false, 0)
 12861  		default:
 12862  			p.statement(f, n.Statement2, true, false, false, 0)
 12863  		}
 12864  	case cc.SelectionStatementSwitch: // "switch" '(' Expression ')' Statement
 12865  		// just dont generate in this case
 12866  		if f.switchCtx == inSwitchFirst {
 12867  			break
 12868  		}
 12869  		sv := f.switchCtx
 12870  		sb := f.block
 12871  		sc := p.pauseCodegen
 12872  		svBreakCtx := f.breakCtx
 12873  		f.breakCtx = 0
 12874  		f.block = f.blocks[n.Statement.CompoundStatement]
 12875  
 12876  		defer func() {
 12877  			f.block = sb
 12878  			f.switchCtx = sv
 12879  			f.breakCtx = svBreakCtx
 12880  			p.pauseCodegen = sc
 12881  		}()
 12882  		if f.hasJumps {
 12883  			f.switchCtx = inSwitchFlat
 12884  			p.flatSwitch(f, n)
 12885  			break
 12886  		}
 12887  
 12888  		f.switchCtx = inSwitchFirst
 12889  		// fmt.Println(f.block.decls)
 12890  		if len(f.block.decls) != 0 {
 12891  			f.block.topDecl = true
 12892  			// fmt.Printf("%p:%tf\n", f.block, f.block.topDecl)
 12893  			p.w("{")
 12894  			for _, v := range f.block.decls {
 12895  				// fmt.Printf("%p:%tf\n", f.block, f.block.topDecl)
 12896  				p.declaration(f, v, true)
 12897  				// fmt.Println("done!")
 12898  			}
 12899  		}
 12900  
 12901  		p.w("switch ")
 12902  		p.expression(f, n.Expression, n.Promote(), exprValue, 0)
 12903  		p.pauseCodegen = true
 12904  		p.statement(f, n.Statement, true, false, true, 0)
 12905  		p.pauseCodegen = false
 12906  		if len(f.block.decls) != 0 {
 12907  			p.w("}")
 12908  		}
 12909  
 12910  	default:
 12911  		panic(todo("%v: internal error: %v", n.Position(), n.Case))
 12912  	}
 12913  }
 12914  
 12915  func (p *project) isIfStmt(n *cc.Statement) bool {
 12916  	if n.Case != cc.StatementSelection {
 12917  		return false
 12918  	}
 12919  
 12920  	switch n.SelectionStatement.Case {
 12921  	case cc.SelectionStatementIf, cc.SelectionStatementIfElse:
 12922  		return true
 12923  	}
 12924  
 12925  	return false
 12926  }
 12927  
 12928  func (p *project) flatSwitch(f *function, n *cc.SelectionStatement) {
 12929  	if n.Statement.Case != cc.StatementCompound {
 12930  		panic(todo("", p.pos(n)))
 12931  	}
 12932  
 12933  	sv := f.block
 12934  	f.block = f.blocks[n.Statement.CompoundStatement]
 12935  	defer func() { f.block = sv }()
 12936  	// "switch" '(' Expression ')' Statement
 12937  	cases := n.Cases()
 12938  	labels := map[*cc.LabeledStatement]int{}
 12939  	svBreakCtx := f.breakCtx
 12940  	f.breakCtx = f.flatLabel()
 12941  	p.w("switch ")
 12942  	p.expression(f, n.Expression, n.Promote(), exprValue, 0)
 12943  	p.w("{")
 12944  	for _, ls := range cases {
 12945  		switch ls.Case {
 12946  		case cc.LabeledStatementLabel: // IDENTIFIER ':' AttributeSpecifierList Statement
 12947  			continue
 12948  		case cc.LabeledStatementCaseLabel: // "case" ConstantExpression ':' Statement
 12949  			p.w("%scase ", tidyComment("\n", ls))
 12950  			p.constantExpression(f, ls.ConstantExpression, ls.ConstantExpression.Operand.Type(), exprValue, 0)
 12951  			p.w(":")
 12952  		case cc.LabeledStatementDefault: // "default" ':' Statement
 12953  			p.w("%sdefault:", tidyComment("\n", ls))
 12954  		case cc.LabeledStatementRange: // "case" ConstantExpression "..." ConstantExpression ':' Statement
 12955  			panic(todo("", p.pos(n)))
 12956  		default:
 12957  			panic(todo("%v: internal error: %v", n.Position(), n.Case))
 12958  		}
 12959  		label := f.flatLabel()
 12960  		labels[ls] = label
 12961  		p.w("goto __%d;", label)
 12962  	}
 12963  	p.w("}; goto __%d;", f.breakCtx)
 12964  	svLabels := f.flatSwitchLabels
 12965  	f.flatSwitchLabels = labels
 12966  	p.statement(f, n.Statement, false, true, false, 0)
 12967  	f.flatSwitchLabels = svLabels
 12968  	p.w("__%d:", f.breakCtx)
 12969  	f.breakCtx = svBreakCtx
 12970  }
 12971  
 12972  func (p *project) expressionStatement(f *function, n *cc.ExpressionStatement) {
 12973  	p.w("%s", tidyComment("\n", n))
 12974  	// Expression AttributeSpecifierList ';'
 12975  	if n.Expression == nil {
 12976  		return
 12977  	}
 12978  
 12979  	p.expression(f, n.Expression, n.Expression.Operand.Type(), exprVoid, 0)
 12980  }
 12981  
 12982  func (p *project) labeledStatement(f *function, n *cc.LabeledStatement) (r *cc.JumpStatement) {
 12983  	if f.hasJumps { //TODO merge with ...Flat below
 12984  		return p.labeledStatementFlat(f, n)
 12985  	}
 12986  
 12987  	switch n.Case {
 12988  	case cc.LabeledStatementLabel: // IDENTIFIER ':' AttributeSpecifierList Statement
 12989  		if _, ok := f.unusedLabels[n.Token.Value]; ok {
 12990  			p.w("goto %s;", f.labelNames[n.Token.Value])
 12991  		}
 12992  		p.w("%s%s:", comment("\n", n), f.labelNames[n.Token.Value])
 12993  		r = p.statement(f, n.Statement, false, false, false, 0)
 12994  	case
 12995  		cc.LabeledStatementCaseLabel, // "case" ConstantExpression ':' Statement
 12996  		cc.LabeledStatementDefault:   // "default" ':' Statement
 12997  
 12998  		p.labeledStatementCase(f, n)
 12999  	case cc.LabeledStatementRange: // "case" ConstantExpression "..." ConstantExpression ':' Statement
 13000  		panic(todo("", n.Position(), n.Case))
 13001  	default:
 13002  		panic(todo("%v: internal error: %v", n.Position(), n.Case))
 13003  	}
 13004  	return r
 13005  }
 13006  
 13007  func (p *project) labeledStatementFlat(f *function, n *cc.LabeledStatement) (r *cc.JumpStatement) {
 13008  	switch n.Case {
 13009  	case cc.LabeledStatementLabel: // IDENTIFIER ':' AttributeSpecifierList Statement
 13010  		if _, ok := f.unusedLabels[n.Token.Value]; ok {
 13011  			p.w("goto %s;", f.labelNames[n.Token.Value])
 13012  		}
 13013  		p.w("%s%s:", tidyComment("\n", n), f.labelNames[n.Token.Value])
 13014  		r = p.statement(f, n.Statement, false, false, false, 0)
 13015  	case
 13016  		cc.LabeledStatementCaseLabel, // "case" ConstantExpression ':' Statement
 13017  		cc.LabeledStatementDefault:   // "default" ':' Statement
 13018  
 13019  		p.labeledStatementCase(f, n)
 13020  	case cc.LabeledStatementRange: // "case" ConstantExpression "..." ConstantExpression ':' Statement
 13021  		panic(todo("", n.Position(), n.Case))
 13022  	default:
 13023  		panic(todo("%v: internal error: %v", n.Position(), n.Case))
 13024  	}
 13025  	return r
 13026  }
 13027  
 13028  func (p *project) labeledStatementCase(f *function, n *cc.LabeledStatement) {
 13029  	switch f.switchCtx {
 13030  	case inSwitchFirst:
 13031  		f.switchCtx = inSwitchCase
 13032  		p.pauseCodegen = false
 13033  	case inSwitchCase:
 13034  		p.w("\nfallthrough;")
 13035  	case inSwitchSeenBreak:
 13036  		f.switchCtx = inSwitchCase
 13037  	case inSwitchFlat:
 13038  		// ok
 13039  	default:
 13040  		panic(todo("", n.Position(), f.switchCtx))
 13041  	}
 13042  	switch n.Case {
 13043  	case cc.LabeledStatementCaseLabel: // "case" ConstantExpression ':' Statement
 13044  		switch {
 13045  		case f.switchCtx == inSwitchFlat:
 13046  			p.w("%s__%d:", tidyComment("\n", n), f.flatSwitchLabels[n])
 13047  		default:
 13048  			p.w("%scase ", tidyComment("\n", n))
 13049  			p.constantExpression(f, n.ConstantExpression, n.ConstantExpression.Operand.Type(), exprValue, 0)
 13050  			p.w(":")
 13051  		}
 13052  	case cc.LabeledStatementDefault: // "default" ':' Statement
 13053  		switch {
 13054  		case f.switchCtx == inSwitchFlat:
 13055  			p.w("%s__%d:", tidyComment("\n", n), f.flatSwitchLabels[n])
 13056  		default:
 13057  			p.w("%sdefault:", tidyComment("\n", n))
 13058  		}
 13059  	default:
 13060  		panic(todo("%v: internal error: %v", n.Position(), n.Case))
 13061  	}
 13062  	p.statement(f, n.Statement, false, false, false, 0)
 13063  }
 13064  
 13065  func (p *project) constantExpression(f *function, n *cc.ConstantExpression, t cc.Type, mode exprMode, flags flags) {
 13066  	// ConditionalExpression
 13067  	p.conditionalExpression(f, n.ConditionalExpression, t, mode, flags)
 13068  }
 13069  
 13070  func (p *project) functionDefinitionSignature(n cc.Node, f *function, tld *tld) {
 13071  	switch {
 13072  	case f.mainSignatureForced:
 13073  		p.w("%sfunc %s(%s *%sTLS, _ int32, _ uintptr) int32", tidyComment("\n", f.fndef), tld.name, f.tlsName, p.task.crt)
 13074  	default:
 13075  		p.w("%s", tidyComment("\n", f.fndef))
 13076  		p.functionSignature(n, f, f.fndef.Declarator.Type(), tld.name)
 13077  	}
 13078  }
 13079  
 13080  func (p *project) functionSignature2(n cc.Node, f *function, t cc.Type, nm string) {
 13081  	p.w("func %s", nm)
 13082  	p.w("(_ *%sTLS", p.task.crt)
 13083  	suffix := 1
 13084  	for _, v := range t.Parameters() {
 13085  		if v.Type().Kind() == cc.Void {
 13086  			break
 13087  		}
 13088  
 13089  		pn := "_"
 13090  		if d := v.Declarator(); d != nil {
 13091  			pn = d.Name().String()
 13092  			if _, ok := reservedNames[pn]; ok {
 13093  				pn += strconv.Itoa(suffix)
 13094  				suffix++
 13095  			}
 13096  		}
 13097  		p.w(", %s %s", pn, p.paramTyp(v.Declarator(), v.Type()))
 13098  	}
 13099  	if t.IsVariadic() {
 13100  		p.w(", _ /* va_list */ uintptr")
 13101  	}
 13102  	p.w(")")
 13103  	if rt := t.Result(); rt != nil && rt.Kind() != cc.Void {
 13104  		p.w(" %s", p.typ(n, rt))
 13105  	}
 13106  }
 13107  
 13108  func (p *project) functionSignature(n cc.Node, f *function, t cc.Type, nm string) {
 13109  	p.w("func")
 13110  	if nm != "" {
 13111  		p.w(" %s", nm)
 13112  	}
 13113  	switch {
 13114  	case f == nil || nm == "":
 13115  		p.w("(*%sTLS", p.task.crt)
 13116  	default:
 13117  		p.w("(%s *%sTLS", f.tlsName, p.task.crt)
 13118  	}
 13119  	for _, v := range t.Parameters() {
 13120  		if v.Type().Kind() == cc.Void {
 13121  			break
 13122  		}
 13123  
 13124  		var pn string
 13125  		if f != nil && nm != "" {
 13126  			pn = "_"
 13127  			if d := v.Declarator(); d != nil {
 13128  				if local := f.locals[d]; local != nil {
 13129  					pn = local.name
 13130  				}
 13131  			}
 13132  		}
 13133  		p.w(", %s %s", pn, p.paramTyp(v.Declarator(), v.Type()))
 13134  	}
 13135  	if t.IsVariadic() {
 13136  		switch {
 13137  		case f == nil || nm == "":
 13138  			p.w(", uintptr")
 13139  		default:
 13140  			p.w(", %s uintptr", f.vaName)
 13141  		}
 13142  	}
 13143  	p.w(")")
 13144  	if rt := t.Result(); rt != nil && rt.Kind() != cc.Void {
 13145  		p.w(" %s", p.typ(n, rt))
 13146  	}
 13147  }
 13148  
 13149  func (p *project) paramTyp(n cc.Node, t cc.Type) string {
 13150  	if t.Kind() == cc.Array {
 13151  		return "uintptr"
 13152  	}
 13153  
 13154  	if isTransparentUnion(t) {
 13155  		switch k := t.UnionCommon(); k {
 13156  		case cc.Ptr:
 13157  			return "uintptr"
 13158  		default:
 13159  			panic(todo("%v: %v %k", n, t, k))
 13160  		}
 13161  	}
 13162  
 13163  	return p.typ(n, t)
 13164  }
 13165  
 13166  func (p *project) dbg(a ...interface{}) {
 13167  	p.w("/*DBG.%v %v */", a, origin(2))
 13168  }
 13169  
 13170  func (p *project) fnVal(n cc.Node, f *function, expr func(), exprDecl *cc.Declarator, exprType cc.Type, deref int, mode exprMode, flags flags) {
 13171  	//  C type		Go type
 13172  	//  fn			N/A: produce name from exprDecl
 13173  	//  (*)()		func()
 13174  	//  (**)()		*func()
 13175  
 13176  	if deref < 0 || deref > 1 {
 13177  		panic(todo(""))
 13178  	}
 13179  
 13180  	switch exprType.Kind() {
 13181  	case cc.Function:
 13182  		// C: fn
 13183  		switch deref {
 13184  		case 0:
 13185  			p.declarator(n, f, exprDecl, exprType, mode, flags)
 13186  		default:
 13187  			panic(todo("", n.Position()))
 13188  		}
 13189  	case cc.Ptr:
 13190  		switch et := exprType.Elem(); et.Kind() {
 13191  		case cc.Function:
 13192  			// C: (*)()
 13193  			switch deref {
 13194  			case 0:
 13195  				// (*struct{ f func()})(unsafe.Pointer(&struct{uintptr}{fprintfptr})).f()
 13196  				p.w("(*struct{ f ")
 13197  				p.functionSignature(n, f, et, "")
 13198  				p.w("})(unsafe.Pointer(&struct{uintptr}{")
 13199  				expr()
 13200  				p.w("})).f")
 13201  			default:
 13202  				p.declarator(n, f, exprDecl, et, mode, flags)
 13203  			}
 13204  		case cc.Ptr:
 13205  			switch et2 := et.Elem(); et2.Kind() {
 13206  			case cc.Function:
 13207  				// C: (**)()
 13208  				switch deref {
 13209  				case 0:
 13210  					panic(todo("", n.Position()))
 13211  				default:
 13212  					// (*struct{ f func()})(unsafe.Pointer(&struct{uintptr}{fprintfptr})).f()
 13213  					p.w("(*(**struct{ f ")
 13214  					p.functionSignature(n, f, et2, "")
 13215  					p.w("})(unsafe.Pointer(&struct{uintptr}{")
 13216  					expr()
 13217  					p.w("}))).f")
 13218  				}
 13219  			default:
 13220  				panic(todo("", n.Position(), et2.Kind(), deref))
 13221  			}
 13222  		default:
 13223  			panic(todo("", n.Position(), et.Kind(), deref))
 13224  		}
 13225  	default:
 13226  		panic(todo("", n.Position(), exprType.Kind(), deref))
 13227  	}
 13228  }