go.go (413952B)
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 ) 114 115 type imported struct { 116 path string // Eg. "example.com/user/foo". 117 name string // Eg. "foo" from "package foo". 118 qualifier string // Eg. "foo." or "foo2." if renamed due to name conflict. 119 exports map[string]struct{} // Eg. {"New": {}, "Close": {}, ...}. 120 121 used bool 122 } 123 124 type taggedStruct struct { 125 ctyp cc.Type 126 gotyp string 127 name string 128 node cc.Node 129 130 conflicts bool 131 emitted bool 132 } 133 134 func (s *taggedStruct) emit(p *project, ds *cc.DeclarationSpecifiers) { 135 if s == nil || s.emitted { 136 return 137 } 138 139 s.emitted = true 140 p.w("%stype %s = %s; /* %v */\n\n", tidyComment("\n", ds), s.name, s.gotyp, p.pos(s.node)) 141 } 142 143 // Return first non empty token separator within n or dflt otherwise. 144 func comment(dflt string, n cc.Node) string { 145 if s := tokenSeparator(n); s != "" { 146 return s 147 } 148 149 return dflt 150 } 151 152 // tidyComment is like comment but makes comment more Go-like. 153 func tidyComment(dflt string, n cc.Node) (r string) { return tidyCommentString(comment(dflt, n)) } 154 155 func tidyCommentString(s string) (r string) { 156 defer func() { 157 if !strings.Contains(r, "// <blockquote><pre>") { 158 return 159 } 160 161 a := strings.Split(r, "\n") 162 in := false 163 for i, v := range a { 164 switch { 165 case in: 166 if strings.HasPrefix(v, "// </pre></blockquote>") { 167 in = false 168 a[i] = "//" 169 break 170 } 171 172 a[i] = fmt.Sprintf("//\t%s", v[3:]) 173 default: 174 if strings.HasPrefix(v, "// <blockquote><pre>") { 175 a[i] = "//" 176 in = true 177 } 178 } 179 } 180 r = strings.Join(a, "\n") 181 }() 182 183 s = strings.ReplaceAll(s, "\f", "") 184 b := bytesBufferPool.Get().(*bytes.Buffer) 185 defer func() { b.Reset(); bytesBufferPool.Put(b) }() 186 for len(s) != 0 { 187 c := s[0] 188 s = s[1:] 189 if len(s) == 0 { 190 b.WriteByte(c) 191 break 192 } 193 194 if c != '/' { 195 b.WriteByte(c) 196 continue 197 } 198 199 c2 := s[0] 200 s = s[1:] 201 switch c2 { 202 case '/': // line comment start 203 b.WriteByte(c) 204 b.WriteByte(c2) 205 for { 206 c := s[0] 207 s = s[1:] 208 b.WriteByte(c) 209 if c == '\n' { 210 break 211 } 212 } 213 case '*': // block comment start 214 b2 := bytesBufferPool.Get().(*bytes.Buffer) 215 defer func() { b2.Reset(); bytesBufferPool.Put(b2) }() 216 for { 217 c := s[0] 218 s = s[1:] 219 if c != '*' { 220 b2.WriteByte(c) 221 continue 222 } 223 224 more: 225 c2 := s[0] 226 s = s[1:] 227 if c2 == '*' { 228 b2.WriteByte(c) 229 goto more 230 } 231 232 if c2 != '/' { 233 b2.WriteByte(c) 234 b2.WriteByte(c2) 235 continue 236 } 237 238 break 239 } 240 s2 := b2.String() // comment sans /* prefix and */ suffix 241 a := strings.Split(s2, "\n") 242 nl := len(s) != 0 && s[0] == '\n' 243 if len(a) == 1 { // /* foo */ form 244 if nl { 245 s = s[1:] 246 fmt.Fprintf(b, "//%s\n", s2) 247 break 248 } 249 250 fmt.Fprintf(b, "/*%s*/", s2) 251 break 252 } 253 254 if !nl { 255 fmt.Fprintf(b, "/*%s*/", s2) 256 break 257 } 258 259 // Block comment followed by a newline can be safely replaced by a sequence of 260 // line comments. Try to enhance the comment. 261 if commentForm1(b, a) || 262 commentForm2(b, a) || 263 commentForm3(b, a) { 264 break 265 } 266 267 // No enhancement posibilities detected, use the default form. 268 if a[len(a)-1] == "" { 269 a = a[:len(a)-1] 270 } 271 fmt.Fprintf(b, "//%s", a[0]) 272 for _, v := range a[1:] { 273 fmt.Fprintf(b, "\n// %s", v) 274 } 275 default: 276 b.WriteByte(c) 277 b.WriteByte(c2) 278 } 279 } 280 return b.String() 281 } 282 283 func commentForm1(b *bytes.Buffer, a []string) bool { 284 // Example 285 // 286 // /* 287 // ** Initialize this module. 288 // ** 289 // ** This Tcl module contains only a single new Tcl command named "sqlite". 290 // ** (Hence there is no namespace. There is no point in using a namespace 291 // ** if the extension only supplies one new name!) The "sqlite" command is 292 // ** used to open a new SQLite database. See the DbMain() routine above 293 // ** for additional information. 294 // ** 295 // ** The EXTERN macros are required by TCL in order to work on windows. 296 // */ 297 if strings.TrimSpace(a[0]) != "" { 298 return false 299 } 300 301 if strings.TrimSpace(a[len(a)-1]) != "" { 302 return false 303 } 304 305 a = a[1 : len(a)-1] 306 if len(a) == 0 { 307 return false 308 } 309 310 for i, v := range a { 311 v = strings.TrimSpace(v) 312 if !strings.HasPrefix(v, "*") { 313 return false 314 } 315 316 a[i] = strings.TrimLeft(v, "*") 317 } 318 319 fmt.Fprintf(b, "//%s", a[0]) 320 for _, v := range a[1:] { 321 fmt.Fprintf(b, "\n//%s", v) 322 } 323 return true 324 } 325 326 func commentForm2(b *bytes.Buffer, a []string) bool { 327 // Example 328 // 329 // /**************************** sqlite3_column_ ******************************* 330 // ** The following routines are used to access elements of the current row 331 // ** in the result set. 332 // */ 333 if strings.TrimSpace(a[len(a)-1]) != "" { 334 return false 335 } 336 337 a = a[:len(a)-1] 338 if len(a) == 0 { 339 return false 340 } 341 342 for i, v := range a[1:] { 343 v = strings.TrimSpace(v) 344 if !strings.HasPrefix(v, "*") { 345 return false 346 } 347 348 a[i+1] = strings.TrimLeft(v, "*") 349 } 350 351 fmt.Fprintf(b, "// %s", strings.TrimSpace(a[0])) 352 if strings.HasPrefix(a[0], "**") && strings.HasSuffix(a[0], "**") { 353 fmt.Fprintf(b, "\n//") 354 } 355 for _, v := range a[1:] { 356 fmt.Fprintf(b, "\n//%s", v) 357 } 358 return true 359 } 360 361 func commentForm3(b *bytes.Buffer, a []string) bool { 362 // Example 363 // 364 // /* Call sqlite3_shutdown() once before doing anything else. This is to 365 // ** test that sqlite3_shutdown() can be safely called by a process before 366 // ** sqlite3_initialize() is. */ 367 for i, v := range a[1:] { 368 v = strings.TrimSpace(v) 369 if !strings.HasPrefix(v, "*") { 370 return false 371 } 372 373 a[i+1] = strings.TrimLeft(v, "*") 374 } 375 376 fmt.Fprintf(b, "// %s", strings.TrimSpace(a[0])) 377 if strings.HasPrefix(a[0], "**") && strings.HasSuffix(a[0], "**") { 378 fmt.Fprintf(b, "\n//") 379 } 380 for _, v := range a[1:] { 381 fmt.Fprintf(b, "\n//%s", v) 382 } 383 return true 384 } 385 386 // Return the preceding white space, including any comments, of the first token 387 // of n. 388 func tokenSeparator(n cc.Node) (r string) { 389 if n == nil { 390 return "" 391 } 392 393 var tok cc.Token 394 cc.Inspect(n, func(n cc.Node, _ bool) bool { 395 if x, ok := n.(*cc.Token); ok { 396 if a, b := tok.Seq(), x.Seq(); a == 0 || a > x.Seq() && b != 0 { 397 tok = *x 398 } 399 } 400 return true 401 }) 402 return tok.Sep.String() 403 } 404 405 func source(n ...cc.Node) (r string) { 406 if len(n) == 0 { 407 return "<nil>" 408 } 409 410 var a []*cc.Token 411 for _, v := range n { 412 cc.Inspect(v, func(n cc.Node, _ bool) bool { 413 if x, ok := n.(*cc.Token); ok && x.Seq() != 0 { 414 a = append(a, x) 415 } 416 return true 417 }) 418 } 419 sort.Slice(a, func(i, j int) bool { 420 return a[i].Seq() < a[j].Seq() 421 }) 422 w := 0 423 seq := -1 424 for _, v := range a { 425 if n := v.Seq(); n != seq { 426 seq = n 427 a[w] = v 428 w++ 429 } 430 } 431 a = a[:w] 432 var b strings.Builder 433 for _, v := range a { 434 b.WriteString(v.Sep.String()) 435 b.WriteString(v.Src.String()) 436 } 437 return b.String() 438 } 439 440 type initPatch struct { 441 t cc.Type 442 init *cc.Initializer 443 fld cc.Field 444 } 445 446 type tld struct { 447 name string // Can differ from the original one. 448 patches []initPatch 449 } 450 451 type block struct { 452 block *cc.CompoundStatement 453 decls []*cc.Declaration // What to declare in this block. 454 params []*cc.Parameter 455 parent *block 456 scope scope 457 458 noDecl bool // Locals declared in one of the parent scopes. 459 topDecl bool // Declare locals at block start to avoid "jumps over declaration". 460 } 461 462 func newBlock(parent *block, n *cc.CompoundStatement, decls []*cc.Declaration, params []*cc.Parameter, scope scope, topDecl bool) *block { 463 return &block{ 464 block: n, 465 decls: decls, 466 params: params, 467 parent: parent, 468 scope: scope, 469 topDecl: topDecl, 470 } 471 } 472 473 type local struct { 474 name string 475 off uintptr // If isPinned: bp+off 476 477 forceRead bool // Possibly never read. 478 isPinned bool // Prevent this local from being placed in Go movable stack. 479 } 480 481 type switchState int 482 483 const ( 484 _ switchState = iota // Not in switch. 485 inSwitchFirst // Before seeing "case/default". 486 inSwitchCase // Seen "case/default". 487 inSwitchSeenBreak // In switch "case/default" and seen "break/return". 488 inSwitchFlat 489 ) 490 491 type function struct { 492 block *block 493 blocks map[*cc.CompoundStatement]*block 494 bpName string 495 breakCtx int //TODO merge with continueCtx 496 complits map[*cc.PostfixExpression]uintptr 497 condInitPrefix func() 498 continueCtx int 499 flatLabels int 500 flatSwitchLabels map[*cc.LabeledStatement]int 501 fndef *cc.FunctionDefinition 502 gen *project 503 ifCtx cc.Node 504 ignore map[*cc.Declarator]bool // Pseudo declarators 505 labelNames map[cc.StringID]string 506 labels scope 507 locals map[*cc.Declarator]*local 508 off uintptr // bp+off allocs 509 params []*cc.Parameter // May differ from what fndef says 510 project *project 511 rt cc.Type // May differ from what fndef says 512 scope scope 513 switchCtx switchState 514 tlsName string 515 top *block 516 unusedLabels map[cc.StringID]struct{} 517 vaLists map[*cc.PostfixExpression]uintptr 518 vaName string 519 vaType cc.Type 520 vlas map[*cc.Declarator]struct{} 521 522 hasJumps bool 523 mainSignatureForced bool 524 } 525 526 func newFunction(p *project, n *cc.FunctionDefinition) *function { 527 d := n.Declarator 528 t := d.Type() 529 rt := t.Result() 530 params := t.Parameters() 531 var mainSignatureForced bool 532 var ignore map[*cc.Declarator]bool 533 if d.Name() == idMain && d.Linkage == cc.External { 534 if rt.Kind() != cc.Int { 535 rt = p.task.cfg.ABI.Type(cc.Int) 536 } 537 if len(params) != 2 { 538 mainSignatureForced = true 539 d1 := newDeclarator("argc") 540 t1 := p.task.cfg.ABI.Type(cc.Int) 541 d2 := newDeclarator("argv") 542 t2 := p.task.cfg.ABI.Ptr(n, p.task.cfg.ABI.Type(cc.Void)) 543 params = []*cc.Parameter{ 544 cc.NewParameter(d1, t1), 545 cc.NewParameter(d2, t2), 546 } 547 ignore = map[*cc.Declarator]bool{d1: true, d2: true} 548 } 549 } 550 f := &function{ 551 blocks: map[*cc.CompoundStatement]*block{}, 552 complits: map[*cc.PostfixExpression]uintptr{}, 553 fndef: n, 554 gen: p, 555 hasJumps: n.CompoundStatement.IsJumpTarget(), 556 ignore: ignore, 557 locals: map[*cc.Declarator]*local{}, 558 mainSignatureForced: mainSignatureForced, 559 params: params, 560 project: p, 561 rt: rt, 562 scope: p.newScope(), 563 unusedLabels: map[cc.StringID]struct{}{}, 564 vaLists: map[*cc.PostfixExpression]uintptr{}, 565 vlas: map[*cc.Declarator]struct{}{}, 566 } 567 f.tlsName = f.scope.take(idTls) 568 if t.IsVariadic() { 569 f.vaName = f.scope.take(idVa) 570 } 571 f.layoutLocals(nil, n.CompoundStatement, params) 572 var extern []cc.StringID 573 for _, v := range n.CompoundStatements() { // testdata/gcc-9.1.0/gcc/testsuite/gcc.c-torture/execute/scope-1.c 574 for _, v := range v.Declarations() { 575 for list := v.InitDeclaratorList; list != nil; list = list.InitDeclaratorList { 576 if d := list.InitDeclarator.Declarator; d != nil && d.IsExtern() { 577 extern = append(extern, d.Name()) 578 } 579 } 580 } 581 } 582 for _, v := range n.CompoundStatements() { 583 block := f.blocks[v] 584 for _, v := range extern { 585 if tld := f.project.externs[v]; tld != nil { 586 block.scope.take(cc.String(tld.name)) 587 } 588 } 589 } 590 for _, v := range n.CompoundStatements() { 591 f.layoutBlocks(v) 592 } 593 f.renameLabels() 594 f.staticAllocsAndPinned(n.CompoundStatement) 595 return f 596 } 597 598 func (f *function) flatLabel() int { 599 if f.project.pass1 { 600 return 1 601 } 602 603 f.flatLabels++ 604 return f.flatLabels 605 } 606 607 func (f *function) renameLabels() { 608 var a []cc.StringID 609 for _, v := range f.fndef.Labels { 610 if v.Case != cc.LabeledStatementLabel { 611 continue 612 } 613 614 a = append(a, v.Token.Value) 615 f.unusedLabels[v.Token.Value] = struct{}{} 616 } 617 for _, v := range f.fndef.Gotos { 618 delete(f.unusedLabels, v.Token2.Value) 619 } 620 if len(a) == 0 { 621 return 622 } 623 sort.Slice(a, func(i, j int) bool { return a[i].String() < a[j].String() }) 624 f.labels = newScope() 625 f.labelNames = map[cc.StringID]string{} 626 for _, id := range a { 627 f.labelNames[id] = f.labels.take(id) 628 } 629 } 630 631 func (f *function) staticAllocsAndPinned(n *cc.CompoundStatement) { 632 for _, v := range f.params { 633 switch { 634 case v.Type().Kind() == cc.Array && v.Type().IsVLA(): 635 // trc("VLA") 636 f.project.err(f.fndef, "variable length arrays not supported") 637 } 638 } 639 640 //TODO use pass1 for this 641 cc.Inspect(n, func(n cc.Node, entry bool) bool { 642 if !entry { 643 return true 644 } 645 646 switch x := n.(type) { 647 case *cc.CastExpression: 648 switch x.Case { 649 case cc.CastExpressionCast: // '(' TypeName ')' CastExpression 650 if t := x.TypeName.Type(); t != nil && t.Kind() != cc.Void { 651 break 652 } 653 654 if d := x.CastExpression.Declarator(); d != nil { 655 if local := f.locals[d]; local != nil { 656 local.forceRead = true 657 } 658 } 659 } 660 } 661 662 x, ok := n.(*cc.PostfixExpression) 663 if !ok || x.Case != cc.PostfixExpressionCall { 664 return true 665 } 666 667 if x.PostfixExpression == nil || x.PostfixExpression.Operand == nil || x.PostfixExpression.Operand.Type() == nil { 668 return true 669 } 670 671 ft := funcType(x.PostfixExpression.Operand.Type()) 672 if ft.Kind() != cc.Function { 673 return true 674 } 675 676 if !ft.IsVariadic() { 677 return true 678 } 679 680 fixedParams := len(ft.Parameters()) 681 iArg := 0 682 var need uintptr 683 for list := x.ArgumentExpressionList; list != nil; list, iArg = list.ArgumentExpressionList, iArg+1 { 684 if iArg < fixedParams { 685 continue 686 } 687 688 t := list.AssignmentExpression.Operand.Type() 689 if t.IsIntegerType() { 690 need += 8 691 continue 692 } 693 694 switch t.Kind() { 695 case cc.Array, cc.Ptr, cc.Double, cc.Float, cc.Function: 696 need += 8 697 default: 698 panic(todo("", f.project.pos(x), t, t.Kind())) 699 } 700 } 701 if need != 0 { 702 //TODO- if f.project.task.mingw { 703 //TODO- need += 8 // On windows the va list is prefixed with its length 704 //TODO- } 705 va := roundup(f.off, 8) 706 f.vaLists[x] = va 707 f.off = va + need 708 } 709 return true 710 }) 711 } 712 713 func funcType(t cc.Type) cc.Type { 714 if t.Kind() == cc.Ptr { 715 t = t.Elem() 716 } 717 return t 718 } 719 720 type declarator interface { 721 Declarator() *cc.Declarator 722 cc.Node 723 } 724 725 func (p *project) isArrayParameterDeclarator(d *cc.Declarator) bool { 726 if d.Type().Kind() == cc.Array { 727 if d.Type().IsVLA() { 728 return false 729 } 730 731 return d.IsParameter 732 } 733 734 return false 735 } 736 737 func (p *project) isArrayDeclarator(d *cc.Declarator) bool { 738 if d.Type().Kind() == cc.Array { 739 if d.Type().IsVLA() { 740 return false 741 } 742 743 return !d.IsParameter 744 } 745 746 return false 747 } 748 749 func (p *project) isArrayParameter(n declarator, t cc.Type) bool { 750 if t.Kind() != cc.Array { 751 return false 752 } 753 754 if t.IsVLA() { 755 return false 756 } 757 758 if d := n.Declarator(); d != nil { 759 return d.IsParameter 760 } 761 762 return false 763 } 764 765 func (p *project) isArrayOrPinnedArray(f *function, n declarator, t cc.Type) (r bool) { 766 if t.Kind() != cc.Array { 767 return false 768 } 769 770 if t.IsVLA() { 771 return false 772 } 773 774 if d := n.Declarator(); d != nil { 775 return !d.IsParameter 776 } 777 778 return p.detectArray(f, n.(cc.Node), true, true, nil) 779 } 780 781 func (p *project) detectArray(f *function, n cc.Node, pinnedOk, recursiveOk bool, out **cc.Declarator) bool { 782 switch x := n.(type) { 783 case *cc.AssignmentExpression: 784 switch x.Case { 785 case cc.AssignmentExpressionCond: // ConditionalExpression 786 return p.detectArray(f, x.ConditionalExpression, pinnedOk, recursiveOk, out) 787 case cc.AssignmentExpressionAssign: // UnaryExpression '=' AssignmentExpression 788 return p.detectArray(f, x.UnaryExpression, pinnedOk, recursiveOk, out) 789 default: 790 return false 791 } 792 case *cc.ConditionalExpression: 793 switch x.Case { 794 case cc.ConditionalExpressionLOr: // LogicalOrExpression 795 return p.detectArray(f, x.LogicalOrExpression, pinnedOk, recursiveOk, out) 796 case cc.ConditionalExpressionCond: // LogicalOrExpression '?' Expression ':' ConditionalExpression 797 return p.detectArray(f, x.LogicalOrExpression, pinnedOk, recursiveOk, out) || 798 p.detectArray(f, x.Expression, pinnedOk, recursiveOk, out) || 799 p.detectArray(f, x.ConditionalExpression, pinnedOk, recursiveOk, out) 800 default: 801 panic(todo("", p.pos(x), x.Case)) 802 } 803 case *cc.LogicalOrExpression: 804 switch x.Case { 805 case cc.LogicalOrExpressionLAnd: // LogicalAndExpression 806 return p.detectArray(f, x.LogicalAndExpression, pinnedOk, recursiveOk, out) 807 default: 808 return false 809 } 810 case *cc.LogicalAndExpression: 811 switch x.Case { 812 case cc.LogicalAndExpressionOr: // InclusiveOrExpression 813 return p.detectArray(f, x.InclusiveOrExpression, pinnedOk, recursiveOk, out) 814 default: 815 return false 816 } 817 case *cc.InclusiveOrExpression: 818 switch x.Case { 819 case cc.InclusiveOrExpressionXor: // ExclusiveOrExpression 820 return p.detectArray(f, x.ExclusiveOrExpression, pinnedOk, recursiveOk, out) 821 default: 822 return false 823 } 824 case *cc.ExclusiveOrExpression: 825 switch x.Case { 826 case cc.ExclusiveOrExpressionAnd: // AndExpression 827 return p.detectArray(f, x.AndExpression, pinnedOk, recursiveOk, out) 828 default: 829 return false 830 } 831 case *cc.AndExpression: 832 switch x.Case { 833 case cc.AndExpressionEq: // EqualityExpression 834 return p.detectArray(f, x.EqualityExpression, pinnedOk, recursiveOk, out) 835 default: 836 return false 837 } 838 case *cc.EqualityExpression: 839 switch x.Case { 840 case cc.EqualityExpressionRel: // RelationalExpression 841 return p.detectArray(f, x.RelationalExpression, pinnedOk, recursiveOk, out) 842 default: 843 return false 844 } 845 case *cc.RelationalExpression: 846 switch x.Case { 847 case cc.RelationalExpressionShift: // ShiftExpression 848 return p.detectArray(f, x.ShiftExpression, pinnedOk, recursiveOk, out) 849 default: 850 return false 851 } 852 case *cc.ShiftExpression: 853 switch x.Case { 854 case cc.ShiftExpressionAdd: // AdditiveExpression 855 return p.detectArray(f, x.AdditiveExpression, pinnedOk, recursiveOk, out) 856 default: 857 return false 858 } 859 case *cc.AdditiveExpression: 860 switch x.Case { 861 case cc.AdditiveExpressionMul: // MultiplicativeExpression 862 return p.detectArray(f, x.MultiplicativeExpression, pinnedOk, recursiveOk, out) 863 case 864 cc.AdditiveExpressionSub, // AdditiveExpression '-' MultiplicativeExpression 865 cc.AdditiveExpressionAdd: // AdditiveExpression '+' MultiplicativeExpression 866 867 return p.detectArray(f, x.AdditiveExpression, pinnedOk, recursiveOk, out) || p.detectArray(f, x.MultiplicativeExpression, pinnedOk, recursiveOk, out) 868 default: 869 panic(todo("", p.pos(x), x.Case)) 870 } 871 case *cc.MultiplicativeExpression: 872 switch x.Case { 873 case cc.MultiplicativeExpressionCast: // CastExpression 874 return p.detectArray(f, x.CastExpression, pinnedOk, recursiveOk, out) 875 default: 876 return false 877 } 878 case *cc.CastExpression: 879 switch x.Case { 880 case cc.CastExpressionUnary: // UnaryExpression 881 return p.detectArray(f, x.UnaryExpression, pinnedOk, recursiveOk, out) 882 case cc.CastExpressionCast: // '(' TypeName ')' CastExpression 883 return p.detectArray(f, x.CastExpression, pinnedOk, recursiveOk, out) 884 default: 885 panic(todo("", p.pos(x), x.Case)) 886 } 887 case *cc.UnaryExpression: 888 switch x.Case { 889 case cc.UnaryExpressionPostfix: // PostfixExpression 890 return p.detectArray(f, x.PostfixExpression, pinnedOk, recursiveOk, out) 891 case 892 cc.UnaryExpressionDeref, // '*' CastExpression 893 cc.UnaryExpressionAddrof: // '&' CastExpression 894 895 return p.detectArray(f, x.CastExpression, pinnedOk, recursiveOk, out) 896 case 897 cc.UnaryExpressionSizeofExpr, // "sizeof" UnaryExpression 898 cc.UnaryExpressionSizeofType, // "sizeof" '(' TypeName ')' 899 cc.UnaryExpressionMinus, // '-' CastExpression 900 cc.UnaryExpressionCpl, // '~' CastExpression 901 cc.UnaryExpressionAlignofExpr, // "_Alignof" UnaryExpression 902 cc.UnaryExpressionAlignofType, // "_Alignof" '(' TypeName ')' 903 cc.UnaryExpressionNot, // '!' CastExpression 904 cc.UnaryExpressionInc, // "++" UnaryExpression 905 cc.UnaryExpressionDec, // "--" UnaryExpression 906 cc.UnaryExpressionPlus: // '+' CastExpression 907 908 return false 909 default: 910 panic(todo("", p.pos(x), x.Case)) 911 } 912 case *cc.PostfixExpression: 913 switch x.Case { 914 case cc.PostfixExpressionPrimary: // PrimaryExpression 915 return p.detectArray(f, x.PrimaryExpression, pinnedOk, recursiveOk, out) 916 case cc.PostfixExpressionIndex: // PostfixExpression '[' Expression ']' 917 return recursiveOk && p.detectArray(f, x.PostfixExpression, pinnedOk, recursiveOk, out) 918 case 919 cc.PostfixExpressionSelect, // PostfixExpression '.' IDENTIFIER 920 cc.PostfixExpressionDec, // PostfixExpression "--" 921 cc.PostfixExpressionInc, // PostfixExpression "++" 922 cc.PostfixExpressionCall, // PostfixExpression '(' ArgumentExpressionList ')' 923 cc.PostfixExpressionComplit, // '(' TypeName ')' '{' InitializerList ',' '}' 924 cc.PostfixExpressionPSelect: // PostfixExpression "->" IDENTIFIER 925 926 return false 927 default: 928 panic(todo("", p.pos(x), x.Case)) 929 } 930 case *cc.PrimaryExpression: 931 switch x.Case { 932 case 933 cc.PrimaryExpressionString, // STRINGLITERAL 934 cc.PrimaryExpressionEnum, // ENUMCONST 935 cc.PrimaryExpressionChar, // CHARCONST 936 cc.PrimaryExpressionLChar, // LONGCHARCONST 937 cc.PrimaryExpressionLString, // LONGSTRINGLITERAL 938 cc.PrimaryExpressionFloat, // FLOATCONST 939 cc.PrimaryExpressionInt: // INTCONST 940 941 return false 942 case cc.PrimaryExpressionIdent: // IDENTIFIER 943 d := x.Declarator() 944 if d == nil || d.IsParameter { 945 return false 946 } 947 948 if d.Type().Kind() != cc.Array { 949 return false 950 } 951 952 if d.Type().IsVLA() { 953 return false 954 } 955 956 if pinnedOk { 957 if out != nil { 958 *out = d 959 } 960 return true 961 } 962 963 local := f.locals[d] 964 if local == nil || local.isPinned { 965 return false 966 } 967 968 if out != nil { 969 *out = d 970 } 971 return true 972 case cc.PrimaryExpressionExpr: // '(' Expression ')' 973 return p.detectArray(f, x.Expression, pinnedOk, recursiveOk, out) 974 case cc.PrimaryExpressionStmt: // '(' CompoundStatement ')' 975 p.err(x, "statement expressions not supported") 976 return false 977 default: 978 panic(todo("", p.pos(x), x.Case)) 979 } 980 case *cc.Expression: 981 switch x.Case { 982 case cc.ExpressionAssign: // AssignmentExpression 983 return p.detectArray(f, x.AssignmentExpression, pinnedOk, recursiveOk, out) 984 case cc.ExpressionComma: // Expression ',' AssignmentExpression 985 return p.detectArray(f, x.Expression, pinnedOk, recursiveOk, out) || p.detectArray(f, x.AssignmentExpression, pinnedOk, recursiveOk, out) 986 default: 987 panic(todo("", p.pos(x), x.Case)) 988 } 989 default: 990 panic(todo("%T", x)) 991 } 992 } 993 994 func (p *project) isArray(f *function, n declarator, t cc.Type) (r bool) { 995 if t.Kind() != cc.Array { 996 return false 997 } 998 999 if t.IsVLA() { 1000 return false 1001 } 1002 1003 if f == nil { 1004 return true 1005 } 1006 1007 if d := n.Declarator(); d != nil { 1008 local := f.locals[d] 1009 return !d.IsParameter && (local == nil || !local.isPinned) 1010 } 1011 1012 return p.detectArray(f, n.(cc.Node), false, true, nil) 1013 } 1014 1015 var home = os.Getenv("HOME") 1016 1017 // Return n's position with path reduced to baseName(path) unless 1018 // p.task.fullPathComments is true. 1019 func (p *project) pos(n cc.Node) (r token.Position) { 1020 if n == nil { 1021 return r 1022 } 1023 1024 if r = token.Position(n.Position()); r.IsValid() { 1025 switch { 1026 case p.task.fullPathComments: 1027 if strings.HasPrefix(r.Filename, home) { 1028 r.Filename = "$HOME" + r.Filename[len(home):] 1029 } 1030 default: 1031 r.Filename = filepath.Base(r.Filename) 1032 } 1033 } 1034 return r 1035 } 1036 1037 // Return n's position with path reduced to baseName(path). 1038 func pos(n cc.Node) (r token.Position) { 1039 if n == nil { 1040 return r 1041 } 1042 1043 r = token.Position(n.Position()) 1044 if r.IsValid() { 1045 r.Filename = filepath.Base(r.Filename) 1046 } 1047 return r 1048 } 1049 1050 func roundup(n, to uintptr) uintptr { 1051 if r := n % to; r != 0 { 1052 return n + to - r 1053 } 1054 1055 return n 1056 } 1057 1058 func (f *function) pin(n cc.Node, d *cc.Declarator) { 1059 local := f.locals[d] 1060 if local == nil || local.isPinned { 1061 return 1062 } 1063 1064 local.isPinned = true 1065 if oTracePin || f.project.task.tracePinning { 1066 fmt.Printf("%v: %s at %v: is pinned (%v)\n", n.Position(), d.Name(), d.Position(), origin(2)) 1067 } 1068 local.off = roundup(f.off, uintptr(d.Type().Align())) 1069 f.off = local.off + paramTypeDecay(d).Size() 1070 } 1071 1072 func paramTypeDecay(d *cc.Declarator) (r cc.Type) { 1073 r = d.Type() 1074 if d.IsParameter && r.Kind() == cc.Array { 1075 r = r.Decay() 1076 } 1077 return r 1078 } 1079 1080 func (f *function) layoutBlocks(n *cc.CompoundStatement) { 1081 block := f.blocks[n] 1082 type item struct { 1083 ds *cc.DeclarationSpecifiers 1084 d *cc.Declarator 1085 } 1086 var work []item 1087 for _, v := range block.params { 1088 if v.Type().Kind() == cc.Void { 1089 break 1090 } 1091 1092 work = append(work, item{nil, v.Declarator()}) 1093 } 1094 for _, decl := range block.decls { 1095 ds := decl.DeclarationSpecifiers 1096 for list := decl.InitDeclaratorList; list != nil; list = list.InitDeclaratorList { 1097 work = append(work, item{ds, list.InitDeclarator.Declarator}) 1098 } 1099 } 1100 block.scope.take(cc.String(f.tlsName)) 1101 if f.vaName != "" { 1102 block.scope.take(cc.String(f.vaName)) 1103 } 1104 for _, item := range work { 1105 d := item.d 1106 if f.ignore[d] { 1107 continue 1108 } 1109 1110 if !f.ignore[d] && d.IsStatic() { 1111 continue 1112 } 1113 1114 if d.IsFunctionPrototype() || d.IsExtern() { 1115 continue 1116 } 1117 1118 local := &local{forceRead: d.Read == 0} 1119 if t := d.Type(); t != nil && t.Name() == idVaList { 1120 local.forceRead = true 1121 } 1122 f.locals[d] = local 1123 local.name = block.scope.take(d.Name()) 1124 } 1125 } 1126 1127 func (f *function) layoutLocals(parent *block, n *cc.CompoundStatement, params []*cc.Parameter) { 1128 block := newBlock(parent, n, n.Declarations(), params, f.project.newScope(), n.IsJumpTarget()) 1129 f.blocks[n] = block 1130 if parent == nil { 1131 f.top = block 1132 f.top.topDecl = f.hasJumps 1133 } 1134 for _, ch := range n.Children() { 1135 f.layoutLocals(block, ch, nil) 1136 if f.hasJumps { 1137 chb := f.blocks[ch] 1138 chb.noDecl = true 1139 f.top.decls = append(f.top.decls, chb.decls...) 1140 chb.decls = nil 1141 } 1142 } 1143 } 1144 1145 func newDeclarator(name string) *cc.Declarator { 1146 return &cc.Declarator{ 1147 DirectDeclarator: &cc.DirectDeclarator{ 1148 Case: cc.DirectDeclaratorIdent, 1149 Token: cc.Token{Rune: cc.IDENTIFIER, Value: cc.String(name)}, 1150 }, 1151 } 1152 } 1153 1154 type enumSpec struct { 1155 decl *cc.Declaration 1156 spec *cc.EnumSpecifier 1157 1158 emitted bool 1159 } 1160 1161 func (n *enumSpec) emit(p *project) { 1162 if n == nil || p.pass1 || n.emitted { 1163 return 1164 } 1165 1166 n.emitted = true 1167 ok := false 1168 for list := n.spec.EnumeratorList; list != nil; list = list.EnumeratorList { 1169 nm := list.Enumerator.Token.Value 1170 if _, ok2 := p.emitedEnums[nm]; !ok2 && p.enumConsts[nm] != "" { 1171 ok = true 1172 break 1173 } 1174 } 1175 if !ok { 1176 return 1177 } 1178 1179 p.w("%s", tidyComment("\n", n.decl)) 1180 p.w("const ( /* %v: */", p.pos(n.decl)) 1181 for list := n.spec.EnumeratorList; list != nil; list = list.EnumeratorList { 1182 en := list.Enumerator 1183 nm := en.Token.Value 1184 if _, ok := p.emitedEnums[nm]; ok || p.enumConsts[nm] == "" { 1185 continue 1186 } 1187 1188 p.emitedEnums[nm] = struct{}{} 1189 p.w("%s%s = ", tidyComment("\n", en), p.enumConsts[nm]) 1190 p.intConst(en, "", en.Operand, en.Operand.Type(), fForceNoConv) 1191 p.w(";") 1192 } 1193 p.w(");") 1194 } 1195 1196 type typedef struct { 1197 sig uint64 1198 tld *tld 1199 } 1200 1201 type define struct { 1202 name string 1203 value cc.Value 1204 } 1205 1206 type project struct { 1207 ast *cc.AST 1208 buf bytes.Buffer 1209 capi []string 1210 defines map[cc.StringID]define 1211 defineLines []string 1212 emitedEnums map[cc.StringID]struct{} 1213 enumConsts map[cc.StringID]string 1214 enumSpecs map[*cc.EnumSpecifier]*enumSpec 1215 errors scanner.ErrorList 1216 externs map[cc.StringID]*tld 1217 fn string 1218 imports map[string]*imported // C name: import info 1219 intType cc.Type 1220 localTaggedStructs []func() 1221 mainName string 1222 ptrSize uintptr 1223 ptrType cc.Type 1224 scope scope 1225 sharedFns map[*cc.FunctionDefinition]struct{} 1226 sharedFnsEmitted map[*cc.FunctionDefinition]struct{} 1227 staticQueue []*cc.InitDeclarator 1228 structs map[cc.StringID]*taggedStruct // key: C tag 1229 symtab map[string]interface{} // *tld or *imported 1230 task *Task 1231 tldScope scope 1232 tlds map[*cc.Declarator]*tld 1233 ts bytes.Buffer // Text segment 1234 tsName string 1235 tsNameP string 1236 tsOffs map[cc.StringID]uintptr 1237 tsW []rune // Text segment, wchar_t 1238 tsWName string 1239 tsWNameP string 1240 tsWOffs map[cc.StringID]uintptr 1241 typeSigHash maphash.Hash 1242 typedefTypes map[cc.StringID]*typedef 1243 typedefsEmited map[string]struct{} 1244 verifyStructs map[string]cc.Type 1245 wanted map[*cc.Declarator]struct{} 1246 wcharSize uintptr 1247 1248 isMain bool 1249 pass1 bool 1250 pauseCodegen bool 1251 } 1252 1253 func newProject(t *Task) (*project, error) { 1254 voidType := t.cfg.ABI.Type(cc.Void) 1255 ptrType := t.cfg.ABI.Ptr(nil, voidType) 1256 intType := t.cfg.ABI.Type(cc.Int) 1257 if intType.Size() != 4 { // We're assuming wchar_t is int32. 1258 return nil, fmt.Errorf("unsupported C int size: %d", intType.Size()) 1259 } 1260 1261 if n := t.cfg.ABI.Types[cc.UChar].Size; n != 1 { 1262 return nil, fmt.Errorf("unsupported C unsigned char size: %d", n) 1263 } 1264 1265 if n := t.cfg.ABI.Types[cc.UShort].Size; n != 2 { 1266 return nil, fmt.Errorf("unsupported C unsigned short size: %d", n) 1267 } 1268 1269 if n := t.cfg.ABI.Types[cc.UInt].Size; n != 4 { 1270 return nil, fmt.Errorf("unsupported C unsigned int size: %d", n) 1271 } 1272 1273 if n := t.cfg.ABI.Types[cc.ULongLong].Size; n != 8 { 1274 return nil, fmt.Errorf("unsupported C unsigned long long size: %d", n) 1275 } 1276 1277 p := &project{ 1278 defines: map[cc.StringID]define{}, 1279 emitedEnums: map[cc.StringID]struct{}{}, 1280 enumConsts: map[cc.StringID]string{}, 1281 enumSpecs: map[*cc.EnumSpecifier]*enumSpec{}, 1282 externs: map[cc.StringID]*tld{}, 1283 imports: map[string]*imported{}, 1284 intType: intType, 1285 ptrSize: t.cfg.ABI.Types[cc.Ptr].Size, 1286 ptrType: ptrType, 1287 scope: newScope(), 1288 sharedFns: t.cfg.SharedFunctionDefinitions.M, 1289 sharedFnsEmitted: map[*cc.FunctionDefinition]struct{}{}, 1290 symtab: map[string]interface{}{}, 1291 task: t, 1292 tlds: map[*cc.Declarator]*tld{}, 1293 tsWOffs: map[cc.StringID]uintptr{}, 1294 tsOffs: map[cc.StringID]uintptr{}, 1295 typedefTypes: map[cc.StringID]*typedef{}, 1296 typedefsEmited: map[string]struct{}{}, 1297 verifyStructs: map[string]cc.Type{}, 1298 wanted: map[*cc.Declarator]struct{}{}, 1299 wcharSize: t.asts[0].WideCharType.Size(), 1300 } 1301 p.tldScope = p.scope 1302 p.scope.take(idCAPI) 1303 for _, v := range t.imported { 1304 var err error 1305 if v.name, v.exports, err = t.capi(v.path); err != nil { 1306 return nil, err 1307 } 1308 1309 v.qualifier = p.scope.take(cc.String(v.name)) + "." 1310 for k := range v.exports { 1311 if p.imports[k] == nil { 1312 p.imports[k] = v 1313 } 1314 } 1315 } 1316 p.tsNameP = p.scope.take(idTs) 1317 p.tsName = p.scope.take(idTs) 1318 p.tsWNameP = p.scope.take(idWtext) 1319 p.tsWName = p.scope.take(idWtext) 1320 if err := p.layout(); err != nil { 1321 return nil, err 1322 } 1323 1324 return p, nil 1325 } 1326 1327 func (p *project) newScope() scope { 1328 s := newScope() 1329 var a []cc.StringID 1330 for k := range p.structs { 1331 a = append(a, k) 1332 } 1333 sort.Slice(a, func(i, j int) bool { return a[i].String() < a[j].String() }) 1334 for _, k := range a { 1335 s.take(cc.String(p.structs[k].name)) 1336 } 1337 return s 1338 } 1339 1340 func (p *project) err(n cc.Node, s string, args ...interface{}) { 1341 if p.task.errTrace || strings.Contains(s, "internal error") { 1342 s = s + "(" + origin(2) + ")" 1343 } 1344 if p.task.traceTranslationUnits { 1345 trc("%v: error: %s (%v)", pos(n), fmt.Sprintf(s, args...), origin(2)) 1346 } 1347 if !p.task.allErrors && len(p.errors) >= 10 { 1348 return 1349 } 1350 1351 switch { 1352 case n == nil: 1353 p.errors.Add(token.Position{}, fmt.Sprintf(s, args...)) 1354 default: 1355 p.errors.Add(token.Position(n.Position()), fmt.Sprintf(s, args...)) 1356 if !p.task.allErrors && len(p.errors) == 10 { 1357 p.errors.Add(token.Position(n.Position()), tooManyErrors) 1358 } 1359 } 1360 } 1361 1362 func (p *project) o(s string, args ...interface{}) { 1363 if oTraceG { 1364 fmt.Printf(s, args...) 1365 } 1366 fmt.Fprintf(p.task.out, s, args...) 1367 } 1368 1369 func (p *project) w(s string, args ...interface{}) { 1370 if p.pass1 || p.pauseCodegen { 1371 return 1372 } 1373 1374 if coverExperiment { 1375 pc, _, _, ok := runtime.Caller(1) 1376 if ok { 1377 coverMap[pc] = struct{}{} 1378 } 1379 } 1380 if oTraceW { 1381 fmt.Printf(s, args...) 1382 } 1383 //fmt.Fprintf(&p.buf, "/* %s */", origin(2)) //TODO- 1384 fmt.Fprintf(&p.buf, s, args...) 1385 } 1386 1387 func (p *project) layout() error { 1388 if err := p.layoutTLDs(); err != nil { 1389 return err 1390 } 1391 1392 if err := p.layoutSymtab(); err != nil { 1393 return err 1394 } 1395 1396 if err := p.layoutStructs(); err != nil { 1397 return err 1398 } 1399 1400 if err := p.layoutEnums(); err != nil { 1401 return err 1402 } 1403 1404 if err := p.layoutDefines(); err != nil { 1405 return err 1406 } 1407 1408 return p.layoutStaticLocals() 1409 } 1410 1411 func (p *project) layoutSymtab() error { 1412 var t0 time.Time 1413 if p.task.traceTranslationUnits { 1414 fmt.Printf("processing symbol table ... ") 1415 t0 = time.Now() 1416 defer func() { fmt.Println(time.Since(t0)) }() 1417 } 1418 1419 for _, i := range p.task.symSearchOrder { 1420 switch { 1421 case i < 0: 1422 imported := p.task.imported[-i-1] 1423 for nm := range imported.exports { 1424 if _, ok := p.symtab[nm]; !ok { 1425 p.symtab[nm] = imported 1426 } 1427 } 1428 default: 1429 ast := p.task.asts[i] 1430 for d := range ast.TLD { 1431 if d.IsFunctionPrototype() || d.Linkage != cc.External { 1432 continue 1433 } 1434 1435 nm := d.Name() 1436 name := nm.String() 1437 if _, ok := p.symtab[name]; !ok { 1438 tld := p.externs[nm] 1439 if tld == nil { 1440 if d.Type().Kind() != cc.Function && !p.task.header { 1441 p.err(d, "back-end: undefined: %s %v %v", d.Name(), d.Type(), d.Type().Kind()) 1442 } 1443 continue 1444 } 1445 1446 p.symtab[name] = tld 1447 } 1448 } 1449 } 1450 } 1451 return nil 1452 } 1453 1454 func (p *project) layoutDefines() error { 1455 if !p.task.exportDefinesValid { 1456 return nil 1457 } 1458 1459 var t0 time.Time 1460 if p.task.traceTranslationUnits { 1461 fmt.Printf("processing #defines ... ") 1462 t0 = time.Now() 1463 defer func() { fmt.Println(time.Since(t0)) }() 1464 } 1465 1466 var prefix = p.task.exportDefines 1467 taken := map[cc.StringID]struct{}{} 1468 for _, ast := range p.task.asts { 1469 var a []cc.StringID 1470 for nm, m := range ast.Macros { 1471 if m.IsFnLike() { 1472 continue 1473 } 1474 1475 if strings.HasPrefix(nm.String(), "__") { 1476 continue 1477 } 1478 1479 if _, ok := taken[nm]; ok { 1480 continue 1481 } 1482 1483 taken[nm] = struct{}{} 1484 a = append(a, nm) 1485 } 1486 sort.Slice(a, func(i, j int) bool { return a[i].String() < a[j].String() }) 1487 for _, nm := range a { 1488 m := ast.Macros[nm] 1489 val, src := evalMacro(m, ast) 1490 if src == "" { 1491 continue 1492 } 1493 1494 name := nm.String() 1495 switch { 1496 case prefix == "": 1497 name = capitalize(name) 1498 default: 1499 name = prefix + name 1500 } 1501 name = p.scope.take(cc.String(name)) 1502 p.defines[nm] = define{name, val} 1503 p.defineLines = append(p.defineLines, fmt.Sprintf("%s = %s // %v:", name, src, p.pos(m))) 1504 } 1505 } 1506 return nil 1507 } 1508 1509 func evalMacro(m *cc.Macro, ast *cc.AST) (cc.Value, string) { 1510 toks := m.ReplacementTokens() 1511 if len(toks) != 1 { 1512 return evalMacro2(m, ast) 1513 } 1514 1515 src := strings.TrimSpace(toks[0].Src.String()) 1516 if len(src) == 0 { 1517 return nil, "" 1518 } 1519 1520 neg := "" 1521 switch src[0] { 1522 case '"': 1523 if _, err := strconv.Unquote(src); err == nil { 1524 return cc.StringValue(cc.String(src)), src 1525 } 1526 case '-': 1527 neg = "-" 1528 src = src[1:] 1529 fallthrough 1530 default: 1531 src = strings.TrimRight(src, "lLuU") 1532 if u64, err := strconv.ParseUint(src, 0, 64); err == nil { 1533 switch { 1534 case neg == "": 1535 return cc.Uint64Value(u64), src 1536 default: 1537 return cc.Int64Value(-u64), neg + src 1538 } 1539 } 1540 1541 src = strings.TrimRight(src, "fF") 1542 if f64, err := strconv.ParseFloat(src, 64); err == nil { 1543 return cc.Float64Value(f64), neg + src 1544 } 1545 } 1546 1547 return evalMacro2(m, ast) 1548 } 1549 1550 func evalMacro2(m *cc.Macro, ast *cc.AST) (cc.Value, string) { 1551 op, err := ast.Eval(m) 1552 if err != nil { 1553 return nil, "" 1554 } 1555 1556 switch x := op.Value().(type) { 1557 case cc.Int64Value: 1558 return op.Value(), fmt.Sprintf("%d", int64(x)) 1559 case cc.Uint64Value: 1560 return op.Value(), fmt.Sprintf("%d", uint64(x)) 1561 default: 1562 panic(todo("", pos(m))) 1563 } 1564 } 1565 1566 func (p *project) layoutEnums() error { 1567 var t0 time.Time 1568 if p.task.traceTranslationUnits { 1569 fmt.Printf("processing enum values ... ") 1570 t0 = time.Now() 1571 defer func() { fmt.Println(time.Since(t0)) }() 1572 } 1573 1574 export := doNotChange 1575 if p.task.exportEnumsValid { 1576 switch { 1577 case p.task.exportEnums != "": 1578 export = exportPrefix 1579 default: 1580 export = exportCapitalize 1581 } 1582 } else if p.task.defaultUnExport { 1583 export = doNotExport 1584 } 1585 1586 var enumList []*cc.EnumSpecifier 1587 for _, v := range p.task.asts { 1588 for list := v.TranslationUnit; list != nil; list = list.TranslationUnit { 1589 decl := list.ExternalDeclaration 1590 switch decl.Case { 1591 case cc.ExternalDeclarationDecl: // Declaration 1592 // ok 1593 default: 1594 continue 1595 } 1596 1597 cc.Inspect(decl.Declaration.DeclarationSpecifiers, func(n cc.Node, entry bool) bool { 1598 if !entry { 1599 return true 1600 } 1601 1602 x, ok := n.(*cc.EnumSpecifier) 1603 if !ok || x.Case != cc.EnumSpecifierDef { 1604 return true 1605 } 1606 1607 if _, ok := p.enumSpecs[x]; !ok { 1608 enumList = append(enumList, x) 1609 p.enumSpecs[x] = &enumSpec{decl: decl.Declaration, spec: x} 1610 } 1611 return true 1612 }) 1613 } 1614 } 1615 1616 vals := map[cc.StringID]interface{}{} 1617 for _, v := range enumList { 1618 for list := v.EnumeratorList; list != nil; list = list.EnumeratorList { 1619 en := list.Enumerator 1620 nm := en.Token.Value 1621 var val int64 1622 switch x := en.Operand.Value().(type) { 1623 case cc.Int64Value: 1624 val = int64(x) 1625 case cc.Uint64Value: 1626 val = int64(x) 1627 default: 1628 panic(todo("")) 1629 } 1630 switch ex, ok := vals[nm]; { 1631 case ok: 1632 switch { 1633 case ex == nil: // 1634 continue 1635 case ex == val: // same name and same value 1636 continue 1637 default: // same name, different value 1638 vals[nm] = nil 1639 } 1640 default: 1641 vals[nm] = val 1642 } 1643 p.enumConsts[nm] = "" 1644 } 1645 } 1646 var a []cc.StringID 1647 for nm := range p.enumConsts { 1648 if val, ok := vals[nm]; ok && val == nil { 1649 delete(p.enumConsts, nm) 1650 continue 1651 } 1652 1653 a = append(a, nm) 1654 } 1655 sort.Slice(a, func(i, j int) bool { return a[i].String() < a[j].String() }) 1656 for _, nm := range a { 1657 name := nm.String() 1658 switch export { 1659 case doNotExport: 1660 name = unCapitalize(name) 1661 case doNotChange: 1662 // nop 1663 case exportCapitalize: 1664 name = capitalize(name) 1665 case exportPrefix: 1666 name = p.task.exportEnums + name 1667 } 1668 name = p.scope.take(cc.String(name)) 1669 p.enumConsts[nm] = name 1670 } 1671 return nil 1672 } 1673 1674 func (p *project) layoutStaticLocals() error { 1675 var t0 time.Time 1676 if p.task.traceTranslationUnits { 1677 fmt.Printf("processing static local declarations ... ") 1678 t0 = time.Now() 1679 defer func() { fmt.Println(time.Since(t0)) }() 1680 } 1681 for _, v := range p.task.asts { 1682 for list := v.TranslationUnit; list != nil; list = list.TranslationUnit { 1683 decl := list.ExternalDeclaration 1684 switch decl.Case { 1685 case cc.ExternalDeclarationFuncDef: // FunctionDefinition 1686 // ok 1687 default: 1688 continue 1689 } 1690 1691 cc.Inspect(decl.FunctionDefinition.CompoundStatement, func(n cc.Node, entry bool) bool { 1692 switch x := n.(type) { 1693 case *cc.Declarator: 1694 if !entry || !x.IsStatic() || x.Read == 0 || x.IsParameter { 1695 break 1696 } 1697 1698 nm := x.Name() 1699 if s := p.task.staticLocalsPrefix; s != "" { 1700 nm = cc.String(s + nm.String()) 1701 } 1702 p.tlds[x] = &tld{name: p.scope.take(nm)} 1703 } 1704 return true 1705 }) 1706 } 1707 } 1708 return nil 1709 } 1710 1711 func (p *project) layoutStructs() error { 1712 var t0 time.Time 1713 if p.task.traceTranslationUnits { 1714 fmt.Printf("processing struct/union types ... ") 1715 t0 = time.Now() 1716 defer func() { fmt.Println(time.Since(t0)) }() 1717 } 1718 1719 export := doNotChange 1720 if p.task.exportStructsValid { 1721 switch { 1722 case p.task.exportStructs != "": 1723 export = exportPrefix 1724 default: 1725 export = exportCapitalize 1726 } 1727 } else if p.task.defaultUnExport { 1728 export = doNotExport 1729 } 1730 1731 m := map[cc.StringID]*taggedStruct{} 1732 var tags []cc.StringID 1733 for _, v := range p.task.asts { 1734 cc.Inspect(v.TranslationUnit, func(n cc.Node, entry bool) bool { 1735 if entry { 1736 switch x := n.(type) { 1737 case *cc.Declarator: 1738 if nm := x.Name().String(); strings.HasPrefix(nm, "_") { 1739 break 1740 } 1741 1742 p.captureStructTags(x, x.Type(), m, &tags) 1743 case *cc.Declaration: 1744 cc.Inspect(x.DeclarationSpecifiers, func(nn cc.Node, entry bool) bool { 1745 switch y := nn.(type) { 1746 case *cc.StructOrUnionSpecifier: 1747 if tag := y.Token.Value; tag != 0 { 1748 p.captureStructTags(y, y.Type(), m, &tags) 1749 } 1750 } 1751 return true 1752 }) 1753 } 1754 } 1755 return true 1756 }) 1757 } 1758 sort.Slice(tags, func(i, j int) bool { return tags[i].String() < tags[j].String() }) 1759 for _, k := range tags { 1760 v := m[k] 1761 //TODO rename conflicts 1762 if v.conflicts { 1763 delete(m, k) 1764 continue 1765 } 1766 1767 name := k.String() 1768 switch export { 1769 case doNotExport: 1770 name = unCapitalize(name) 1771 case doNotChange: 1772 // nop 1773 case exportCapitalize: 1774 name = capitalize(name) 1775 case exportPrefix: 1776 name = p.task.exportStructs + name 1777 } 1778 v.name = p.scope.take(cc.String(name)) 1779 } 1780 for _, k := range tags { 1781 v := m[k] 1782 if v != nil { 1783 v.gotyp = p.structType(nil, v.ctyp) 1784 } 1785 } 1786 p.structs = m 1787 return nil 1788 } 1789 1790 func (p *project) captureStructTags(n cc.Node, t cc.Type, m map[cc.StringID]*taggedStruct, tags *[]cc.StringID) { 1791 if t == nil { 1792 return 1793 } 1794 1795 t = t.Alias() 1796 for t.Kind() == cc.Ptr { 1797 t = t.Alias().Elem().Alias() 1798 } 1799 if t.Kind() == cc.Invalid || t.IsIncomplete() { 1800 return 1801 } 1802 1803 switch t.Kind() { 1804 case cc.Struct, cc.Union: 1805 tag := t.Tag() 1806 if tag == 0 { 1807 return 1808 } 1809 1810 ex := m[tag] 1811 if ex != nil { 1812 ts := p.typeSignature(n, t) 1813 exs := p.typeSignature(n, ex.ctyp) 1814 if ts != exs { 1815 ex.conflicts = true 1816 } 1817 return 1818 } 1819 1820 nf := t.NumField() 1821 m[tag] = &taggedStruct{ctyp: t, node: n} 1822 for idx := []int{0}; idx[0] < nf; idx[0]++ { 1823 p.captureStructTags(n, t.FieldByIndex(idx).Type(), m, tags) 1824 } 1825 *tags = append(*tags, tag) 1826 case cc.Array: 1827 p.captureStructTags(n, t.Elem(), m, tags) 1828 } 1829 } 1830 1831 func (p *project) typeSignature(n cc.Node, t cc.Type) (r uint64) { 1832 p.typeSigHash.Reset() 1833 p.typeSignature2(n, &p.typeSigHash, t) 1834 return p.typeSigHash.Sum64() 1835 } 1836 1837 func (p *project) typeSignature2(n cc.Node, b *maphash.Hash, t cc.Type) { 1838 t = t.Alias() 1839 if t.IsIntegerType() { 1840 if !t.IsSignedType() { 1841 b.WriteByte('u') 1842 } 1843 fmt.Fprintf(b, "int%d", t.Size()*8) 1844 return 1845 } 1846 1847 if t.IsArithmeticType() { 1848 b.WriteString(t.Kind().String()) 1849 return 1850 } 1851 1852 structOrUnion := "struct" 1853 switch t.Kind() { 1854 case cc.Ptr: 1855 fmt.Fprintf(b, "*%s", t.Elem()) 1856 case cc.Array: 1857 if t.IsVLA() { 1858 // trc("VLA") 1859 p.err(n, "variable length arrays not supported: %v", t) 1860 } 1861 1862 fmt.Fprintf(b, "[%d]%s", t.Len(), t.Elem()) 1863 case cc.Vector: 1864 fmt.Fprintf(b, "[%d]%s", t.Len(), t.Elem()) 1865 case cc.Union: 1866 structOrUnion = "union" 1867 fallthrough 1868 case cc.Struct: 1869 b.WriteString(structOrUnion) 1870 nf := t.NumField() 1871 fmt.Fprintf(b, " %d{", nf) 1872 b.WriteByte('{') 1873 for idx := []int{0}; idx[0] < nf; idx[0]++ { 1874 f := t.FieldByIndex(idx) 1875 fmt.Fprintf(b, "%s:%d:%d:%v:%d:%d:", 1876 f.Name(), f.BitFieldOffset(), f.BitFieldWidth(), f.IsBitField(), f.Offset(), f.Padding(), 1877 ) 1878 p.typeSignature2(f.Declarator(), b, f.Type()) 1879 b.WriteByte(';') 1880 } 1881 b.WriteByte('}') 1882 case cc.Void: 1883 b.WriteString("void") 1884 case cc.Invalid: 1885 b.WriteString("invalid") //TODO fix cc/v3 1886 default: 1887 panic(todo("", p.pos(n), t, t.Kind())) 1888 } 1889 } 1890 1891 func (p *project) structType(n cc.Node, t cc.Type) string { 1892 switch t.Kind() { 1893 case cc.Struct, cc.Union: 1894 tag := t.Tag() 1895 if tag != 0 && p.structs != nil { 1896 s := p.structs[tag] 1897 if s == nil { 1898 return p.structLiteral(n, t) 1899 } 1900 1901 if s.gotyp == "" { 1902 s.gotyp = p.structLiteral(n, t) 1903 } 1904 return s.gotyp 1905 } 1906 1907 return p.structLiteral(n, t) 1908 default: 1909 panic(todo("internal error: %v", t.Kind())) 1910 } 1911 } 1912 1913 func (p *project) padName(n *int) string { 1914 if !p.task.exportFieldsValid { 1915 return "_" 1916 } 1917 1918 *n++ 1919 return fmt.Sprintf("%s__ccgo_pad%d", p.task.exportFields, *n) 1920 } 1921 1922 func (p *project) structLiteral(n cc.Node, t cc.Type) string { 1923 var npad int 1924 b := bytesBufferPool.Get().(*bytes.Buffer) 1925 defer func() { b.Reset(); bytesBufferPool.Put(b) }() 1926 switch t.Kind() { 1927 case cc.Struct: 1928 info := cc.NewStructLayout(t) 1929 // trc("%v: %q\n%s", p.pos(n), t.Tag(), info) 1930 b.WriteString("struct {") 1931 if info.NeedExplicitAlign { 1932 fmt.Fprintf(b, "%s [0]uint%d;", p.padName(&npad), 8*p.align(n, t)) 1933 } 1934 var max uintptr 1935 for _, off := range info.Offsets { 1936 flds := info.OffsetToFields[off] 1937 if off < max { 1938 var a []string 1939 var nmf cc.Field 1940 for _, f := range flds { 1941 if f.Name() != 0 && nmf == nil { 1942 nmf = f 1943 } 1944 if !f.IsBitField() { 1945 panic(todo("internal error %q, off %v max %v\n%s", f.Name(), off, max, info)) 1946 } 1947 a = append(a, fmt.Sprintf("%s %s: %d", f.Type(), f.Name(), f.BitFieldWidth())) 1948 } 1949 fmt.Fprintf(b, "/* %s */", strings.Join(a, ", ")) 1950 continue 1951 } 1952 1953 f := flds[0] 1954 switch pad := info.PaddingsBefore[f]; { 1955 case pad < 0: 1956 continue 1957 case pad > 0: 1958 fmt.Fprintf(b, "%s [%d]byte;", p.padName(&npad), pad) 1959 } 1960 switch { 1961 case f.IsBitField(): 1962 max += uintptr(f.BitFieldBlockWidth()) >> 3 1963 var a []string 1964 var nmf cc.Field 1965 for _, f := range flds { 1966 if f.Name() != 0 && nmf == nil { 1967 nmf = f 1968 } 1969 if !f.IsBitField() { 1970 panic(todo("internal error %q\n%s", f.Name(), info)) 1971 } 1972 a = append(a, fmt.Sprintf("%s %s: %d", f.Type(), f.Name(), f.BitFieldWidth())) 1973 } 1974 if nmf == nil { 1975 nmf = f 1976 } 1977 fmt.Fprintf(b, "%s uint%d /* %s */;", p.bitFieldName(n, nmf), f.BitFieldBlockWidth(), strings.Join(a, ", ")) 1978 default: 1979 ft := f.Type() 1980 if ft.Kind() == cc.Array && ft.IsIncomplete() || ft.Size() == 0 { 1981 break 1982 } 1983 1984 max += ft.Size() 1985 fmt.Fprintf(b, "%s %s;", p.fieldName2(n, f), p.typ(n, ft)) 1986 } 1987 } 1988 if info.PaddingAfter != 0 { 1989 fmt.Fprintf(b, "%s [%d]byte;", p.padName(&npad), info.PaddingAfter) 1990 } 1991 b.WriteByte('}') 1992 case cc.Union: 1993 b.WriteString("struct {") 1994 info := cc.NewStructLayout(t) 1995 if info.NeedExplicitAlign { 1996 fmt.Fprintf(b, "%s [0]uint%d;", p.padName(&npad), 8*p.align(n, t)) 1997 } 1998 al := uintptr(t.Align()) 1999 sz := t.Size() 2000 if al > sz { 2001 panic(todo("", p.pos(n))) 2002 } 2003 2004 f := t.FieldByIndex([]int{0}) 2005 ft := f.Type() 2006 al0 := ft.Align() 2007 if f.IsBitField() { 2008 al0 = f.BitFieldBlockWidth() >> 3 2009 } 2010 if al != uintptr(al0) { 2011 fmt.Fprintf(b, "%s [0]uint%d;", p.padName(&npad), 8*al) 2012 } 2013 fsz := ft.Size() 2014 switch { 2015 case f.IsBitField(): 2016 fmt.Fprintf(b, "%s ", p.fieldName2(n, f)) 2017 fmt.Fprintf(b, "uint%d;", f.BitFieldBlockWidth()) 2018 fsz = uintptr(f.BitFieldBlockWidth()) >> 3 2019 default: 2020 fmt.Fprintf(b, "%s %s;", p.fieldName2(n, f), p.typ(n, ft)) 2021 } 2022 if pad := sz - fsz; pad != 0 { 2023 fmt.Fprintf(b, "%s [%d]byte;", p.padName(&npad), pad) 2024 } 2025 b.WriteByte('}') 2026 default: 2027 panic(todo("internal error: %v", t.Kind())) 2028 } 2029 r := b.String() 2030 if p.task.verifyStructs { 2031 if _, ok := p.verifyStructs[r]; !ok { 2032 p.verifyStructs[r] = t 2033 } 2034 } 2035 return r 2036 } 2037 2038 func (p *project) align(nd cc.Node, t cc.Type) int { 2039 switch n := t.Align(); { 2040 case n <= 1: 2041 return 1 2042 case n <= 2: 2043 return 2 2044 case n <= 4: 2045 return 4 2046 case n <= 8: 2047 return 8 2048 default: 2049 if !p.task.ignoreUnsupportedAligment { 2050 p.err(nd, "unsupported alignment of type %s: %v", t, n) 2051 } 2052 return 8 2053 } 2054 } 2055 2056 func (p *project) bitFieldName(n cc.Node, f cc.Field) string { 2057 if id := f.Name(); id != 0 { 2058 return p.fieldName(n, id) 2059 } 2060 2061 return fmt.Sprintf("__%d", f.Offset()) 2062 } 2063 2064 func (p *project) fieldName2(n cc.Node, f cc.Field) string { 2065 if f.Name() != 0 { 2066 return p.fieldName(n, f.Name()) 2067 } 2068 2069 return p.fieldName(n, cc.String(fmt.Sprintf("__%d", f.Offset()))) 2070 } 2071 2072 func (p *project) fieldName(n cc.Node, id cc.StringID) string { 2073 if id == 0 { 2074 panic(todo("", p.pos(n))) 2075 } 2076 2077 if !p.task.exportFieldsValid { 2078 s := id.String() 2079 if p.task.defaultUnExport { 2080 s = unCapitalize(s) 2081 } 2082 2083 if !reservedNames[s] { 2084 return s 2085 } 2086 2087 return "__" + s 2088 } 2089 2090 if s := p.task.exportFields; s != "" { 2091 return s + id.String() 2092 } 2093 2094 return capitalize(id.String()) 2095 } 2096 2097 func (p *project) dtyp(d *cc.Declarator) (r string) { 2098 t := d.Type() 2099 if t.IsIncomplete() { 2100 if t.Kind() == cc.Array && d.IsParameter { 2101 return "uintptr" 2102 } 2103 2104 panic(todo("")) 2105 } 2106 2107 return p.typ(d, t) 2108 } 2109 2110 func (p *project) typ(nd cc.Node, t cc.Type) (r string) { 2111 if t.IsIncomplete() { 2112 panic(todo("", p.pos(nd), t)) 2113 } 2114 2115 if t.IsAliasType() { 2116 if tld := p.tlds[t.AliasDeclarator()]; tld != nil { 2117 return tld.name 2118 } 2119 } 2120 2121 b := bytesBufferPool.Get().(*bytes.Buffer) 2122 defer func() { b.Reset(); bytesBufferPool.Put(b) }() 2123 if t.IsIntegerType() { 2124 switch t.Kind() { 2125 case cc.Int128: 2126 fmt.Fprintf(b, "%sInt128", p.task.crt) 2127 return b.String() 2128 case cc.UInt128: 2129 fmt.Fprintf(b, "%sUint128", p.task.crt) 2130 return b.String() 2131 } 2132 2133 if !t.IsSignedType() { 2134 b.WriteByte('u') 2135 } 2136 if t.Size() > 8 { 2137 p.err(nd, "unsupported C type: %v", t) 2138 } 2139 fmt.Fprintf(b, "int%d", 8*t.Size()) 2140 return b.String() 2141 } 2142 2143 switch t.Kind() { 2144 case cc.Ptr, cc.Function: 2145 return "uintptr" 2146 case cc.Double: 2147 return "float64" 2148 case cc.Float: 2149 return "float32" 2150 case cc.Array: 2151 n := t.Len() 2152 switch { 2153 case t.IsVLA(): 2154 fmt.Fprintf(b, "uintptr") 2155 default: 2156 fmt.Fprintf(b, "[%d]%s", n, p.typ(nd, t.Elem())) 2157 } 2158 return b.String() 2159 case cc.Vector: 2160 n := t.Len() 2161 fmt.Fprintf(b, "[%d]%s", n, p.typ(nd, t.Elem())) 2162 return b.String() 2163 case cc.Struct, cc.Union: 2164 if tag := t.Tag(); tag != 0 { 2165 if s := p.structs[tag]; s != nil { 2166 if s.name == "" { 2167 panic(todo("internal error %q", tag)) 2168 } 2169 2170 return s.name 2171 } 2172 } 2173 2174 return p.structType(nd, t) 2175 } 2176 2177 panic(todo("", p.pos(nd), t.Kind(), t)) 2178 } 2179 2180 func isScalarKind(k cc.Kind) bool { 2181 switch k { 2182 case 2183 cc.Char, cc.SChar, cc.UChar, 2184 cc.Short, cc.UShort, 2185 cc.Int, cc.UInt, 2186 cc.Long, cc.ULong, 2187 cc.LongLong, cc.ULongLong, 2188 cc.Float, cc.Double, 2189 cc.Ptr: 2190 2191 return true 2192 } 2193 2194 return false 2195 } 2196 2197 func (p *project) layoutTLDs() error { 2198 var t0 time.Time 2199 if p.task.traceTranslationUnits { 2200 fmt.Printf("processing file scope declarations ... ") 2201 t0 = time.Now() 2202 defer func() { fmt.Println(time.Since(t0)) }() 2203 } 2204 2205 exportExtern, exportTypedef := doNotChange, doNotChange 2206 if p.task.exportExternsValid { 2207 switch { 2208 case p.task.exportExterns != "": 2209 exportExtern = exportPrefix 2210 default: 2211 exportExtern = exportCapitalize 2212 } 2213 } else if p.task.defaultUnExport { 2214 exportExtern = doNotExport 2215 } 2216 2217 if p.task.exportTypedefsValid { 2218 switch { 2219 case p.task.exportTypedefs != "": 2220 exportTypedef = exportPrefix 2221 default: 2222 exportTypedef = exportCapitalize 2223 } 2224 } else if p.task.defaultUnExport { 2225 exportTypedef = doNotExport 2226 } 2227 2228 var a []*cc.Declarator 2229 if p.task.pkgName == "" || p.task.pkgName == "main" { 2230 out: 2231 for _, ast := range p.task.asts { 2232 if a := ast.Scope[idMain]; len(a) != 0 { 2233 switch x := a[0].(type) { 2234 case *cc.Declarator: 2235 if x.Linkage == cc.External { 2236 p.isMain = true 2237 p.scope.take(idMain) 2238 break out 2239 } 2240 } 2241 } 2242 } 2243 } 2244 sharedFns := map[*cc.FunctionDefinition]struct{}{} 2245 for _, ast := range p.task.asts { 2246 a = a[:0] 2247 for d := range ast.TLD { 2248 if d.IsFunctionPrototype() { 2249 continue 2250 } 2251 2252 // https://gcc.gnu.org/onlinedocs/gcc/Inline.html 2253 // 2254 // If you specify both inline and extern in the function definition, then the 2255 // definition is used only for inlining. In no case is the function compiled on 2256 // its own, not even if you refer to its address explicitly. Such an address 2257 // becomes an external reference, as if you had only declared the function, and 2258 // had not defined it. 2259 // 2260 // This combination of inline and extern has almost the effect of a macro. The 2261 // way to use it is to put a function definition in a header file with these 2262 // keywords, and put another copy of the definition (lacking inline and extern) 2263 // in a library file. The definition in the header file causes most calls to 2264 // the function to be inlined. If any uses of the function remain, they refer 2265 // to the single copy in the library. 2266 if d.IsExtern() && d.Type().Inline() { 2267 continue 2268 } 2269 2270 if fn := d.FunctionDefinition(); fn != nil { 2271 if _, ok := p.sharedFns[fn]; ok { 2272 if _, ok := sharedFns[fn]; ok { 2273 continue 2274 } 2275 2276 sharedFns[fn] = struct{}{} 2277 } 2278 } 2279 2280 a = append(a, d) 2281 p.wanted[d] = struct{}{} 2282 } 2283 sort.Slice(a, func(i, j int) bool { 2284 return a[i].NameTok().Seq() < a[j].NameTok().Seq() 2285 }) 2286 for _, d := range a { 2287 switch d.Type().Kind() { 2288 case cc.Struct, cc.Union: 2289 p.checkAttributes(d.Type()) 2290 } 2291 nm := d.Name() 2292 name := nm.String() 2293 2294 switch d.Linkage { 2295 case cc.External: 2296 if ex := p.externs[nm]; ex != nil { 2297 if _, ok := p.task.hide[name]; ok { 2298 break 2299 } 2300 2301 if d.Type().Kind() != cc.Function { 2302 break 2303 } 2304 2305 p.err(d, "redeclared: %s", d.Name()) 2306 break 2307 } 2308 2309 isMain := p.isMain && nm == idMain 2310 switch exportExtern { 2311 case doNotExport: 2312 name = unCapitalize(name) 2313 case doNotChange: 2314 // nop 2315 case exportCapitalize: 2316 name = capitalize(name) 2317 case exportPrefix: 2318 name = p.task.exportExterns + name 2319 } 2320 name = p.scope.take(cc.String(name)) 2321 if isMain { 2322 p.mainName = name 2323 d.Read++ 2324 } 2325 tld := &tld{name: name} 2326 p.externs[nm] = tld 2327 for _, v := range ast.Scope[nm] { 2328 if d, ok := v.(*cc.Declarator); ok { 2329 p.tlds[d] = tld 2330 } 2331 } 2332 if !isMain { 2333 p.capi = append(p.capi, d.Name().String()) 2334 } 2335 case cc.Internal: 2336 if token.IsExported(name) && !p.isMain && p.task.exportExternsValid { 2337 name = "s" + name 2338 } 2339 tld := &tld{name: p.scope.take(cc.String(name))} 2340 for _, v := range ast.Scope[nm] { 2341 if d, ok := v.(*cc.Declarator); ok { 2342 p.tlds[d] = tld 2343 } 2344 } 2345 case cc.None: 2346 if d.IsTypedefName { 2347 if d.Type().IsIncomplete() { 2348 break 2349 } 2350 2351 if exportTypedef == doNotChange && strings.HasPrefix(name, "__") { 2352 break 2353 } 2354 2355 ex, ok := p.typedefTypes[d.Name()] 2356 if ok { 2357 sig := p.typeSignature(d, d.Type()) 2358 if ex.sig == sig { 2359 tld := ex.tld 2360 for _, v := range ast.Scope[nm] { 2361 if d, ok := v.(*cc.Declarator); ok { 2362 p.tlds[d] = tld 2363 } 2364 } 2365 break 2366 } 2367 } 2368 2369 switch exportTypedef { 2370 case doNotExport: 2371 name = unCapitalize(name) 2372 case doNotChange: 2373 // nop 2374 case exportCapitalize: 2375 name = capitalize(name) 2376 case exportPrefix: 2377 name = p.task.exportTypedefs + name 2378 } 2379 2380 tld := &tld{name: p.scope.take(cc.String(name))} 2381 p.typedefTypes[d.Name()] = &typedef{p.typeSignature(d, d.Type()), tld} 2382 for _, v := range ast.Scope[nm] { 2383 if d, ok := v.(*cc.Declarator); ok { 2384 p.tlds[d] = tld 2385 } 2386 } 2387 } 2388 default: 2389 panic(todo("", p.pos(d), nm, d.Linkage)) 2390 } 2391 } 2392 } 2393 for _, ast := range p.task.asts { 2394 for list := ast.TranslationUnit; list != nil; list = list.TranslationUnit { 2395 decl := list.ExternalDeclaration 2396 switch decl.Case { 2397 case cc.ExternalDeclarationFuncDef: // FunctionDefinition 2398 // ok 2399 default: 2400 continue 2401 } 2402 2403 cc.Inspect(decl.FunctionDefinition.CompoundStatement, func(n cc.Node, entry bool) bool { 2404 switch x := n.(type) { 2405 case *cc.Declarator: 2406 if x.IsFunctionPrototype() { 2407 nm := x.Name() 2408 if extern := p.externs[nm]; extern != nil { 2409 break 2410 } 2411 2412 tld := &tld{name: nm.String()} 2413 for _, nd := range ast.Scope[nm] { 2414 if d, ok := nd.(*cc.Declarator); ok { 2415 p.tlds[d] = tld 2416 } 2417 } 2418 } 2419 2420 } 2421 return true 2422 }) 2423 } 2424 } 2425 return nil 2426 } 2427 2428 func (p *project) checkAttributes(t cc.Type) (r bool) { 2429 r = true 2430 for _, v := range t.Attributes() { 2431 cc.Inspect(v, func(n cc.Node, entry bool) bool { 2432 if !entry { 2433 return true 2434 } 2435 2436 switch x := n.(type) { 2437 case *cc.AttributeValue: 2438 if x.Token.Value != idAligned { 2439 break 2440 } 2441 2442 //TODO switch v := x.ExpressionList.AssignmentExpression.Operand.Value().(type) { 2443 //TODO default: 2444 //TODO panic(todo("%T(%v)", v, v)) 2445 //TODO } 2446 } 2447 return true 2448 }) 2449 } 2450 switch t.Kind() { 2451 case cc.Struct, cc.Union: 2452 for i := []int{0}; i[0] < t.NumField(); i[0]++ { 2453 f := t.FieldByIndex(i) 2454 if !p.checkAttributes(f.Type()) { 2455 return false 2456 } 2457 2458 sd := f.Declarator() 2459 if sd == nil { 2460 continue 2461 } 2462 2463 cc.Inspect(sd.StructDeclaration().SpecifierQualifierList, func(n cc.Node, entry bool) bool { 2464 if !entry { 2465 return true 2466 } 2467 2468 switch x := n.(type) { 2469 case *cc.AttributeValue: 2470 if x.Token.Value == idPacked { 2471 p.err(sd, "unsupported attribute: packed") 2472 r = false 2473 return false 2474 } 2475 2476 if x.Token.Value != idAligned { 2477 break 2478 } 2479 2480 switch v := x.ExpressionList.AssignmentExpression.Operand.Value().(type) { 2481 case cc.Int64Value: 2482 if int(v) != t.Align() { 2483 p.err(sd, "unsupported attribute: alignment") 2484 r = false 2485 return false 2486 } 2487 default: 2488 panic(todo("%T(%v)", v, v)) 2489 } 2490 } 2491 return true 2492 }) 2493 if !r { 2494 return false 2495 } 2496 } 2497 } 2498 return r 2499 } 2500 2501 func unCapitalize(s string) string { 2502 if strings.HasPrefix(s, "_") { 2503 return s 2504 } 2505 a := []rune(s) 2506 return strings.ToLower(string(a[0])) + string(a[1:]) 2507 } 2508 2509 func capitalize(s string) string { 2510 if strings.HasPrefix(s, "_") { 2511 s = "X" + s 2512 } 2513 a := []rune(s) 2514 return strings.ToUpper(string(a[0])) + string(a[1:]) 2515 } 2516 2517 func (p *project) main() error { 2518 targs := append([]string(nil), p.task.args...) 2519 for i, v := range targs { 2520 if v == "" { 2521 targs[i] = `""` 2522 } 2523 } 2524 p.o(`// Code generated by '%s %s', DO NOT EDIT. 2525 2526 package %s 2527 2528 `, 2529 filepath.Base(p.task.args[0]), 2530 strings.Join(targs[1:], " "), 2531 p.task.pkgName, 2532 ) 2533 if len(p.defineLines) != 0 { 2534 p.w("\nconst (") 2535 p.w("%s", strings.Join(p.defineLines, "\n")) 2536 p.w("\n)\n\n") 2537 } 2538 var a []*enumSpec 2539 for _, es := range p.enumSpecs { 2540 if es.spec.LexicalScope().Parent() == nil && !es.emitted { 2541 a = append(a, es) 2542 } 2543 } 2544 sort.Slice(a, func(i, j int) bool { 2545 return a[i].decl.Position().String() < a[j].decl.Position().String() 2546 }) 2547 for _, es := range a { 2548 es.emit(p) 2549 } 2550 for i, v := range p.task.asts { 2551 var t0 time.Time 2552 if p.task.traceTranslationUnits { 2553 fmt.Printf("Go back end %v/%v: %s ... ", i+1, len(p.task.asts), filepath.Base(p.task.sources[i].Name)) 2554 t0 = time.Now() 2555 } 2556 p.oneAST(v) 2557 if p.task.traceTranslationUnits { 2558 fmt.Println(time.Since(t0)) 2559 } 2560 p.task.asts[i] = nil 2561 memGuard(i, p.task.isScripted) 2562 } 2563 sort.Slice(p.task.imported, func(i, j int) bool { return p.task.imported[i].path < p.task.imported[j].path }) 2564 p.o(`import ( 2565 "math" 2566 "reflect" 2567 "sync/atomic" 2568 "unsafe" 2569 `) 2570 if len(p.verifyStructs) != 0 { 2571 p.o("\t\"fmt\"\n") 2572 } 2573 first := true 2574 libc := false 2575 for _, v := range p.task.imported { 2576 if v.used { 2577 if v.path == p.task.crtImportPath { 2578 libc = true 2579 } 2580 if first { 2581 p.o("\n") 2582 first = false 2583 } 2584 p.o("\t%q\n", v.path) 2585 } 2586 } 2587 if p.task.crtImportPath != "" { 2588 if !libc { 2589 p.o("\t%q\n", p.task.crtImportPath) 2590 } 2591 p.o("\t%q\n", p.task.crtImportPath+"/sys/types") 2592 } 2593 p.o(`) 2594 2595 var _ = math.Pi 2596 var _ reflect.Kind 2597 var _ atomic.Value 2598 var _ unsafe.Pointer 2599 `) 2600 if p.task.crtImportPath != "" { 2601 if libc { 2602 p.o("var _ *libc.TLS\n") 2603 } 2604 p.o("var _ types.Size_t\n") 2605 } 2606 if p.isMain { 2607 p.o(` 2608 func main() { %sStart(%s) }`, p.task.crt, p.mainName) 2609 } 2610 p.flushStructs() 2611 p.initPatches() 2612 p.flushTS() 2613 if !p.task.noCapi { 2614 p.flushCAPI() 2615 } 2616 p.doVerifyStructs() 2617 if err := p.Err(); err != nil { 2618 return err 2619 } 2620 2621 if _, err := p.buf.WriteTo(p.task.out); err != nil { 2622 return err 2623 } 2624 2625 return p.Err() 2626 } 2627 2628 func (p *project) doVerifyStructs() { 2629 if len(p.verifyStructs) == 0 { 2630 return 2631 } 2632 2633 var a []string 2634 for k := range p.verifyStructs { 2635 a = append(a, k) 2636 } 2637 sort.Strings(a) 2638 p.w("\n\nfunc init() {") 2639 n := 0 2640 for _, k := range a { 2641 t := p.verifyStructs[k] 2642 p.w("\nvar v%d %s", n, k) 2643 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()) 2644 nf := t.NumField() 2645 for idx := []int{0}; idx[0] < nf; idx[0]++ { 2646 f := t.FieldByIndex(idx) 2647 if f.IsFlexible() { 2648 break 2649 } 2650 2651 if f.IsBitField() || f.Type().Size() == 0 { 2652 continue 2653 } 2654 2655 nm := p.fieldName2(f.Declarator(), f) 2656 switch { 2657 case t.Kind() == cc.Union: 2658 if f.Offset() != 0 { 2659 panic(todo("")) 2660 } 2661 2662 if idx[0] != 0 { 2663 break 2664 } 2665 2666 fallthrough 2667 default: 2668 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()) 2669 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()) 2670 } 2671 } 2672 n++ 2673 } 2674 p.w("\n}\n") 2675 } 2676 2677 func (p *project) flushCAPI() { 2678 if p.isMain { 2679 return 2680 } 2681 2682 b := bytes.NewBuffer(nil) 2683 fmt.Fprintf(b, `// Code generated by '%s %s', DO NOT EDIT. 2684 2685 package %s 2686 2687 `, 2688 filepath.Base(p.task.args[0]), 2689 strings.Join(p.task.args[1:], " "), 2690 p.task.pkgName, 2691 ) 2692 fmt.Fprintf(b, "\n\nvar CAPI = map[string]struct{}{") 2693 sort.Strings(p.capi) 2694 for _, nm := range p.capi { 2695 fmt.Fprintf(b, "\n%q: {},", nm) 2696 } 2697 fmt.Fprintf(b, "\n}\n") 2698 if err := ioutil.WriteFile(p.task.capif, b.Bytes(), 0644); err != nil { 2699 p.err(nil, "%v", err) 2700 return 2701 } 2702 2703 if out, err := exec.Command("gofmt", "-r", "(x) -> x", "-l", "-s", "-w", p.task.capif).CombinedOutput(); err != nil { 2704 p.err(nil, "%s: %v", out, err) 2705 } 2706 2707 if out, err := exec.Command("gofmt", "-l", "-s", "-w", p.task.capif).CombinedOutput(); err != nil { 2708 p.err(nil, "%s: %v", out, err) 2709 } 2710 } 2711 2712 func (p *project) initPatches() { 2713 var tlds []*tld 2714 for _, tld := range p.tlds { 2715 if len(tld.patches) != 0 { 2716 tlds = append(tlds, tld) 2717 } 2718 } 2719 if len(tlds) == 0 { 2720 return 2721 } 2722 2723 sort.Slice(tlds, func(i, j int) bool { return tlds[i].name < tlds[j].name }) 2724 p.w("\n\nfunc init() {") 2725 for _, tld := range tlds { 2726 for _, patch := range tld.patches { 2727 var fld string 2728 if patch.fld != nil { 2729 fld = fmt.Sprintf("/* .%s */", patch.fld.Name()) 2730 } 2731 init := patch.init 2732 expr := init.AssignmentExpression 2733 d := expr.Declarator() 2734 switch { 2735 case d != nil && d.Type().Kind() == cc.Function: 2736 p.w("\n*(*") 2737 p.functionSignature(d, nil, d.Type(), "") 2738 p.w(")(unsafe.Pointer(uintptr(unsafe.Pointer(&%s))+%d%s)) = ", tld.name, init.Offset, fld) 2739 p.declarator(init, nil, d, d.Type(), exprFunc, 0) 2740 default: 2741 p.w("\n*(*%s)(unsafe.Pointer(uintptr(unsafe.Pointer(&%s))+%d%s)) = ", p.typ(init, patch.t), tld.name, init.Offset, fld) 2742 p.assignmentExpression(nil, expr, patch.t, exprValue, 0) 2743 } 2744 p.w("// %s:", p.pos(init)) 2745 } 2746 } 2747 p.w("\n}\n") 2748 } 2749 2750 func (p *project) Err() error { 2751 if len(p.errors) == 0 { 2752 return nil 2753 } 2754 2755 var lpos token.Position 2756 w := 0 2757 for _, v := range p.errors { 2758 if lpos.Filename != "" { 2759 if v.Pos.Filename == lpos.Filename && v.Pos.Line == lpos.Line && !strings.HasPrefix(v.Msg, tooManyErrors) { 2760 continue 2761 } 2762 } 2763 2764 p.errors[w] = v 2765 w++ 2766 lpos = v.Pos 2767 } 2768 p.errors = p.errors[:w] 2769 sort.Slice(p.errors, func(i, j int) bool { 2770 a := p.errors[i] 2771 if a.Msg == tooManyErrors { 2772 return false 2773 } 2774 2775 b := p.errors[j] 2776 if b.Msg == tooManyErrors { 2777 return true 2778 } 2779 2780 if !a.Pos.IsValid() && b.Pos.IsValid() { 2781 return true 2782 } 2783 2784 if a.Pos.IsValid() && !b.Pos.IsValid() { 2785 return false 2786 } 2787 2788 if a.Pos.Filename < b.Pos.Filename { 2789 return true 2790 } 2791 2792 if a.Pos.Filename > b.Pos.Filename { 2793 return false 2794 } 2795 2796 if a.Pos.Line < b.Pos.Line { 2797 return true 2798 } 2799 2800 if a.Pos.Line > b.Pos.Line { 2801 return false 2802 } 2803 2804 return a.Pos.Column < b.Pos.Column 2805 }) 2806 a := make([]string, 0, len(p.errors)) 2807 for _, v := range p.errors { 2808 a = append(a, v.Error()) 2809 } 2810 return fmt.Errorf("%s", strings.Join(a, "\n")) 2811 } 2812 2813 func (p *project) flushTS() { 2814 b := p.ts.Bytes() 2815 if len(b) != 0 { 2816 p.w("\n\n") 2817 //TODO add cmd line option for this 2818 //TODO s := strings.TrimSpace(hex.Dump(b)) 2819 //TODO a := strings.Split(s, "\n") 2820 //TODO p.w("// %s\n", strings.Join(a, "\n// ")) 2821 p.w("var %s = %q\n", p.tsName, b) 2822 p.w("var %s = (*reflect.StringHeader)(unsafe.Pointer(&%s)).Data\n", p.tsNameP, p.tsName) 2823 } 2824 if len(p.tsW) != 0 { 2825 p.w("var %s = [...]%s{", p.tsWName, p.typ(nil, p.ast.WideCharType)) 2826 for _, v := range p.tsW { 2827 p.w("%d, ", v) 2828 } 2829 p.w("}\n") 2830 p.w("var %s = uintptr(unsafe.Pointer(&%s[0]))\n", p.tsWNameP, p.tsWName) 2831 } 2832 } 2833 2834 func (p *project) flushStructs() { 2835 var a []*taggedStruct 2836 for _, v := range p.structs { 2837 if !v.emitted { 2838 a = append(a, v) 2839 } 2840 } 2841 sort.Slice(a, func(i, j int) bool { return a[i].name < a[j].name }) 2842 for _, v := range a { 2843 v.emit(p, nil) 2844 } 2845 } 2846 2847 func (p *project) oneAST(ast *cc.AST) { 2848 p.ast = ast 2849 for list := ast.TranslationUnit; list != nil; list = list.TranslationUnit { 2850 p.externalDeclaration(list.ExternalDeclaration) 2851 } 2852 p.w("%s", tidyCommentString(ast.TrailingSeperator.String())) 2853 } 2854 2855 func (p *project) externalDeclaration(n *cc.ExternalDeclaration) { 2856 switch n.Case { 2857 case cc.ExternalDeclarationFuncDef: // FunctionDefinition 2858 p.functionDefinition(n.FunctionDefinition) 2859 case cc.ExternalDeclarationDecl: // Declaration 2860 p.declaration(nil, n.Declaration, false) 2861 case cc.ExternalDeclarationAsm: // AsmFunctionDefinition 2862 // nop 2863 case cc.ExternalDeclarationAsmStmt: // AsmStatement 2864 panic(todo("", p.pos(n))) 2865 case cc.ExternalDeclarationEmpty: // ';' 2866 // nop 2867 case cc.ExternalDeclarationPragma: // PragmaSTDC 2868 panic(todo("", p.pos(n))) 2869 default: 2870 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 2871 } 2872 } 2873 2874 func (p *project) declaration(f *function, n *cc.Declaration, topDecl bool) { 2875 cc.Inspect(n.DeclarationSpecifiers, func(m cc.Node, entry bool) bool { 2876 switch x := m.(type) { 2877 case *cc.EnumSpecifier: 2878 if f == nil { 2879 p.enumSpecs[x].emit(p) 2880 } 2881 case *cc.StructOrUnionSpecifier: 2882 if tag := x.Token.Value; tag != 0 { 2883 switch { 2884 case f == nil: 2885 p.structs[tag].emit(p, n.DeclarationSpecifiers) 2886 default: 2887 p.localTaggedStructs = append(p.localTaggedStructs, func() { 2888 p.structs[tag].emit(p, n.DeclarationSpecifiers) 2889 }) 2890 } 2891 } 2892 } 2893 return true 2894 }) 2895 2896 if n.InitDeclaratorList == nil { 2897 return 2898 } 2899 2900 // DeclarationSpecifiers InitDeclaratorList ';' 2901 sep := tidyComment("\n", n) //TODO repeats 2902 for list := n.InitDeclaratorList; list != nil; list = list.InitDeclaratorList { 2903 p.initDeclarator(f, list.InitDeclarator, sep, topDecl) 2904 sep = "\n" 2905 } 2906 } 2907 2908 func (p *project) initDeclarator(f *function, n *cc.InitDeclarator, sep string, topDecl bool) { 2909 if f == nil { 2910 p.tld(f, n, sep, false) 2911 return 2912 } 2913 2914 d := n.Declarator 2915 if d.IsExtern() || d.IsTypedefName { 2916 return 2917 } 2918 2919 if tld := p.tlds[d]; tld != nil && !topDecl { // static local 2920 if !p.pass1 { 2921 p.staticQueue = append(p.staticQueue, n) 2922 } 2923 return 2924 } 2925 2926 local := f.locals[d] 2927 if local == nil { // Dead declaration. 2928 return 2929 } 2930 2931 block := f.block 2932 t := d.Type() 2933 vla := t.Kind() == cc.Array && t.IsVLA() 2934 if vla && p.pass1 { 2935 f.vlas[d] = struct{}{} 2936 return 2937 } 2938 2939 switch n.Case { 2940 case cc.InitDeclaratorDecl: // Declarator AttributeSpecifierList 2941 if block.noDecl || block.topDecl && !topDecl { 2942 return 2943 } 2944 2945 switch { 2946 case vla: 2947 p.initDeclaratorDeclVLA(f, n, sep) 2948 default: 2949 p.initDeclaratorDecl(f, n, sep) 2950 } 2951 case cc.InitDeclaratorInit: // Declarator AttributeSpecifierList '=' Initializer 2952 if vla { 2953 panic(todo("")) 2954 } 2955 2956 if f.block.topDecl { 2957 switch { 2958 case topDecl: 2959 p.initDeclaratorDecl(f, n, sep) 2960 if local.forceRead && !local.isPinned { 2961 p.w("_ = %s;", local.name) 2962 } 2963 default: 2964 sv := f.condInitPrefix 2965 f.condInitPrefix = func() { 2966 p.declarator(d, f, d, d.Type(), exprLValue, 0) 2967 p.w(" = ") 2968 } 2969 switch { 2970 case p.isConditionalInitializer(n.Initializer): 2971 p.assignmentExpression(f, n.Initializer.AssignmentExpression, d.Type(), exprCondInit, 0) 2972 default: 2973 f.condInitPrefix() 2974 p.initializer(f, n.Initializer, d.Type(), d.StorageClass, nil) 2975 } 2976 f.condInitPrefix = sv 2977 p.w(";") 2978 } 2979 return 2980 } 2981 2982 p.w("%s", sep) 2983 switch { 2984 case local.isPinned: 2985 sv := f.condInitPrefix 2986 f.condInitPrefix = func() { 2987 //TODO- p.declarator(d, f, d, d.Type(), exprLValue, 0) 2988 //TODO- p.w(" = ") 2989 p.w("*(*%s)(unsafe.Pointer(%s%s/* %s */)) = ", p.typ(n, d.Type()), f.bpName, nonZeroUintptr(local.off), local.name) 2990 } 2991 switch { 2992 case p.isConditionalInitializer(n.Initializer): 2993 p.assignmentExpression(f, n.Initializer.AssignmentExpression, d.Type(), exprCondInit, 0) 2994 default: 2995 f.condInitPrefix() 2996 p.initializer(f, n.Initializer, d.Type(), d.StorageClass, nil) 2997 p.w(";") 2998 } 2999 f.condInitPrefix = sv 3000 p.w(";") 3001 default: 3002 var semi string 3003 switch { 3004 case block.noDecl: 3005 semi = "" 3006 default: 3007 p.w("var %s ", local.name) 3008 if !isAggregateTypeOrUnion(d.Type()) { 3009 p.w("%s ", p.typ(n, d.Type())) 3010 } 3011 semi = ";" 3012 } 3013 switch { 3014 case p.isConditionalInitializer(n.Initializer): 3015 p.w("%s", semi) 3016 sv := f.condInitPrefix 3017 f.condInitPrefix = func() { p.w("%s = ", local.name) } 3018 p.assignmentExpression(f, n.Initializer.AssignmentExpression, d.Type(), exprCondInit, 0) 3019 f.condInitPrefix = sv 3020 default: 3021 if block.noDecl { 3022 p.w("%s", local.name) 3023 } 3024 p.w(" = ") 3025 p.initializer(f, n.Initializer, d.Type(), d.StorageClass, nil) 3026 } 3027 p.w(";") 3028 } 3029 default: 3030 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 3031 } 3032 if !block.noDecl && local.forceRead && !local.isPinned { 3033 p.w("_ = %s;", local.name) 3034 } 3035 } 3036 3037 func (p *project) isConditionalInitializer(n *cc.Initializer) bool { 3038 return n.Case == cc.InitializerExpr && p.isConditionalAssignmentExpr(n.AssignmentExpression) 3039 } 3040 3041 func (p *project) isConditionalAssignmentExpr(n *cc.AssignmentExpression) bool { 3042 return n.Case == cc.AssignmentExpressionCond && 3043 n.ConditionalExpression.Case == cc.ConditionalExpressionCond 3044 } 3045 3046 func (p *project) initDeclaratorDeclVLA(f *function, n *cc.InitDeclarator, sep string) { 3047 d := n.Declarator 3048 local := f.locals[d] 3049 if strings.TrimSpace(sep) == "" { 3050 sep = "\n" 3051 } 3052 if local.isPinned { 3053 panic(todo("")) 3054 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()) 3055 return 3056 } 3057 3058 p.w("%s%s = %sXrealloc(%s, %s, types.Size_t(", sep, local.name, p.task.crt, f.tlsName, local.name) 3059 e := d.Type().LenExpr() 3060 p.assignmentExpression(f, e, e.Operand.Type(), exprValue, 0) 3061 if sz := d.Type().Elem().Size(); sz != 1 { 3062 p.w("*%d", sz) 3063 } 3064 p.w("));") 3065 } 3066 3067 func (p *project) initDeclaratorDecl(f *function, n *cc.InitDeclarator, sep string) { 3068 d := n.Declarator 3069 local := f.locals[d] 3070 if strings.TrimSpace(sep) == "" { 3071 sep = "\n" 3072 } 3073 if local.isPinned { 3074 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()) 3075 return 3076 } 3077 3078 p.w("%svar %s %s;", sep, local.name, p.typ(n, d.Type())) 3079 } 3080 3081 func (p *project) declarator(n cc.Node, f *function, d *cc.Declarator, t cc.Type, mode exprMode, flags flags) { 3082 switch mode { 3083 case exprLValue: 3084 p.declaratorLValue(n, f, d, t, mode, flags) 3085 case exprFunc: 3086 p.declaratorFunc(n, f, d, t, mode, flags) 3087 case exprValue: 3088 p.declaratorValue(n, f, d, t, mode, flags) 3089 case exprAddrOf: 3090 p.declaratorAddrOf(n, f, d, t, flags) 3091 case exprSelect: 3092 p.declaratorSelect(n, f, d) 3093 case exprDecay: 3094 p.declaratorDecay(n, f, d, t, mode, flags) 3095 default: 3096 panic(todo("", mode)) 3097 } 3098 } 3099 3100 func (p *project) declaratorDecay(n cc.Node, f *function, d *cc.Declarator, t cc.Type, mode exprMode, flags flags) { 3101 if d.Type().Kind() != cc.Array { 3102 panic(todo("", n.Position(), p.pos(d))) 3103 } 3104 3105 if f != nil { 3106 if local := f.locals[d]; local != nil { 3107 if d.Type().IsVLA() { 3108 switch { 3109 case local.isPinned: 3110 panic(todo("")) 3111 default: 3112 p.w("%s", local.name) 3113 return 3114 } 3115 } 3116 3117 if d.IsParameter { 3118 p.w("%s", local.name) 3119 return 3120 } 3121 3122 if p.pass1 { 3123 if !d.Type().IsVLA() { 3124 f.pin(n, d) 3125 } 3126 return 3127 } 3128 3129 if !local.isPinned { 3130 p.err(n, "%v: %v: missed pinning", n.Position(), d.Position(), d.Name()) 3131 } 3132 p.w("(%s%s)/* &%s[0] */", f.bpName, nonZeroUintptr(local.off), local.name) 3133 return 3134 } 3135 } 3136 3137 if x := p.tlds[d]; x != nil && d.IsStatic() { 3138 p.w("uintptr(unsafe.Pointer(&%s))", x.name) 3139 return 3140 } 3141 3142 switch x := p.symtab[d.Name().String()].(type) { 3143 case *tld: 3144 p.w("uintptr(unsafe.Pointer(&%s))", x.name) 3145 case *imported: 3146 x.used = true 3147 p.w("uintptr(unsafe.Pointer(&%sX%s))", x.qualifier, d.Name()) 3148 default: 3149 panic(todo("%v: %v: %q %T", n.Position(), p.pos(d), d.Name(), x)) 3150 } 3151 } 3152 3153 func (p *project) declaratorValue(n cc.Node, f *function, d *cc.Declarator, t cc.Type, mode exprMode, flags flags) { 3154 switch k := p.declaratorKind(d); k { 3155 case opNormal: 3156 p.declaratorValueNormal(n, f, d, t, mode, flags) 3157 case opArray: 3158 p.declaratorValueArray(n, f, d, t, mode, flags) 3159 case opFunction: 3160 p.declarator(n, f, d, t, exprAddrOf, flags) 3161 case opUnion: 3162 p.declaratorValueUnion(n, f, d, t, mode, flags) 3163 case opArrayParameter: 3164 p.declaratorValueArrayParameter(n, f, d, t, mode, flags) 3165 default: 3166 panic(todo("", d.Position(), k)) 3167 } 3168 } 3169 3170 func (p *project) declaratorValueArrayParameter(n cc.Node, f *function, d *cc.Declarator, t cc.Type, mode exprMode, flags flags) { 3171 if d.Type().IsScalarType() { 3172 defer p.w("%s", p.convertType(n, d.Type(), t, flags)) 3173 } 3174 local := f.locals[d] 3175 if local.isPinned { 3176 p.w("*(*%s)(unsafe.Pointer(%s%s/* %s */))", p.typ(n, paramTypeDecay(d)), f.bpName, nonZeroUintptr(local.off), local.name) 3177 return 3178 } 3179 3180 p.w("%s", local.name) 3181 } 3182 3183 func (p *project) declaratorValueUnion(n cc.Node, f *function, d *cc.Declarator, t cc.Type, mode exprMode, flags flags) { 3184 if d.Type().IsScalarType() { 3185 defer p.w("%s", p.convertType(n, d.Type(), t, flags)) 3186 } 3187 if f != nil { 3188 if local := f.locals[d]; local != nil { 3189 if local.isPinned { 3190 p.w("*(*%s)(unsafe.Pointer(%s%s/* %s */))", p.typ(d, d.Type()), f.bpName, nonZeroUintptr(local.off), local.name) 3191 return 3192 } 3193 3194 p.w("%s", local.name) 3195 return 3196 } 3197 } 3198 3199 p.declaratorDefault(n, d) 3200 } 3201 3202 func (p *project) isVolatileOrAtomic(d *cc.Declarator) bool { 3203 if d.Type().IsVolatile() || d.Type().IsAtomic() { 3204 return true 3205 } 3206 3207 _, ok := p.task.volatiles[d.Name()] 3208 return ok 3209 } 3210 3211 func (p *project) declaratorDefault(n cc.Node, d *cc.Declarator) { 3212 if x := p.tlds[d]; x != nil && d.IsStatic() { 3213 if p.isVolatileOrAtomic(d) { 3214 p.atomicLoadNamedAddr(n, d.Type(), x.name) 3215 return 3216 } 3217 3218 p.w("%s", x.name) 3219 return 3220 } 3221 3222 switch x := p.symtab[d.Name().String()].(type) { 3223 case *tld: 3224 if p.isVolatileOrAtomic(d) { 3225 p.atomicLoadNamedAddr(n, d.Type(), x.name) 3226 return 3227 } 3228 3229 p.w("%s", x.name) 3230 case *imported: 3231 x.used = true 3232 if p.isVolatileOrAtomic(d) { 3233 p.atomicLoadNamedAddr(n, d.Type(), fmt.Sprintf("%sX%s", x.qualifier, d.Name())) 3234 return 3235 } 3236 3237 p.w("%sX%s", x.qualifier, d.Name()) 3238 default: 3239 if d.IsExtern() { 3240 switch d.Name() { 3241 case idEnviron: 3242 if d.Type().String() == "pointer to pointer to char" { 3243 p.w("%sEnviron()", p.task.crt) 3244 return 3245 } 3246 } 3247 } 3248 3249 if d.Linkage == cc.External && p.task.nostdlib { 3250 p.w("X%s", d.Name()) 3251 return 3252 } 3253 3254 id := fmt.Sprintf("__builtin_%s", d.Name()) 3255 switch x := p.symtab[id].(type) { 3256 case *imported: 3257 x.used = true 3258 p.w("%sX%s", x.qualifier, d.Name()) 3259 return 3260 } 3261 3262 if !d.IsImplicit() { 3263 nm := d.Name() 3264 name := nm.String() 3265 switch d.Linkage { 3266 case cc.External: 3267 name = p.task.exportExterns + name 3268 tld := &tld{name: name} 3269 p.externs[nm] = tld 3270 p.w("%s", name) 3271 return 3272 case cc.Internal: 3273 if token.IsExported(name) { 3274 name = "s" + name 3275 } 3276 tld := &tld{name: p.scope.take(cc.String(name))} 3277 for _, v := range p.ast.Scope[nm] { 3278 if d, ok := v.(*cc.Declarator); ok { 3279 p.tlds[d] = tld 3280 } 3281 } 3282 p.w("%s", name) 3283 return 3284 } 3285 } 3286 3287 p.err(n, "back-end: undefined: %s", d.Name()) 3288 } 3289 } 3290 3291 func (p *project) declaratorValueArray(n cc.Node, f *function, d *cc.Declarator, t cc.Type, mode exprMode, flags flags) { 3292 if t.IsIntegerType() { 3293 defer p.w("%s", p.convertType(n, nil, t, flags)) 3294 } 3295 if f != nil { 3296 if local := f.locals[d]; local != nil { 3297 if local.isPinned { 3298 p.w("(%s%s)/* %s */", f.bpName, nonZeroUintptr(local.off), local.name) 3299 return 3300 } 3301 3302 p.w("%s", local.name) 3303 return 3304 } 3305 } 3306 3307 p.declaratorDefault(n, d) 3308 } 3309 3310 func (p *project) declaratorValueNormal(n cc.Node, f *function, d *cc.Declarator, t cc.Type, mode exprMode, flags flags) { 3311 if d.Type().IsScalarType() { 3312 defer p.w("%s", p.convertType(n, d.Type(), t, flags)) 3313 } 3314 if f != nil { 3315 if local := f.locals[d]; local != nil { 3316 if local.isPinned { 3317 if p.isVolatileOrAtomic(d) && d.IsParameter && d.Write != 0 { 3318 p.w("%sAtomicLoadP%s(%s%s/* %s */)", p.task.crt, p.helperType(n, d.Type()), f.bpName, nonZeroUintptr(local.off), local.name) 3319 return 3320 } 3321 3322 p.w("*(*%s)(unsafe.Pointer(%s%s/* %s */))", p.typ(d, d.Type()), f.bpName, nonZeroUintptr(local.off), local.name) 3323 return 3324 } 3325 3326 if p.isVolatileOrAtomic(d) && d.IsParameter && d.Write != 0 { 3327 p.atomicLoadNamedAddr(n, d.Type(), local.name) 3328 return 3329 } 3330 3331 p.w("%s", local.name) 3332 return 3333 } 3334 } 3335 3336 p.declaratorDefault(n, d) 3337 } 3338 3339 func (p *project) declaratorFunc(n cc.Node, f *function, d *cc.Declarator, t cc.Type, mode exprMode, flags flags) { 3340 switch k := p.declaratorKind(d); k { 3341 case opFunction: 3342 p.declaratorFuncFunc(n, f, d, t, exprValue, flags) 3343 case opNormal: 3344 p.declaratorFuncNormal(n, f, d, t, exprValue, flags) 3345 default: 3346 panic(todo("", d.Position(), k)) 3347 } 3348 } 3349 3350 func (p *project) declaratorFuncNormal(n cc.Node, f *function, d *cc.Declarator, t cc.Type, mode exprMode, flags flags) { 3351 u := d.Type() 3352 if u.Kind() == cc.Ptr { 3353 u = u.Elem() 3354 } 3355 switch u.Kind() { 3356 case cc.Function: 3357 if local := f.locals[d]; local != nil { 3358 if local.isPinned { 3359 p.w("(*(*") 3360 p.functionSignature(n, f, u, "") 3361 p.w(")(unsafe.Pointer(%s%s)))", f.bpName, nonZeroUintptr(local.off)) 3362 return 3363 } 3364 3365 if d.IsParameter { 3366 p.w("(*(*") 3367 p.functionSignature(n, f, u, "") 3368 p.w(")(unsafe.Pointer(&%s)))", local.name) 3369 return 3370 } 3371 3372 panic(todo("", p.pos(d))) 3373 } 3374 3375 if x := p.tlds[d]; x != nil && d.IsStatic() { 3376 p.w("(*(*") 3377 p.functionSignature(n, f, u, "") 3378 p.w(")(unsafe.Pointer(&%s)))", x.name) 3379 return 3380 } 3381 3382 switch x := p.symtab[d.Name().String()].(type) { 3383 case *tld: 3384 p.w("(*(*") 3385 p.functionSignature(n, f, u, "") 3386 p.w(")(unsafe.Pointer(&%s)))", x.name) 3387 case *imported: 3388 x.used = true 3389 p.w("uintptr(unsafe.Pointer(&%sX%s))", x.qualifier, d.Name()) 3390 default: 3391 panic(todo("%v: %v: %q", n.Position(), p.pos(d), d.Name())) 3392 } 3393 default: 3394 panic(todo("", p.pos(d), u)) 3395 } 3396 } 3397 3398 func (p *project) declaratorFuncFunc(n cc.Node, f *function, d *cc.Declarator, t cc.Type, mode exprMode, flags flags) { 3399 switch d.Type().Kind() { 3400 case cc.Function: 3401 // ok 3402 default: 3403 panic(todo("", p.pos(d), d.Type(), d.Type().Kind())) 3404 } 3405 3406 if f != nil { 3407 if local := f.locals[d]; local != nil { 3408 if local.isPinned { 3409 panic(todo("")) 3410 } 3411 3412 p.w(" %s", local.name) 3413 return 3414 } 3415 } 3416 3417 p.declaratorDefault(n, d) 3418 } 3419 3420 func (p *project) declaratorLValue(n cc.Node, f *function, d *cc.Declarator, t cc.Type, mode exprMode, flags flags) { 3421 switch k := p.declaratorKind(d); k { 3422 case opNormal, opArrayParameter, opUnion: 3423 p.declaratorLValueNormal(n, f, d, t, mode, flags) 3424 case opArray: 3425 p.declaratorLValueArray(n, f, d, t, mode, flags) 3426 default: 3427 panic(todo("", d.Position(), k)) 3428 } 3429 } 3430 3431 func (p *project) declaratorLValueArray(n cc.Node, f *function, d *cc.Declarator, t cc.Type, mode exprMode, flags flags) { 3432 if f != nil { 3433 if local := f.locals[d]; local != nil { 3434 if local.isPinned { 3435 p.w("*(*%s)(unsafe.Pointer(%s%s/* %s */))", p.typ(d, d.Type()), f.bpName, nonZeroUintptr(local.off), local.name) 3436 return 3437 } 3438 3439 p.w("%s", local.name) 3440 return 3441 } 3442 } 3443 3444 p.declaratorDefault(n, d) 3445 } 3446 3447 func (p *project) declaratorLValueNormal(n cc.Node, f *function, d *cc.Declarator, t cc.Type, mode exprMode, flags flags) { 3448 if p.isVolatileOrAtomic(d) { 3449 panic(todo("", n.Position(), d.Position())) 3450 } 3451 3452 if d.Type().IsScalarType() { 3453 defer p.w("%s", p.convertType(n, d.Type(), t, flags)) 3454 } 3455 if f != nil { 3456 if local := f.locals[d]; local != nil { 3457 if local.isPinned { 3458 p.w("*(*%s)(unsafe.Pointer(%s%s/* %s */))", p.dtyp(d), f.bpName, nonZeroUintptr(local.off), local.name) 3459 return 3460 } 3461 3462 p.w("%s", local.name) 3463 return 3464 } 3465 } 3466 3467 p.declaratorLValueDefault(n, d) 3468 } 3469 3470 func (p *project) declaratorLValueDefault(n cc.Node, d *cc.Declarator) { 3471 if x := p.tlds[d]; x != nil && d.IsStatic() { 3472 p.w("%s", x.name) 3473 return 3474 } 3475 3476 switch x := p.symtab[d.Name().String()].(type) { 3477 case *tld: 3478 p.w("%s", x.name) 3479 case *imported: 3480 x.used = true 3481 p.w("%sX%s", x.qualifier, d.Name()) 3482 default: 3483 if d.IsExtern() { 3484 switch d.Name() { 3485 case idEnviron: 3486 if d.Type().String() == "pointer to pointer to char" { 3487 p.w("*(*uintptr)(unsafe.Pointer(%sEnvironP()))", p.task.crt) 3488 return 3489 } 3490 } 3491 } 3492 3493 panic(todo("%v: %v: %q", n.Position(), p.pos(d), d.Name())) 3494 } 3495 } 3496 3497 func (p *project) declaratorKind(d *cc.Declarator) opKind { 3498 switch { 3499 case p.isArrayParameterDeclarator(d): 3500 return opArrayParameter 3501 case !p.pass1 && p.isArrayDeclarator(d): 3502 return opArray 3503 case d.Type().Kind() == cc.Function && !d.IsParameter: 3504 return opFunction 3505 case d.Type().Kind() == cc.Union: 3506 return opUnion 3507 default: 3508 return opNormal 3509 } 3510 } 3511 3512 func (p *project) declaratorSelect(n cc.Node, f *function, d *cc.Declarator) { 3513 switch k := p.declaratorKind(d); k { 3514 case opNormal: 3515 p.declaratorSelectNormal(n, f, d) 3516 case opArray: 3517 p.declaratorSelectArray(n, f, d) 3518 default: 3519 panic(todo("", d.Position(), k)) 3520 } 3521 } 3522 3523 func (p *project) declaratorSelectArray(n cc.Node, f *function, d *cc.Declarator) { 3524 if local := f.locals[d]; local != nil { 3525 if local.isPinned { 3526 panic(todo("", p.pos(n))) 3527 //TODO type error 3528 p.w("(*%s)(unsafe.Pointer(%s%s/* &%s */))", p.typ(d, d.Type()), f.bpName, nonZeroUintptr(local.off), local.name) 3529 return 3530 } 3531 3532 p.w("%s", local.name) 3533 return 3534 } 3535 3536 p.declaratorDefault(n, d) 3537 } 3538 3539 func (p *project) declaratorSelectNormal(n cc.Node, f *function, d *cc.Declarator) { 3540 if local := f.locals[d]; local != nil { 3541 if local.isPinned { 3542 p.w("(*%s)(unsafe.Pointer(%s%s/* &%s */))", p.typ(d, d.Type()), f.bpName, nonZeroUintptr(local.off), local.name) 3543 return 3544 } 3545 3546 p.w("%s", local.name) 3547 return 3548 } 3549 3550 p.declaratorDefault(n, d) 3551 } 3552 3553 func (p *project) declaratorAddrOf(n cc.Node, f *function, d *cc.Declarator, t cc.Type, flags flags) { 3554 switch k := p.declaratorKind(d); k { 3555 case opArray: 3556 p.declaratorAddrOfArray(n, f, d) 3557 case opNormal: 3558 p.declaratorAddrOfNormal(n, f, d, flags) 3559 case opUnion: 3560 p.declaratorAddrOfUnion(n, f, d) 3561 case opFunction: 3562 p.declaratorAddrOfFunction(n, f, d) 3563 case opArrayParameter: 3564 p.declaratorAddrOfArrayParameter(n, f, d) 3565 default: 3566 panic(todo("", d.Position(), k)) 3567 } 3568 } 3569 3570 func (p *project) declaratorAddrOfArrayParameter(n cc.Node, f *function, d *cc.Declarator) { 3571 if p.pass1 { 3572 f.pin(n, d) 3573 return 3574 } 3575 3576 local := f.locals[d] 3577 p.w("(%s%s)/* &%s */", f.bpName, nonZeroUintptr(local.off), local.name) 3578 } 3579 3580 func (p *project) declaratorAddrOfFunction(n cc.Node, f *function, d *cc.Declarator) { 3581 if d.Type().Kind() != cc.Function { 3582 panic(todo("", p.pos(n))) 3583 } 3584 3585 if x := p.tlds[d]; x != nil && d.IsStatic() { 3586 p.w("*(*uintptr)(unsafe.Pointer(&struct{f ") 3587 p.functionSignature(n, f, d.Type(), "") 3588 p.w("}{%s}))", x.name) 3589 return 3590 } 3591 3592 switch x := p.symtab[d.Name().String()].(type) { 3593 case *tld: 3594 p.w("*(*uintptr)(unsafe.Pointer(&struct{f ") 3595 p.functionSignature(n, f, d.Type(), "") 3596 p.w("}{%s}))", x.name) 3597 case *imported: 3598 x.used = true 3599 p.w("*(*uintptr)(unsafe.Pointer(&struct{f ") 3600 p.functionSignature(n, f, d.Type(), "") 3601 p.w("}{%sX%s}))", x.qualifier, d.Name()) 3602 default: 3603 p.err(d, "back-end: undefined: %s", d.Name()) 3604 } 3605 } 3606 3607 func (p *project) declaratorAddrOfUnion(n cc.Node, f *function, d *cc.Declarator) { 3608 if f != nil { 3609 if local := f.locals[d]; local != nil { 3610 if p.pass1 { 3611 f.pin(n, d) 3612 return 3613 } 3614 3615 if local.isPinned { 3616 p.w("(%s%s)/* &%s */", f.bpName, nonZeroUintptr(local.off), local.name) 3617 return 3618 } 3619 3620 panic(todo("", p.pos(n))) 3621 } 3622 } 3623 3624 if x := p.tlds[d]; x != nil && d.IsStatic() { 3625 p.w("uintptr(unsafe.Pointer(&%s))", x.name) 3626 return 3627 } 3628 3629 switch x := p.symtab[d.Name().String()].(type) { 3630 case *tld: 3631 p.w("uintptr(unsafe.Pointer(&%s))", x.name) 3632 case *imported: 3633 x.used = true 3634 p.w("uintptr(unsafe.Pointer(&%sX%s))", x.qualifier, d.Name()) 3635 default: 3636 panic(todo("%v: %v: %q", n.Position(), p.pos(d), d.Name())) 3637 } 3638 } 3639 3640 func (p *project) declaratorAddrOfNormal(n cc.Node, f *function, d *cc.Declarator, flags flags) { 3641 if f != nil { 3642 if local := f.locals[d]; local != nil { 3643 if p.pass1 && flags&fAddrOfFuncPtrOk == 0 { 3644 f.pin(n, d) 3645 return 3646 } 3647 3648 if local.isPinned { 3649 p.w("(%s%s)/* &%s */", f.bpName, nonZeroUintptr(local.off), local.name) 3650 return 3651 } 3652 3653 if flags&fAddrOfFuncPtrOk != 0 { 3654 if dt := d.Type(); dt.Kind() == cc.Ptr { 3655 if elem := dt.Elem(); elem.Kind() == cc.Function || elem.Kind() == cc.Ptr && elem.Elem().Kind() == cc.Function { 3656 p.w("&%s", local.name) 3657 return 3658 } 3659 } 3660 } 3661 3662 panic(todo("", p.pos(n), p.pos(d), d.Name(), d.Type(), d.IsParameter, d.AddressTaken, flags&fAddrOfFuncPtrOk != 0)) 3663 } 3664 } 3665 3666 if x := p.tlds[d]; x != nil && d.IsStatic() { 3667 p.w("uintptr(unsafe.Pointer(&%s))", x.name) 3668 return 3669 } 3670 3671 switch x := p.symtab[d.Name().String()].(type) { 3672 case *tld: 3673 p.w("uintptr(unsafe.Pointer(&%s))", x.name) 3674 case *imported: 3675 x.used = true 3676 p.w("uintptr(unsafe.Pointer(&%sX%s))", x.qualifier, d.Name()) 3677 default: 3678 p.err(n, "undefined: %s", d.Name()) 3679 } 3680 } 3681 3682 func (p *project) declaratorAddrOfArray(n cc.Node, f *function, d *cc.Declarator) { 3683 if f != nil { 3684 if local := f.locals[d]; local != nil { 3685 if p.pass1 { 3686 f.pin(n, d) 3687 return 3688 } 3689 3690 if local.isPinned { 3691 p.w("(%s%s)/* &%s */", f.bpName, nonZeroUintptr(local.off), local.name) 3692 return 3693 } 3694 3695 panic(todo("", p.pos(d), d.Name(), d.Type(), d.IsParameter)) 3696 } 3697 } 3698 3699 if x := p.tlds[d]; x != nil && d.IsStatic() { 3700 p.w("uintptr(unsafe.Pointer(&%s))", x.name) 3701 return 3702 } 3703 3704 switch x := p.symtab[d.Name().String()].(type) { 3705 case *tld: 3706 p.w("uintptr(unsafe.Pointer(&%s))", x.name) 3707 case *imported: 3708 x.used = true 3709 p.w("uintptr(unsafe.Pointer(&%sX%s))", x.qualifier, d.Name()) 3710 default: 3711 panic(todo("%v: %v: %q", n.Position(), p.pos(d), d.Name())) 3712 } 3713 } 3714 3715 func (p *project) convertType(n cc.Node, from, to cc.Type, flags flags) string { 3716 // trc("%v: %v: %v -> %v %v", n.Position(), origin(1), from, to, flags) //TODO- DBG 3717 if from != nil { 3718 switch from.Kind() { 3719 case cc.Int128: 3720 return p.convertTypeFromInt128(n, to, flags) 3721 case cc.UInt128: 3722 return p.convertTypeFromUint128(n, to, flags) 3723 } 3724 } 3725 3726 switch to.Kind() { 3727 case cc.Int128: 3728 return p.convertTypeToInt128(n, from, flags) 3729 case cc.UInt128: 3730 return p.convertTypeToUint128(n, from, flags) 3731 } 3732 3733 // trc("%v: %v -> %v\n%s", p.pos(n), from, to, debug.Stack()[:600]) //TODO- 3734 force := flags&fForceConv != 0 3735 if from == nil { 3736 p.w("%s(", p.typ(n, to)) 3737 return ")" 3738 } 3739 3740 if from.IsScalarType() { 3741 switch { 3742 case force: 3743 p.w("%s(", p.helperType2(n, from, to)) 3744 return ")" 3745 case from.Kind() == to.Kind(): 3746 return "" 3747 default: 3748 p.w("%s(", p.typ(n, to)) 3749 return ")" 3750 } 3751 } 3752 3753 switch from.Kind() { 3754 case cc.Function, cc.Struct, cc.Union, cc.Ptr, cc.Array: 3755 if from.Kind() == to.Kind() { 3756 return "" 3757 } 3758 3759 panic(todo("", n.Position(), from, to, from.Alias(), to.Alias())) 3760 case cc.Double, cc.Float: 3761 p.w("%s(", p.typ(n, to)) 3762 return ")" 3763 } 3764 3765 panic(todo("", n.Position(), from, to, from.Alias(), to.Alias())) 3766 } 3767 3768 func (p *project) convertTypeFromInt128(n cc.Node, to cc.Type, flags flags) string { 3769 switch k := to.Kind(); { 3770 case k == cc.Float, k == cc.Double: 3771 p.w("(") 3772 return fmt.Sprintf(").Float%d()", to.Size()*8) 3773 case k == cc.Int128: 3774 return "" 3775 case k == cc.UInt128: 3776 p.w("%sUint128FromInt128(", p.task.crt) 3777 return ")" 3778 case to.IsIntegerType() && to.IsSignedType(): 3779 p.w("int%d((", to.Size()*8) 3780 return ").Lo)" 3781 case to.IsIntegerType() && !to.IsSignedType(): 3782 p.w("uint%d((", to.Size()*8) 3783 return ").Lo)" 3784 default: 3785 panic(todo("", n.Position(), to, to.Alias())) 3786 } 3787 } 3788 3789 func (p *project) convertTypeFromUint128(n cc.Node, to cc.Type, flags flags) string { 3790 switch k := to.Kind(); { 3791 case k == cc.Float, k == cc.Double: 3792 p.w("(") 3793 return fmt.Sprintf(").Float%d()", to.Size()*8) 3794 case k == cc.Int128: 3795 p.w("(") 3796 return ").Int128()" 3797 case k == cc.UInt128: 3798 return "" 3799 case to.IsIntegerType() && to.IsSignedType(): 3800 p.w("int%d((", to.Size()*8) 3801 return ").Lo)" 3802 case to.IsIntegerType() && !to.IsSignedType(): 3803 p.w("uint%d((", to.Size()*8) 3804 return ").Lo)" 3805 default: 3806 panic(todo("", n.Position(), to, to.Alias())) 3807 } 3808 } 3809 3810 func (p *project) convertTypeToInt128(n cc.Node, from cc.Type, flags flags) string { 3811 switch k := from.Kind(); { 3812 case k == cc.Float, k == cc.Double: 3813 p.w("%sInt128FromFloat%d(", p.task.crt, from.Size()*8) 3814 return ")" 3815 case k == cc.Int128: 3816 return "" 3817 case k == cc.UInt128: 3818 p.w("%sInt128FromUint128(", p.task.crt) 3819 return ")" 3820 case from.IsIntegerType() && from.IsSignedType(): 3821 p.w("%sInt128FromInt%d(", p.task.crt, from.Size()*8) 3822 return ")" 3823 case from.IsIntegerType() && !from.IsSignedType(): 3824 p.w("%sInt128FromUint%d(", p.task.crt, from.Size()*8) 3825 return ")" 3826 default: 3827 panic(todo("", n.Position(), from, from.Alias())) 3828 } 3829 } 3830 3831 func (p *project) convertTypeToUint128(n cc.Node, from cc.Type, flags flags) string { 3832 switch k := from.Kind(); { 3833 case k == cc.Float, k == cc.Double: 3834 p.w("%sUint128FromFloat%d(", p.task.crt, from.Size()*8) 3835 return ")" 3836 case k == cc.Int128: 3837 p.w("(") 3838 return ").Uint128()" 3839 case k == cc.UInt128: 3840 return "" 3841 case from.IsIntegerType() && from.IsSignedType(): 3842 p.w("%sUint128FromInt%d(", p.task.crt, from.Size()*8) 3843 return ")" 3844 case from.IsIntegerType() && !from.IsSignedType(): 3845 p.w("%sUint128FromUint%d(", p.task.crt, from.Size()*8) 3846 return ")" 3847 default: 3848 panic(todo("", n.Position(), from, from.Alias())) 3849 } 3850 } 3851 3852 func (p *project) convertFromInt128(n cc.Node, op cc.Operand, to cc.Type, flags flags) string { 3853 switch k := to.Kind(); { 3854 case k == cc.Float, k == cc.Double: 3855 p.w("(") 3856 return fmt.Sprintf(").Float%d()", to.Size()*8) 3857 case k == cc.Int128: 3858 return "" 3859 case k == cc.UInt128: 3860 p.w("(") 3861 return ").Uint128()" 3862 case to.IsIntegerType() && to.IsSignedType(): 3863 p.w("%sInt%d(", p.task.crt, to.Size()*8) 3864 return ")" 3865 case to.IsIntegerType() && !to.IsSignedType(): 3866 p.w("%sUint%d(", p.task.crt, to.Size()*8) 3867 return ")" 3868 default: 3869 panic(todo("", n.Position(), to, to.Alias())) 3870 } 3871 } 3872 3873 func (p *project) convertFromUint128(n cc.Node, op cc.Operand, to cc.Type, flags flags) string { 3874 switch k := to.Kind(); { 3875 case k == cc.Float, k == cc.Double: 3876 p.w("%sUint128FromFloat%d(", p.task.crt, to.Size()*8) 3877 return ")" 3878 case k == cc.Int128: 3879 p.w("(") 3880 return ").Int128()" 3881 case k == cc.UInt128: 3882 return "" 3883 case to.IsIntegerType() && to.IsSignedType(): 3884 p.w("%sInt%d(", p.task.crt, to.Size()*8) 3885 return ")" 3886 case to.IsIntegerType() && !to.IsSignedType(): 3887 p.w("%sUint%d(", p.task.crt, to.Size()*8) 3888 return ")" 3889 default: 3890 panic(todo("", n.Position(), to, to.Alias())) 3891 } 3892 } 3893 3894 func (p *project) convertToInt128(n cc.Node, op cc.Operand, to cc.Type, flags flags) string { 3895 from := op.Type() 3896 switch k := from.Kind(); { 3897 case k == cc.Float, k == cc.Double: 3898 p.w("%sInt128FromFloat%d(", p.task.crt, from.Size()*8) 3899 return ")" 3900 case k == cc.Int128: 3901 return "" 3902 case k == cc.UInt128: 3903 p.w("(") 3904 return ").Int128()" 3905 case from.IsIntegerType() && from.IsSignedType(): 3906 p.w("%sInt128FromInt%d(", p.task.crt, from.Size()*8) 3907 return ")" 3908 case from.IsIntegerType() && !from.IsSignedType(): 3909 p.w("%sInt128FromUint%d(", p.task.crt, from.Size()*8) 3910 return ")" 3911 default: 3912 panic(todo("", n.Position(), from, from.Alias())) 3913 } 3914 } 3915 3916 func (p *project) convertToUint128(n cc.Node, op cc.Operand, to cc.Type, flags flags) string { 3917 from := op.Type() 3918 switch k := from.Kind(); { 3919 case k == cc.Float, k == cc.Double: 3920 p.w("%sUint128FromFloat%d(", p.task.crt, from.Size()*8) 3921 return ")" 3922 case k == cc.Int128: 3923 p.w("(") 3924 return ").Uint128()" 3925 case k == cc.UInt128: 3926 return "" 3927 case from.IsIntegerType() && from.IsSignedType(): 3928 p.w("%sUint128FromInt%d(", p.task.crt, from.Size()*8) 3929 return ")" 3930 case from.IsIntegerType() && !from.IsSignedType(): 3931 p.w("%sUint128FromUint%d(", p.task.crt, from.Size()*8) 3932 return ")" 3933 default: 3934 panic(todo("", n.Position(), from, from.Alias())) 3935 } 3936 } 3937 3938 func (p *project) convertNil(n cc.Node, to cc.Type, flags flags) string { 3939 switch to.Kind() { 3940 case cc.Int128: 3941 panic(todo("", p.pos(n))) 3942 case cc.UInt128: 3943 panic(todo("", p.pos(n))) 3944 } 3945 3946 p.w("%s(", p.typ(n, to)) 3947 return ")" 3948 } 3949 3950 func (p *project) convert(n cc.Node, op cc.Operand, to cc.Type, flags flags) string { 3951 if op == nil { 3952 panic(todo("internal error")) 3953 } 3954 3955 from := op.Type() 3956 switch from.Kind() { 3957 case cc.Int128: 3958 return p.convertFromInt128(n, op, to, flags) 3959 case cc.UInt128: 3960 return p.convertFromUint128(n, op, to, flags) 3961 } 3962 switch to.Kind() { 3963 case cc.Int128: 3964 return p.convertToInt128(n, op, to, flags) 3965 case cc.UInt128: 3966 return p.convertToUint128(n, op, to, flags) 3967 } 3968 3969 if flags&fForceRuntimeConv != 0 { 3970 flags |= fForceConv 3971 } 3972 force := flags&fForceConv != 0 3973 if !force && from.IsScalarType() && from.Kind() == to.Kind() { 3974 return "" 3975 } 3976 3977 if from.IsIntegerType() { 3978 return p.convertInt(n, op, to, flags) 3979 } 3980 3981 if from == to { 3982 return "" 3983 } 3984 3985 switch from.Kind() { 3986 case cc.Ptr: 3987 if !force && from.Kind() == to.Kind() { 3988 return "" 3989 } 3990 3991 if to.IsIntegerType() { 3992 p.w("%s(", p.typ(n, to)) 3993 return ")" 3994 } 3995 3996 if to.Kind() == cc.Ptr { 3997 return "" 3998 } 3999 4000 panic(todo("%v: force %v, %q %v -> %q %v", p.pos(n), force, from, from.Kind(), to, to.Kind())) 4001 case cc.Function, cc.Struct, cc.Union: 4002 if !force && from.Kind() == to.Kind() { 4003 return "" 4004 } 4005 4006 trc("%p %p", from, to) 4007 panic(todo("%q %v -> %q %v", from, from.Kind(), to, to.Kind())) 4008 case cc.Double, cc.Float: 4009 switch { 4010 case to.IsIntegerType(): 4011 p.w("%s(", p.helperType2(n, from, to)) 4012 return ")" 4013 default: 4014 p.w("%s(", p.typ(n, to)) 4015 return ")" 4016 } 4017 case cc.Array: 4018 if from.Kind() == to.Kind() { 4019 return "" 4020 } 4021 4022 switch to.Kind() { 4023 case cc.Ptr: 4024 return "" 4025 } 4026 4027 panic(todo("%q, %v -> %q, %v", from, from.Kind(), to.Kind())) 4028 } 4029 4030 panic(todo("%q -> %q", from, to)) 4031 } 4032 4033 func (p *project) convertInt(n cc.Node, op cc.Operand, to cc.Type, flags flags) string { 4034 from := op.Type() 4035 switch from.Kind() { 4036 case cc.Int128: 4037 panic(todo("", p.pos(n))) 4038 case cc.UInt128: 4039 panic(todo("", p.pos(n))) 4040 } 4041 switch to.Kind() { 4042 case cc.Int128: 4043 panic(todo("", p.pos(n))) 4044 case cc.UInt128: 4045 panic(todo("", p.pos(n))) 4046 } 4047 4048 force := flags&fForceConv != 0 4049 value := op.Value() 4050 if value == nil || !to.IsIntegerType() { 4051 if to.IsScalarType() { 4052 p.w("%s(", p.typ(n, to)) 4053 return ")" 4054 } 4055 4056 panic(todo("", op.Type(), to)) 4057 } 4058 4059 if flags&fForceRuntimeConv != 0 { 4060 p.w("%s(", p.helperType2(n, op.Type(), to)) 4061 return ")" 4062 } 4063 4064 switch { 4065 case from.IsSignedType(): 4066 switch { 4067 case to.IsSignedType(): 4068 switch x := value.(type) { 4069 case cc.Int64Value: 4070 switch to.Size() { 4071 case 1: 4072 if x >= math.MinInt8 && x <= math.MaxInt8 { 4073 switch { 4074 case !force && from.Size() == to.Size(): 4075 return "" 4076 default: 4077 p.w("int8(") 4078 return ")" 4079 } 4080 } 4081 4082 p.w("%sInt8FromInt%d(", p.task.crt, from.Size()*8) 4083 return ")" 4084 case 2: 4085 if x >= math.MinInt16 && x <= math.MaxInt16 { 4086 switch { 4087 case !force && from.Size() == to.Size(): 4088 return "" 4089 default: 4090 p.w("int16(") 4091 return ")" 4092 } 4093 } 4094 4095 p.w("%sInt16FromInt%d(", p.task.crt, from.Size()*8) 4096 return ")" 4097 case 4: 4098 if x >= math.MinInt32 && x <= math.MaxInt32 { 4099 switch { 4100 case !force && from.Size() == to.Size(): 4101 return "" 4102 default: 4103 p.w("int32(") 4104 return ")" 4105 } 4106 } 4107 4108 p.w("%sInt32FromInt%d(", p.task.crt, from.Size()*8) 4109 return ")" 4110 case 8: 4111 switch { 4112 case !force && from.Size() == to.Size(): 4113 return "" 4114 default: 4115 p.w("int64(") 4116 return ")" 4117 } 4118 default: 4119 panic(todo("%T(%v) %v -> %v", x, op.Value(), from, to)) 4120 } 4121 default: 4122 panic(todo("%T(%v) %v -> %v", x, op.Value(), from, to)) 4123 } 4124 default: // to is unsigned 4125 switch x := value.(type) { 4126 case cc.Int64Value: 4127 switch to.Size() { 4128 case 1: 4129 if x >= 0 && x <= math.MaxUint8 { 4130 p.w("%s(", p.typ(n, to)) 4131 return ")" 4132 } 4133 4134 p.w("%sUint8FromInt%d(", p.task.crt, from.Size()*8) 4135 return ")" 4136 case 2: 4137 if x >= 0 && x <= math.MaxUint16 { 4138 p.w("%s(", p.typ(n, to)) 4139 return ")" 4140 } 4141 4142 p.w("%sUint16FromInt%d(", p.task.crt, from.Size()*8) 4143 return ")" 4144 case 4: 4145 if x >= 0 && x <= math.MaxUint32 { 4146 p.w("%s(", p.typ(n, to)) 4147 return ")" 4148 } 4149 4150 p.w("%sUint32FromInt%d(", p.task.crt, from.Size()*8) 4151 return ")" 4152 case 8: 4153 if x >= 0 { 4154 p.w("uint64(") 4155 return ")" 4156 } 4157 4158 p.w("%sUint64FromInt%d(", p.task.crt, from.Size()*8) 4159 return ")" 4160 default: 4161 panic(todo("%T(%v) %v -> %v", x, op.Value(), from, to)) 4162 } 4163 case cc.Uint64Value: 4164 switch to.Size() { 4165 case 1: 4166 if x <= math.MaxUint8 { 4167 p.w("%s(", p.typ(n, to)) 4168 return ")" 4169 } 4170 4171 p.w("%sUint8FromUint%d(", p.task.crt, from.Size()*8) 4172 return ")" 4173 case 2: 4174 if x <= math.MaxUint16 { 4175 p.w("%s(", p.typ(n, to)) 4176 return ")" 4177 } 4178 4179 p.w("%sUint16FromUint%d(", p.task.crt, from.Size()*8) 4180 return ")" 4181 case 4: 4182 if x <= math.MaxUint32 { 4183 p.w("%s(", p.typ(n, to)) 4184 return ")" 4185 } 4186 4187 p.w("%sUint32FromUint%d(", p.task.crt, from.Size()*8) 4188 return ")" 4189 case 8: 4190 p.w("uint64(") 4191 return ")" 4192 default: 4193 panic(todo("%T(%v) %v -> %v", x, op.Value(), from, to)) 4194 } 4195 default: 4196 panic(todo("%T(%v) %v -> %v", x, op.Value(), from, to)) 4197 } 4198 } 4199 default: // from is unsigned 4200 switch { 4201 case to.IsSignedType(): 4202 switch x := value.(type) { 4203 case cc.Uint64Value: 4204 switch to.Size() { 4205 case 1: 4206 if x <= math.MaxInt8 { 4207 p.w("int8(") 4208 return ")" 4209 } 4210 4211 p.w("%sInt8FromUint%d(", p.task.crt, from.Size()*8) 4212 return ")" 4213 case 2: 4214 if x <= math.MaxInt16 { 4215 p.w("int16(") 4216 return ")" 4217 } 4218 4219 p.w("%sInt16FromUint%d(", p.task.crt, from.Size()*8) 4220 return ")" 4221 case 4: 4222 if x <= math.MaxInt32 { 4223 p.w("int32(") 4224 return ")" 4225 } 4226 4227 p.w("%sInt32FromUint%d(", p.task.crt, from.Size()*8) 4228 return ")" 4229 case 8: 4230 if x <= math.MaxInt64 { 4231 p.w("int64(") 4232 return ")" 4233 } 4234 4235 p.w("%sInt64FromUint%d(", p.task.crt, from.Size()*8) 4236 return ")" 4237 default: 4238 panic(todo("%T(%v) %v -> %v", x, op.Value(), from, to)) 4239 } 4240 default: 4241 panic(todo("%T(%v) %v -> %v", x, op.Value(), from, to)) 4242 } 4243 default: // to is unsigned 4244 switch x := value.(type) { 4245 case cc.Uint64Value: 4246 switch to.Size() { 4247 case 1: 4248 if x <= math.MaxUint8 { 4249 switch { 4250 case !force && from.Size() == 1: 4251 return "" 4252 default: 4253 p.w("uint8(") 4254 return ")" 4255 } 4256 } 4257 4258 p.w("%sUint8FromUint%d(", p.task.crt, from.Size()*8) 4259 return ")" 4260 case 2: 4261 if x <= math.MaxUint16 { 4262 switch { 4263 case !force && from.Size() == 2: 4264 return "" 4265 default: 4266 p.w("uint16(") 4267 return ")" 4268 } 4269 } 4270 4271 p.w("%sUint16FromUint%d(", p.task.crt, from.Size()*8) 4272 return ")" 4273 case 4: 4274 if x <= math.MaxUint32 { 4275 switch { 4276 case !force && from.Size() == 4: 4277 return "" 4278 default: 4279 p.w("uint32(") 4280 return ")" 4281 } 4282 } 4283 4284 p.w("%sUint32FromUint%d(", p.task.crt, from.Size()*8) 4285 return ")" 4286 case 8: 4287 switch { 4288 case !force && from.Size() == 8: 4289 return "" 4290 default: 4291 p.w("uint64(") 4292 return ")" 4293 } 4294 default: 4295 panic(todo("%T(%v) %v -> %v", x, op.Value(), from, to)) 4296 } 4297 default: 4298 panic(todo("%T(%v) %v -> %v", x, op.Value(), from, to)) 4299 } 4300 } 4301 } 4302 } 4303 4304 func nonZeroUintptr(n uintptr) string { 4305 if n == 0 { 4306 return "" 4307 } 4308 4309 return fmt.Sprintf("%+d", n) 4310 } 4311 4312 func alias(attr []*cc.AttributeSpecifier) (r cc.StringID) { 4313 for _, v := range attr { 4314 cc.Inspect(v, func(n cc.Node, entry bool) bool { 4315 if !entry { 4316 return true 4317 } 4318 4319 if x, ok := n.(*cc.AttributeValue); ok && x.Token.Value == idAlias { 4320 switch y := x.ExpressionList.AssignmentExpression.Operand.Value().(type) { 4321 case cc.StringValue: 4322 r = cc.StringID(y) 4323 return false 4324 } 4325 } 4326 return true 4327 }) 4328 if r != 0 { 4329 return r 4330 } 4331 } 4332 return 0 4333 } 4334 4335 func (p *project) tld(f *function, n *cc.InitDeclarator, sep string, staticLocal bool) { 4336 d := n.Declarator 4337 if d.IsExtern() && d.Linkage == cc.External && !d.IsTypedefName { 4338 if alias := alias(attrs(d.Type())); alias != 0 { 4339 p.capi = append(p.capi, d.Name().String()) 4340 p.w("\n\nvar %s%s = %s\t// %v:\n", p.task.exportExterns, d.Name(), p.externs[alias].name, p.pos(d)) 4341 return 4342 } 4343 } 4344 4345 if _, ok := p.wanted[d]; !ok && !staticLocal { 4346 isFn := d.Type().Kind() == cc.Function 4347 if isFn && p.task.header && p.task.funcSig { 4348 if nm := d.Name().String(); !strings.HasPrefix(nm, "__") { 4349 p.w("\n\n") 4350 t := p.tlds[d] 4351 if t == nil { 4352 t = &tld{} 4353 t.name = p.tldScope.take(d.Name()) 4354 } 4355 p.functionSignature2(n, nil, d.Type(), t.name) 4356 } 4357 } 4358 return 4359 } 4360 4361 tld := p.tlds[d] 4362 if tld == nil { // Dead declaration. 4363 return 4364 } 4365 4366 t := d.Type() 4367 if d.IsTypedefName { 4368 p.checkAttributes(t) 4369 if _, ok := p.typedefsEmited[tld.name]; ok { 4370 return 4371 } 4372 4373 p.typedefsEmited[tld.name] = struct{}{} 4374 if t.Kind() != cc.Void { 4375 p.w("%stype %s = %s; /* %v */", sep, tld.name, p.typ(n, t), p.pos(d)) 4376 } 4377 return 4378 } 4379 4380 switch n.Case { 4381 case cc.InitDeclaratorDecl: // Declarator AttributeSpecifierList 4382 p.w("%svar %s %s\t/* %v: */", sep, tld.name, p.typ(n, t), p.pos(n)) 4383 switch t.Kind() { 4384 case cc.Struct, cc.Union: 4385 p.structs[t.Tag()].emit(p, nil) 4386 } 4387 case cc.InitDeclaratorInit: // Declarator AttributeSpecifierList '=' Initializer 4388 if d.IsStatic() && d.Read == 0 && d.Write == 1 && n.Initializer.IsConst() { // Initialized with no side effects and unused. 4389 break 4390 } 4391 4392 p.w("%svar %s ", sep, tld.name) 4393 if !isAggregateTypeOrUnion(d.Type()) { 4394 p.w("%s ", p.typ(n, d.Type())) 4395 } 4396 p.w("= ") 4397 p.initializer(f, n.Initializer, d.Type(), d.StorageClass, tld) 4398 p.w("; /* %v */", p.pos(d)) 4399 default: 4400 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 4401 } 4402 } 4403 4404 func (p *project) functionDefinition(n *cc.FunctionDefinition) { 4405 // DeclarationSpecifiers Declarator DeclarationList CompoundStatement 4406 if p.task.header && !p.task.funcSig { 4407 return 4408 } 4409 4410 if _, ok := p.sharedFns[n]; ok { 4411 if _, ok := p.sharedFnsEmitted[n]; ok { 4412 return 4413 } 4414 4415 p.sharedFnsEmitted[n] = struct{}{} 4416 } 4417 4418 d := n.Declarator 4419 if d.IsExtern() && d.Type().Inline() { 4420 // https://gcc.gnu.org/onlinedocs/gcc/Inline.html 4421 // 4422 // If you specify both inline and extern in the function definition, then the 4423 // definition is used only for inlining. In no case is the function compiled on 4424 // its own, not even if you refer to its address explicitly. Such an address 4425 // becomes an external reference, as if you had only declared the function, and 4426 // had not defined it. 4427 // 4428 // This combination of inline and extern has almost the effect of a macro. The 4429 // way to use it is to put a function definition in a header file with these 4430 // keywords, and put another copy of the definition (lacking inline and extern) 4431 // in a library file. The definition in the header file causes most calls to 4432 // the function to be inlined. If any uses of the function remain, they refer 4433 // to the single copy in the library. 4434 return 4435 } 4436 4437 name := d.Name().String() 4438 if _, ok := p.task.hide[name]; ok { 4439 return 4440 } 4441 4442 if p.isMain && d.Linkage == cc.External && d.Read == 0 && !d.AddressTaken && len(p.task.asts) == 1 { 4443 return 4444 } 4445 4446 if d.Linkage == cc.Internal && d.Read == 0 && !d.AddressTaken /*TODO- && strings.HasPrefix(name, "__") */ { 4447 return 4448 } 4449 4450 tld := p.tlds[d] 4451 if tld == nil { 4452 return 4453 } 4454 4455 p.fn = name 4456 4457 defer func() { p.fn = "" }() 4458 4459 f := newFunction(p, n) 4460 p.pass1 = true 4461 p.compoundStatement(f, n.CompoundStatement, "", false, false, 0) 4462 p.pass1 = false 4463 p.w("\n\n") 4464 p.functionDefinitionSignature(n, f, tld) 4465 if p.task.header && p.task.funcSig { 4466 return 4467 } 4468 4469 p.w(" ") 4470 comment := fmt.Sprintf("/* %v: */", p.pos(d)) 4471 if p.task.panicStubs { 4472 p.w("%s{ panic(%q) }", comment, tld.name) 4473 return 4474 } 4475 4476 brace := "{" 4477 if need := f.off; need != 0 { 4478 scope := f.blocks[n.CompoundStatement].scope 4479 f.bpName = scope.take(idBp) 4480 p.w("{%s\n%s := %s.Alloc(%d)\n", comment, f.bpName, f.tlsName, need) 4481 p.w("defer %s.Free(%d)\n", f.tlsName, need) 4482 for _, v := range d.Type().Parameters() { 4483 if local := f.locals[v.Declarator()]; local != nil && local.isPinned { // Pin it. 4484 p.w("*(*%s)(unsafe.Pointer(%s%s)) = %s\n", p.typ(v.Declarator(), paramTypeDecay(v.Declarator())), f.bpName, nonZeroUintptr(local.off), local.name) 4485 } 4486 } 4487 comment = "" 4488 brace = "" 4489 } 4490 if len(f.vlas) != 0 { 4491 p.w("%s%s\n", brace, comment) 4492 var vlas []*cc.Declarator 4493 for k := range f.vlas { 4494 vlas = append(vlas, k) 4495 } 4496 sort.Slice(vlas, func(i, j int) bool { 4497 return vlas[i].NameTok().Seq() < vlas[j].NameTok().Seq() 4498 }) 4499 for _, v := range vlas { 4500 local := f.locals[v] 4501 switch { 4502 case local.isPinned: 4503 panic(todo("", v.Position())) 4504 default: 4505 p.w("var %s uintptr // %v: %v\n", local.name, p.pos(v), v.Type()) 4506 } 4507 } 4508 switch { 4509 case len(vlas) == 1: 4510 p.w("defer %sXfree(%s, %s)\n", p.task.crt, f.tlsName, f.locals[vlas[0]].name) 4511 default: 4512 p.w("defer func() {\n") 4513 for _, v := range vlas { 4514 p.w("%sXfree(%s, %s)\n", p.task.crt, f.tlsName, f.locals[v].name) 4515 } 4516 p.w("\n}()\n") 4517 } 4518 } 4519 p.compoundStatement(f, n.CompoundStatement, comment, false, true, 0) 4520 p.w(";") 4521 p.flushLocalTaggesStructs() 4522 p.flushStaticTLDs() 4523 } 4524 4525 func (p *project) flushLocalTaggesStructs() { 4526 for _, v := range p.localTaggedStructs { 4527 v() 4528 } 4529 p.localTaggedStructs = nil 4530 } 4531 4532 func (p *project) flushStaticTLDs() { 4533 for _, v := range p.staticQueue { 4534 p.tld(nil, v, "\n", true) 4535 } 4536 p.staticQueue = nil 4537 } 4538 4539 func (p *project) compoundStatement(f *function, n *cc.CompoundStatement, scomment string, forceNoBraces, fnBody bool, mode exprMode) { 4540 if p.task.panicStubs { 4541 return 4542 } 4543 4544 // '{' BlockItemList '}' 4545 brace := (!n.IsJumpTarget() || n.Parent() == nil) && !forceNoBraces 4546 if brace && len(f.vlas) == 0 && (n.Parent() != nil || f.off == 0) { 4547 p.w("{%s", scomment) 4548 } 4549 if fnBody { 4550 p.instrument(n) 4551 } 4552 sv := f.block 4553 f.block = f.blocks[n] 4554 if f.block.topDecl { 4555 for _, v := range f.block.decls { 4556 p.declaration(f, v, true) 4557 } 4558 } 4559 var r *cc.JumpStatement 4560 for list := n.BlockItemList; list != nil; list = list.BlockItemList { 4561 m := mode 4562 if list.BlockItemList != nil { 4563 m = 0 4564 } 4565 r = p.blockItem(f, list.BlockItem, m) 4566 } 4567 if n.Parent() == nil && r == nil && f.rt.Kind() != cc.Void { 4568 p.w("\nreturn ") 4569 p.zeroValue(n, f.rt) 4570 } 4571 s := tidyComment("\n", &n.Token2) 4572 p.w("%s", s) 4573 if brace { 4574 if !strings.HasSuffix(s, "\n") { 4575 p.w("\n") 4576 } 4577 p.w("}") 4578 } 4579 f.block = sv 4580 } 4581 4582 func (p *project) zeroValue(n cc.Node, t cc.Type) { 4583 if t.IsScalarType() { 4584 p.w("%s(0)", p.typ(n, t)) 4585 return 4586 } 4587 4588 switch t.Kind() { 4589 case cc.Struct, cc.Union: 4590 p.w("%s{}", p.typ(n, t)) 4591 default: 4592 panic(todo("", t, t.Kind())) 4593 } 4594 } 4595 4596 func (p *project) blockItem(f *function, n *cc.BlockItem, mode exprMode) (r *cc.JumpStatement) { 4597 switch n.Case { 4598 case cc.BlockItemDecl: // Declaration 4599 p.declaration(f, n.Declaration, false) 4600 case cc.BlockItemStmt: // Statement 4601 r = p.statement(f, n.Statement, false, false, false, mode) 4602 p.w(";") 4603 if r == nil { 4604 p.instrument(n) 4605 } 4606 case cc.BlockItemLabel: // LabelDeclaration 4607 panic(todo("", p.pos(n))) 4608 p.w(";") 4609 case cc.BlockItemFuncDef: // DeclarationSpecifiers Declarator CompoundStatement 4610 p.err(n, "nested functions not supported") 4611 p.w(";") 4612 case cc.BlockItemPragma: // PragmaSTDC 4613 panic(todo("", p.pos(n))) 4614 p.w(";") 4615 default: 4616 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 4617 } 4618 return r 4619 } 4620 4621 func (p *project) instrument(n cc.Node) { 4622 if p.task.cover { 4623 p.w("%sCover();", p.task.crt) 4624 } 4625 if p.task.coverC { 4626 p.w("%sCoverC(%q);", p.task.crt, p.pos(n).String()+" "+p.fn) 4627 } 4628 if p.task.watch { 4629 p.w("%sWatch();", p.task.crt) 4630 } 4631 } 4632 4633 var dummyJumpStatement = &cc.JumpStatement{} 4634 4635 func (p *project) statement(f *function, n *cc.Statement, forceCompoundStmtBrace, forceNoBraces, switchBlock bool, mode exprMode) (r *cc.JumpStatement) { 4636 if forceCompoundStmtBrace { 4637 if f.switchCtx == inSwitchFirst && p.pauseCodegen { 4638 p.pauseCodegen = false 4639 p.w(" {") 4640 p.pauseCodegen = true 4641 } 4642 p.w(" {") 4643 if !switchBlock { 4644 p.instrument(n) 4645 } 4646 } 4647 switch n.Case { 4648 case cc.StatementLabeled: // LabeledStatement 4649 r = p.labeledStatement(f, n.LabeledStatement) 4650 case cc.StatementCompound: // CompoundStatement 4651 if !forceCompoundStmtBrace { 4652 p.w("%s", n.CompoundStatement.Token.Sep) 4653 } 4654 if f.hasJumps { 4655 forceNoBraces = true 4656 } 4657 p.compoundStatement(f, n.CompoundStatement, "", forceCompoundStmtBrace || forceNoBraces, false, 0) 4658 case cc.StatementExpr: // ExpressionStatement 4659 if mode != 0 { 4660 p.w("return ") 4661 e := n.ExpressionStatement.Expression 4662 p.expression(f, e, e.Operand.Type(), exprValue, 0) 4663 r = dummyJumpStatement 4664 break 4665 } 4666 4667 p.expressionStatement(f, n.ExpressionStatement) 4668 case cc.StatementSelection: // SelectionStatement 4669 p.selectionStatement(f, n.SelectionStatement) 4670 case cc.StatementIteration: // IterationStatement 4671 p.iterationStatement(f, n.IterationStatement) 4672 case cc.StatementJump: // JumpStatement 4673 r = p.jumpStatement(f, n.JumpStatement) 4674 case cc.StatementAsm: // AsmStatement 4675 // AsmStatement: 4676 // Asm AttributeSpecifierList ';' 4677 // Asm: 4678 // "__asm__" AsmQualifierList '(' STRINGLITERAL AsmArgList ')' 4679 if n.AsmStatement.Asm.Token3.Value == 0 && n.AsmStatement.Asm.AsmArgList == nil { 4680 break 4681 } 4682 4683 p.w("panic(`%s: assembler statements not supported`)", n.Position()) 4684 default: 4685 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 4686 } 4687 if forceCompoundStmtBrace { 4688 // We need to do this, to guarantee that we always close the brace is we opened it 4689 if f.switchCtx == inSwitchFirst && p.pauseCodegen { 4690 p.pauseCodegen = false 4691 p.w("}") 4692 p.pauseCodegen = true 4693 } 4694 p.w("}") 4695 } 4696 return r 4697 } 4698 4699 func (p *project) jumpStatement(f *function, n *cc.JumpStatement) (r *cc.JumpStatement) { 4700 p.w("%s", tidyComment("\n", n)) 4701 if _, ok := n.Context().(*cc.SelectionStatement); ok && f.ifCtx == nil { 4702 switch f.switchCtx { 4703 case inSwitchCase: 4704 f.switchCtx = inSwitchSeenBreak 4705 case inSwitchSeenBreak: 4706 // nop but TODO 4707 case inSwitchFlat: 4708 // ok 4709 default: 4710 panic(todo("", n.Position(), f.switchCtx)) 4711 } 4712 } 4713 4714 switch n.Case { 4715 case cc.JumpStatementGoto: // "goto" IDENTIFIER ';' 4716 p.w("goto %s", f.labelNames[n.Token2.Value]) 4717 case cc.JumpStatementGotoExpr: // "goto" '*' Expression ';' 4718 panic(todo("", p.pos(n))) 4719 case cc.JumpStatementContinue: // "continue" ';' 4720 switch { 4721 case f.continueCtx != 0: 4722 p.w("goto __%d", f.continueCtx) 4723 default: 4724 p.w("continue") 4725 } 4726 case cc.JumpStatementBreak: // "break" ';' 4727 switch { 4728 case f.breakCtx != 0: 4729 p.w("goto __%d", f.breakCtx) 4730 default: 4731 p.w("break") 4732 } 4733 case cc.JumpStatementReturn: // "return" Expression ';' 4734 r = n 4735 switch { 4736 case f.rt != nil && f.rt.Kind() == cc.Void: 4737 if n.Expression != nil { 4738 p.expression(f, n.Expression, n.Expression.Operand.Type(), exprVoid, 0) 4739 p.w(";") 4740 } 4741 p.w("return") 4742 case f.rt != nil && f.rt.Kind() != cc.Void: 4743 if n.Expression != nil { 4744 p.expression(f, n.Expression, f.rt, exprCondReturn, 0) 4745 break 4746 } 4747 4748 p.w("return ") 4749 p.zeroValue(n, f.rt) 4750 default: 4751 if n.Expression != nil { 4752 p.expression(f, n.Expression, n.Expression.Operand.Type(), exprVoid, 0) 4753 p.w(";") 4754 } 4755 p.w("return") 4756 } 4757 default: 4758 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 4759 } 4760 return r 4761 } 4762 4763 func (p *project) expression(f *function, n *cc.Expression, t cc.Type, mode exprMode, flags flags) { 4764 switch mode { 4765 case exprVoid: 4766 p.expressionVoid(f, n, t, mode, flags) 4767 case exprValue, exprCondReturn, exprCondInit: 4768 p.expressionValue(f, n, t, mode, flags) 4769 case exprBool: 4770 p.expressionBool(f, n, t, mode, flags) 4771 case exprAddrOf: 4772 p.expressionAddrOf(f, n, t, mode, flags) 4773 case exprPSelect: 4774 p.expressionPSelect(f, n, t, mode, flags) 4775 case exprLValue: 4776 p.expressionLValue(f, n, t, mode, flags) 4777 case exprFunc: 4778 p.expressionFunc(f, n, t, mode, flags) 4779 case exprSelect: 4780 p.expressionSelect(f, n, t, mode, flags) 4781 case exprDecay: 4782 p.expressionDecay(f, n, t, mode, flags) 4783 default: 4784 panic(todo("", n.Position(), mode)) 4785 } 4786 } 4787 4788 func (p *project) expressionDecay(f *function, n *cc.Expression, t cc.Type, mode exprMode, flags flags) { 4789 switch n.Case { 4790 case cc.ExpressionAssign: // AssignmentExpression 4791 p.assignmentExpression(f, n.AssignmentExpression, t, mode, flags) 4792 case cc.ExpressionComma: // Expression ',' AssignmentExpression 4793 p.w("func() uintptr {") 4794 p.expression(f, n.Expression, n.Expression.Operand.Type(), exprVoid, flags) 4795 p.w("; return ") 4796 p.assignmentExpression(f, n.AssignmentExpression, t, mode, flags) 4797 p.w("}()") 4798 default: 4799 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 4800 } 4801 } 4802 4803 func (p *project) expressionSelect(f *function, n *cc.Expression, t cc.Type, mode exprMode, flags flags) { 4804 switch n.Case { 4805 case cc.ExpressionAssign: // AssignmentExpression 4806 p.assignmentExpression(f, n.AssignmentExpression, t, mode, flags) 4807 case cc.ExpressionComma: // Expression ',' AssignmentExpression 4808 panic(todo("", p.pos(n))) 4809 default: 4810 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 4811 } 4812 } 4813 4814 func (p *project) expressionFunc(f *function, n *cc.Expression, t cc.Type, mode exprMode, flags flags) { 4815 switch n.Case { 4816 case cc.ExpressionAssign: // AssignmentExpression 4817 p.assignmentExpression(f, n.AssignmentExpression, t, mode, flags) 4818 case cc.ExpressionComma: // Expression ',' AssignmentExpression 4819 panic(todo("", p.pos(n))) 4820 default: 4821 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 4822 } 4823 } 4824 4825 func (p *project) expressionLValue(f *function, n *cc.Expression, t cc.Type, mode exprMode, flags flags) { 4826 switch n.Case { 4827 case cc.ExpressionAssign: // AssignmentExpression 4828 p.assignmentExpression(f, n.AssignmentExpression, t, mode, flags) 4829 case cc.ExpressionComma: // Expression ',' AssignmentExpression 4830 panic(todo("", p.pos(n))) 4831 default: 4832 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 4833 } 4834 } 4835 4836 func (p *project) expressionPSelect(f *function, n *cc.Expression, t cc.Type, mode exprMode, flags flags) { 4837 switch n.Case { 4838 case cc.ExpressionAssign: // AssignmentExpression 4839 p.assignmentExpression(f, n.AssignmentExpression, t, mode, flags) 4840 case cc.ExpressionComma: // Expression ',' AssignmentExpression 4841 panic(todo("", p.pos(n))) 4842 default: 4843 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 4844 } 4845 } 4846 4847 func (p *project) expressionAddrOf(f *function, n *cc.Expression, t cc.Type, mode exprMode, flags flags) { 4848 switch n.Case { 4849 case cc.ExpressionAssign: // AssignmentExpression 4850 p.assignmentExpression(f, n.AssignmentExpression, t, mode, flags) 4851 case cc.ExpressionComma: // Expression ',' AssignmentExpression 4852 p.w(" func() uintptr {") 4853 p.expression(f, n.Expression, n.Expression.Operand.Type(), exprVoid, flags) 4854 p.w("; return ") 4855 p.assignmentExpression(f, n.AssignmentExpression, t, mode, flags) 4856 p.w("}()") 4857 default: 4858 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 4859 } 4860 } 4861 4862 func (p *project) expressionBool(f *function, n *cc.Expression, t cc.Type, mode exprMode, flags flags) { 4863 switch n.Case { 4864 case cc.ExpressionAssign: // AssignmentExpression 4865 p.assignmentExpression(f, n.AssignmentExpression, t, mode, flags) 4866 case cc.ExpressionComma: // Expression ',' AssignmentExpression 4867 p.w("func() bool {") 4868 p.expression(f, n.Expression, n.Expression.Operand.Type(), exprVoid, flags) 4869 p.w("; return ") 4870 p.assignmentExpression(f, n.AssignmentExpression, n.AssignmentExpression.Operand.Type(), mode, flags) 4871 p.w("}()") 4872 default: 4873 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 4874 } 4875 } 4876 4877 func (p *project) expressionValue(f *function, n *cc.Expression, t cc.Type, mode exprMode, flags flags) { 4878 switch n.Case { 4879 case cc.ExpressionAssign: // AssignmentExpression 4880 p.assignmentExpression(f, n.AssignmentExpression, t, mode, flags) 4881 case cc.ExpressionComma: // Expression ',' AssignmentExpression 4882 if mode == exprCondReturn { 4883 p.expression(f, n.Expression, n.Expression.Operand.Type(), exprVoid, flags) 4884 p.w("; return ") 4885 p.assignmentExpression(f, n.AssignmentExpression, n.AssignmentExpression.Operand.Type(), exprValue, flags) 4886 return 4887 } 4888 4889 switch { 4890 case n.AssignmentExpression.Operand.Type().Kind() == cc.Array: 4891 p.expressionDecay(f, n, t, exprDecay, flags) 4892 default: 4893 defer p.w("%s", p.convertType(n, n.Operand.Type(), t, flags)) 4894 p.w("func() %v {", p.typ(n, n.AssignmentExpression.Operand.Type())) 4895 p.expression(f, n.Expression, n.Expression.Operand.Type(), exprVoid, flags) 4896 p.w("; return ") 4897 p.assignmentExpression(f, n.AssignmentExpression, n.AssignmentExpression.Operand.Type(), exprValue, flags) 4898 p.w("}()") 4899 } 4900 default: 4901 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 4902 } 4903 } 4904 4905 func (p *project) expressionVoid(f *function, n *cc.Expression, t cc.Type, mode exprMode, flags flags) { 4906 switch n.Case { 4907 case cc.ExpressionAssign: // AssignmentExpression 4908 p.assignmentExpression(f, n.AssignmentExpression, t, mode, flags) 4909 case cc.ExpressionComma: // Expression ',' AssignmentExpression 4910 p.expression(f, n.Expression, t, mode, flags) 4911 p.w(";") 4912 p.assignmentExpression(f, n.AssignmentExpression, t, mode, flags) 4913 default: 4914 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 4915 } 4916 } 4917 4918 func (p *project) opKind(f *function, d declarator, t cc.Type) opKind { 4919 switch { 4920 case p.isArrayParameter(d, t): 4921 return opArrayParameter 4922 case !p.pass1 && p.isArray(f, d, t): 4923 return opArray 4924 case t.Kind() == cc.Union: 4925 return opUnion 4926 case t.Kind() == cc.Struct: 4927 return opStruct 4928 case t.IsBitFieldType(): 4929 return opBitfield 4930 case t.Kind() == cc.Function: 4931 return opFunction 4932 default: 4933 return opNormal 4934 } 4935 } 4936 4937 func (p *project) assignmentExpression(f *function, n *cc.AssignmentExpression, t cc.Type, mode exprMode, flags flags) { 4938 switch mode { 4939 case exprVoid: 4940 p.assignmentExpressionVoid(f, n, t, mode, flags) 4941 case exprValue, exprCondReturn, exprCondInit: 4942 p.assignmentExpressionValue(f, n, t, mode, flags) 4943 case exprAddrOf: 4944 p.assignmentExpressionAddrOf(f, n, t, mode, flags) 4945 case exprBool: 4946 p.assignmentExpressionBool(f, n, t, mode, flags) 4947 case exprLValue: 4948 p.assignmentExpressionLValue(f, n, t, mode, flags) 4949 case exprPSelect: 4950 p.assignmentExpressionPSelect(f, n, t, mode, flags) 4951 case exprFunc: 4952 p.assignmentExpressionFunc(f, n, t, mode, flags) 4953 case exprSelect: 4954 p.assignmentExpressionSelect(f, n, t, mode, flags) 4955 case exprDecay: 4956 p.assignmentExpressionDecay(f, n, t, mode, flags) 4957 default: 4958 panic(todo("", n.Position(), mode)) 4959 } 4960 } 4961 4962 func (p *project) assignmentExpressionDecay(f *function, n *cc.AssignmentExpression, t cc.Type, mode exprMode, flags flags) { 4963 switch n.Case { 4964 case cc.AssignmentExpressionCond: // ConditionalExpression 4965 p.conditionalExpression(f, n.ConditionalExpression, t, mode, flags) 4966 case cc.AssignmentExpressionAssign: // UnaryExpression '=' AssignmentExpression 4967 panic(todo("", p.pos(n))) 4968 case cc.AssignmentExpressionMul: // UnaryExpression "*=" AssignmentExpression 4969 panic(todo("", p.pos(n))) 4970 case cc.AssignmentExpressionDiv: // UnaryExpression "/=" AssignmentExpression 4971 panic(todo("", p.pos(n))) 4972 case cc.AssignmentExpressionMod: // UnaryExpression "%=" AssignmentExpression 4973 panic(todo("", p.pos(n))) 4974 case cc.AssignmentExpressionAdd: // UnaryExpression "+=" AssignmentExpression 4975 panic(todo("", p.pos(n))) 4976 case cc.AssignmentExpressionSub: // UnaryExpression "-=" AssignmentExpression 4977 panic(todo("", p.pos(n))) 4978 case cc.AssignmentExpressionLsh: // UnaryExpression "<<= AssignmentExpression 4979 panic(todo("", p.pos(n))) 4980 case cc.AssignmentExpressionRsh: // UnaryExpression ">>=" AssignmentExpression 4981 panic(todo("", p.pos(n))) 4982 case cc.AssignmentExpressionAnd: // UnaryExpression "&=" AssignmentExpression 4983 panic(todo("", p.pos(n))) 4984 case cc.AssignmentExpressionXor: // UnaryExpression "^=" AssignmentExpression 4985 panic(todo("", p.pos(n))) 4986 case cc.AssignmentExpressionOr: // UnaryExpression "|=" AssignmentExpression 4987 panic(todo("", p.pos(n))) 4988 default: 4989 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 4990 } 4991 } 4992 4993 func (p *project) assignmentExpressionSelect(f *function, n *cc.AssignmentExpression, t cc.Type, mode exprMode, flags flags) { 4994 switch n.Case { 4995 case cc.AssignmentExpressionCond: // ConditionalExpression 4996 p.conditionalExpression(f, n.ConditionalExpression, t, mode, flags) 4997 case cc.AssignmentExpressionAssign: // UnaryExpression '=' AssignmentExpression 4998 panic(todo("", p.pos(n))) 4999 case cc.AssignmentExpressionMul: // UnaryExpression "*=" AssignmentExpression 5000 panic(todo("", p.pos(n))) 5001 case cc.AssignmentExpressionDiv: // UnaryExpression "/=" AssignmentExpression 5002 panic(todo("", p.pos(n))) 5003 case cc.AssignmentExpressionMod: // UnaryExpression "%=" AssignmentExpression 5004 panic(todo("", p.pos(n))) 5005 case cc.AssignmentExpressionAdd: // UnaryExpression "+=" AssignmentExpression 5006 panic(todo("", p.pos(n))) 5007 case cc.AssignmentExpressionSub: // UnaryExpression "-=" AssignmentExpression 5008 panic(todo("", p.pos(n))) 5009 case cc.AssignmentExpressionLsh: // UnaryExpression "<<=" AssignmentExpression 5010 panic(todo("", p.pos(n))) 5011 case cc.AssignmentExpressionRsh: // UnaryExpression ">>=" AssignmentExpression 5012 panic(todo("", p.pos(n))) 5013 case cc.AssignmentExpressionAnd: // UnaryExpression "&=" AssignmentExpression 5014 panic(todo("", p.pos(n))) 5015 case cc.AssignmentExpressionXor: // UnaryExpression "^=" AssignmentExpression 5016 panic(todo("", p.pos(n))) 5017 case cc.AssignmentExpressionOr: // UnaryExpression "|=" AssignmentExpression 5018 panic(todo("", p.pos(n))) 5019 default: 5020 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 5021 } 5022 } 5023 5024 func (p *project) assignmentExpressionFunc(f *function, n *cc.AssignmentExpression, t cc.Type, mode exprMode, flags flags) { 5025 switch n.Case { 5026 case cc.AssignmentExpressionCond: // ConditionalExpression 5027 p.conditionalExpression(f, n.ConditionalExpression, t, mode, flags) 5028 case cc.AssignmentExpressionAssign: // UnaryExpression '=' AssignmentExpression 5029 panic(todo("", p.pos(n))) 5030 case cc.AssignmentExpressionMul: // UnaryExpression "*=" AssignmentExpression 5031 panic(todo("", p.pos(n))) 5032 case cc.AssignmentExpressionDiv: // UnaryExpression "/=" AssignmentExpression 5033 panic(todo("", p.pos(n))) 5034 case cc.AssignmentExpressionMod: // UnaryExpression "%=" AssignmentExpression 5035 panic(todo("", p.pos(n))) 5036 case cc.AssignmentExpressionAdd: // UnaryExpression "+=" AssignmentExpression 5037 panic(todo("", p.pos(n))) 5038 case cc.AssignmentExpressionSub: // UnaryExpression "-=" AssignmentExpression 5039 panic(todo("", p.pos(n))) 5040 case cc.AssignmentExpressionLsh: // UnaryExpremode, ssion "<<= 5041 panic(todo("", p.pos(n))) 5042 case cc.AssignmentExpressionRsh: // UnaryExpression ">>=" AssignmentExpression 5043 panic(todo("", p.pos(n))) 5044 case cc.AssignmentExpressionAnd: // UnaryExpression "&=" AssignmentExpression 5045 panic(todo("", p.pos(n))) 5046 case cc.AssignmentExpressionXor: // UnaryExpression "^=" AssignmentExpression 5047 panic(todo("", p.pos(n))) 5048 case cc.AssignmentExpressionOr: // UnaryExpression "|=" AssignmentExpression 5049 panic(todo("", p.pos(n))) 5050 default: 5051 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 5052 } 5053 } 5054 5055 func (p *project) assignmentExpressionPSelect(f *function, n *cc.AssignmentExpression, t cc.Type, mode exprMode, flags flags) { 5056 switch n.Case { 5057 case cc.AssignmentExpressionCond: // ConditionalExpression 5058 p.conditionalExpression(f, n.ConditionalExpression, t, mode, flags) 5059 case cc.AssignmentExpressionAssign: // UnaryExpression '=' AssignmentExpression 5060 p.w("(*%s)(unsafe.Pointer(", p.typ(n, n.AssignmentExpression.Operand.Type().Elem())) 5061 p.assignmentExpression(f, n, t, exprValue, flags) 5062 p.w("))") 5063 case cc.AssignmentExpressionMul: // UnaryExpression "*=" AssignmentExpression 5064 panic(todo("", p.pos(n))) 5065 case cc.AssignmentExpressionDiv: // UnaryExpression "/=" AssignmentExpression 5066 panic(todo("", p.pos(n))) 5067 case cc.AssignmentExpressionMod: // UnaryExpression "%=" AssignmentExpression 5068 panic(todo("", p.pos(n))) 5069 case cc.AssignmentExpressionAdd: // UnaryExpression "+=" AssignmentExpression 5070 panic(todo("", p.pos(n))) 5071 case cc.AssignmentExpressionSub: // UnaryExpression "-=" AssignmentExpression 5072 panic(todo("", p.pos(n))) 5073 case cc.AssignmentExpressionLsh: // UnaryExpression "<<=" AssignmentExpression 5074 panic(todo("", p.pos(n))) 5075 case cc.AssignmentExpressionRsh: // UnaryExpression ">>=" AssignmentExpression 5076 panic(todo("", p.pos(n))) 5077 case cc.AssignmentExpressionAnd: // UnaryExpression "&=" AssignmentExpression 5078 panic(todo("", p.pos(n))) 5079 case cc.AssignmentExpressionXor: // UnaryExpression "^=" AssignmentExpression 5080 panic(todo("", p.pos(n))) 5081 case cc.AssignmentExpressionOr: // UnaryExpression "|=" AssignmentExpression 5082 panic(todo("", p.pos(n))) 5083 default: 5084 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 5085 } 5086 } 5087 5088 func (p *project) assignmentExpressionLValue(f *function, n *cc.AssignmentExpression, t cc.Type, mode exprMode, flags flags) { 5089 switch n.Case { 5090 case cc.AssignmentExpressionCond: // ConditionalExpression 5091 p.conditionalExpression(f, n.ConditionalExpression, t, mode, flags) 5092 case cc.AssignmentExpressionAssign: // UnaryExpression '=' AssignmentExpression 5093 panic(todo("", p.pos(n))) 5094 case cc.AssignmentExpressionMul: // UnaryExpression "*=" AssignmentExpression 5095 panic(todo("", p.pos(n))) 5096 case cc.AssignmentExpressionDiv: // UnaryExpression "/=" AssignmentExpression 5097 panic(todo("", p.pos(n))) 5098 case cc.AssignmentExpressionMod: // UnaryExpression "%=" AssignmentExpression 5099 panic(todo("", p.pos(n))) 5100 case cc.AssignmentExpressionAdd: // UnaryExpression "+=" AssignmentExpression 5101 panic(todo("", p.pos(n))) 5102 case cc.AssignmentExpressionSub: // UnaryExpression "-=" AssignmentExpression 5103 panic(todo("", p.pos(n))) 5104 case cc.AssignmentExpressionLsh: // UnaryExpression "<<=" AssignmentExpression 5105 panic(todo("", p.pos(n))) 5106 case cc.AssignmentExpressionRsh: // UnaryExpression ">>=" AssignmentExpression 5107 panic(todo("", p.pos(n))) 5108 case cc.AssignmentExpressionAnd: // UnaryExpression "&=" AssignmentExpression 5109 panic(todo("", p.pos(n))) 5110 case cc.AssignmentExpressionXor: // UnaryExpression "^=" AssignmentExpression 5111 panic(todo("", p.pos(n))) 5112 case cc.AssignmentExpressionOr: // UnaryExpression "|=" AssignmentExpression 5113 panic(todo("", p.pos(n))) 5114 default: 5115 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 5116 } 5117 } 5118 5119 func (p *project) assignmentExpressionBool(f *function, n *cc.AssignmentExpression, t cc.Type, mode exprMode, flags flags) { 5120 switch n.Case { 5121 case cc.AssignmentExpressionCond: // ConditionalExpression 5122 p.conditionalExpression(f, n.ConditionalExpression, t, mode, flags) 5123 default: 5124 // case cc.AssignmentExpressionAssign: // UnaryExpression '=' AssignmentExpression 5125 // case cc.AssignmentExpressionMul: // UnaryExpression "*=" AssignmentExpression 5126 // case cc.AssignmentExpressionDiv: // UnaryExpression "/=" AssignmentExpression 5127 // case cc.AssignmentExpressionMod: // UnaryExpression "%=" AssignmentExpression 5128 // case cc.AssignmentExpressionAdd: // UnaryExpression "+=" AssignmentExpression 5129 // case cc.AssignmentExpressionSub: // UnaryExpression "-=" AssignmentExpression 5130 // case cc.AssignmentExpressionLsh: // UnaryExpression "<<=" AssignmentExpression 5131 // case cc.AssignmentExpressionRsh: // UnaryExpression ">>=" AssignmentExpression 5132 // case cc.AssignmentExpressionAnd: // UnaryExpression "&=" AssignmentExpression 5133 // case cc.AssignmentExpressionXor: // UnaryExpression "^=" AssignmentExpression 5134 // case cc.AssignmentExpressionOr: // UnaryExpression "|=" AssignmentExpression 5135 p.w("(") 5136 defer p.w(")") 5137 defer p.w(" != 0 ") 5138 p.assignmentExpression(f, n, t, exprValue, flags) 5139 } 5140 } 5141 5142 func (p *project) assignmentExpressionAddrOf(f *function, n *cc.AssignmentExpression, t cc.Type, mode exprMode, flags flags) { 5143 switch n.Case { 5144 case cc.AssignmentExpressionCond: // ConditionalExpression 5145 p.conditionalExpression(f, n.ConditionalExpression, t, mode, flags) 5146 case cc.AssignmentExpressionAssign: // UnaryExpression '=' AssignmentExpression 5147 p.assignmentExpressionValueAddrOf(f, n, t, mode, flags) 5148 case cc.AssignmentExpressionMul: // UnaryExpression "*=" AssignmentExpression 5149 panic(todo("", p.pos(n))) 5150 case cc.AssignmentExpressionDiv: // UnaryExpression "/=" AssignmentExpression 5151 panic(todo("", p.pos(n))) 5152 case cc.AssignmentExpressionMod: // UnaryExpression "%=" AssignmentExpression 5153 panic(todo("", p.pos(n))) 5154 case cc.AssignmentExpressionAdd: // UnaryExpression "+=" AssignmentExpression 5155 panic(todo("", p.pos(n))) 5156 case cc.AssignmentExpressionSub: // UnaryExpression "-=" AssignmentExpression 5157 panic(todo("", p.pos(n))) 5158 case cc.AssignmentExpressionLsh: // UnaryExpression "<<=" AssignmentExpression 5159 panic(todo("", p.pos(n))) 5160 case cc.AssignmentExpressionRsh: // UnaryExpression ">>=" AssignmentExpression 5161 panic(todo("", p.pos(n))) 5162 case cc.AssignmentExpressionAnd: // UnaryExpression "&=" AssignmentExpression 5163 panic(todo("", p.pos(n))) 5164 case cc.AssignmentExpressionXor: // UnaryExpression "^=" AssignmentExpression 5165 panic(todo("", p.pos(n))) 5166 case cc.AssignmentExpressionOr: // UnaryExpression "|=" AssignmentExpression 5167 panic(todo("", p.pos(n))) 5168 default: 5169 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 5170 } 5171 } 5172 5173 func (p *project) assignmentExpressionValueAddrOf(f *function, n *cc.AssignmentExpression, t cc.Type, mode exprMode, flags flags) { 5174 // UnaryExpression '=' AssignmentExpression 5175 if mode == exprCondReturn { 5176 panic(todo("", p.pos(n))) 5177 } 5178 5179 lhs := n.UnaryExpression 5180 switch k := p.opKind(f, lhs, lhs.Operand.Type()); k { 5181 case opStruct, opUnion: 5182 p.assignmentExpressionValueAssignStructAddrof(f, n, n.Operand.Type(), mode, flags) 5183 default: 5184 panic(todo("", n.Position(), k)) 5185 } 5186 } 5187 5188 func (p *project) assignmentExpressionValueAssignStructAddrof(f *function, n *cc.AssignmentExpression, t cc.Type, mode exprMode, flags flags) { 5189 // UnaryExpression '=' AssignmentExpression 5190 lhs := n.UnaryExpression.Operand.Type() 5191 rhs := n.AssignmentExpression.Operand.Type() 5192 if lhs.Kind() == cc.Array || rhs.Kind() == cc.Array { 5193 panic(todo("", p.pos(n))) 5194 } 5195 5196 if d := n.UnaryExpression.Declarator(); d != nil { 5197 if local := f.locals[d]; local != nil { 5198 if local.isPinned { 5199 if !p.pass1 { 5200 p.w("%sXmemmove(tls, ", p.task.crt) 5201 p.unaryExpression(f, n.UnaryExpression, lhs, exprAddrOf, flags) 5202 p.w(", ") 5203 p.assignmentExpression(f, n.AssignmentExpression, rhs, exprAddrOf, flags) 5204 p.w(", %d)", lhs.Size()) 5205 return 5206 } 5207 } 5208 5209 if !p.pass1 { 5210 panic(todo("", p.pos(n))) 5211 } 5212 } 5213 } 5214 5215 p.w("%sXmemmove(tls, ", p.task.crt) 5216 p.unaryExpression(f, n.UnaryExpression, lhs, exprAddrOf, flags) 5217 p.w(", ") 5218 p.assignmentExpression(f, n.AssignmentExpression, rhs, exprAddrOf, flags) 5219 p.w(", %d)", lhs.Size()) 5220 } 5221 5222 func (p *project) assignmentExpressionValue(f *function, n *cc.AssignmentExpression, t cc.Type, mode exprMode, flags flags) { 5223 switch n.Case { 5224 case cc.AssignmentExpressionCond: // ConditionalExpression 5225 p.conditionalExpression(f, n.ConditionalExpression, t, mode, flags) 5226 case cc.AssignmentExpressionAssign: // UnaryExpression '=' AssignmentExpression 5227 p.assignmentExpressionValueAssign(f, n, t, mode, flags) 5228 case cc.AssignmentExpressionMul: // UnaryExpression "*=" AssignmentExpression 5229 p.assignOp(f, n, t, mode, "*", "Mul", flags) 5230 case cc.AssignmentExpressionDiv: // UnaryExpression "/=" AssignmentExpression 5231 p.assignOp(f, n, t, mode, "/", "Div", flags) 5232 case cc.AssignmentExpressionMod: // UnaryExpression "%=" AssignmentExpression 5233 p.assignOp(f, n, t, mode, "%", "Rem", flags) 5234 case cc.AssignmentExpressionAdd: // UnaryExpression "+=" AssignmentExpression 5235 p.assignOp(f, n, t, mode, "+", "Add", flags) 5236 case cc.AssignmentExpressionSub: // UnaryExpression "-=" AssignmentExpression 5237 p.assignOp(f, n, t, mode, "-", "Sub", flags) 5238 case cc.AssignmentExpressionLsh: // UnaryExpremode, ssion "<<= 5239 p.assignOp(f, n, t, mode, "<<", "Shl", flags) 5240 case cc.AssignmentExpressionRsh: // UnaryExpression ">>=" AssignmentExpression 5241 p.assignOp(f, n, t, mode, ">>", "Shr", flags) 5242 case cc.AssignmentExpressionAnd: // UnaryExpression "&=" AssignmentExpression 5243 p.assignOp(f, n, t, mode, "&", "And", flags) 5244 case cc.AssignmentExpressionXor: // UnaryExpression "^=" AssignmentExpression 5245 p.assignOp(f, n, t, mode, "^", "Xor", flags) 5246 case cc.AssignmentExpressionOr: // UnaryExpression "|=" AssignmentExpression 5247 p.assignOp(f, n, t, mode, "|", "Or", flags) 5248 default: 5249 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 5250 } 5251 } 5252 5253 func (p *project) assignmentExpressionValueAssign(f *function, n *cc.AssignmentExpression, t cc.Type, mode exprMode, flags flags) { 5254 // UnaryExpression '=' AssignmentExpression 5255 if mode == exprCondReturn { 5256 p.w("return ") 5257 } 5258 lhs := n.UnaryExpression 5259 switch k := p.opKind(f, lhs, lhs.Operand.Type()); k { 5260 case opNormal: 5261 p.assignmentExpressionValueAssignNormal(f, n, t, mode, flags) 5262 case opBitfield: 5263 p.assignmentExpressionValueAssignBitfield(f, n, t, mode, flags) 5264 case opStruct, opUnion: 5265 p.assignmentExpressionValueAssignStruct(f, n, t, mode, flags) 5266 default: 5267 panic(todo("", n.Position(), k)) 5268 } 5269 } 5270 5271 func (p *project) assignmentExpressionValueAssignStruct(f *function, n *cc.AssignmentExpression, t cc.Type, mode exprMode, flags flags) { 5272 // UnaryExpression '=' AssignmentExpression 5273 lhs := n.UnaryExpression.Operand.Type() 5274 rhs := n.AssignmentExpression.Operand.Type() 5275 if lhs.Kind() == cc.Array || rhs.Kind() == cc.Array { 5276 panic(todo("", p.pos(n))) 5277 } 5278 5279 p.w(" func() %s { __v := ", p.typ(n, lhs)) 5280 p.assignmentExpression(f, n.AssignmentExpression, rhs, exprValue, flags) 5281 p.w(";") 5282 p.unaryExpression(f, n.UnaryExpression, lhs, exprLValue, flags) 5283 p.w(" = __v; return __v}()") 5284 } 5285 5286 func (p *project) assignmentExpressionValueAssignBitfield(f *function, n *cc.AssignmentExpression, t cc.Type, mode exprMode, flags flags) { 5287 if d := n.UnaryExpression.Declarator(); d != nil { 5288 panic(todo("", p.pos(n))) 5289 } 5290 5291 lhs := n.UnaryExpression 5292 lt := lhs.Operand.Type() 5293 bf := lt.BitField() 5294 defer p.w("%s", p.convertType(n, lt, t, flags)) 5295 p.w("%sAssignBitFieldPtr%d%s(", p.task.crt, bf.BitFieldBlockWidth(), p.bfHelperType(lt)) 5296 p.unaryExpression(f, lhs, lt, exprAddrOf, flags) 5297 p.w(", ") 5298 p.assignmentExpression(f, n.AssignmentExpression, lt, exprValue, flags) 5299 p.w(", %d, %d, %#x)", bf.BitFieldWidth(), bf.BitFieldOffset(), bf.Mask()) 5300 } 5301 5302 func (p *project) assignmentExpressionValueAssignNormal(f *function, n *cc.AssignmentExpression, t cc.Type, mode exprMode, flags flags) { 5303 if d := n.UnaryExpression.Declarator(); d != nil { 5304 if !d.Type().IsScalarType() { 5305 panic(todo("", p.pos(n))) 5306 } 5307 5308 if local := f.locals[d]; local != nil { 5309 if local.isPinned { 5310 defer p.w(")%s", p.convertType(n, d.Type(), t, flags)) 5311 p.w("%sAssignPtr%s(", p.task.crt, p.helperType(d, d.Type())) 5312 p.w("%s%s /* %s */", f.bpName, nonZeroUintptr(local.off), local.name) 5313 p.w(", ") 5314 p.assignmentExpression(f, n.AssignmentExpression, n.UnaryExpression.Operand.Type(), exprValue, flags) 5315 return 5316 } 5317 5318 defer p.w(")%s", p.convertType(n, d.Type(), t, flags)) 5319 p.w("%sAssign%s(&%s, ", p.task.crt, p.helperType(n, d.Type()), local.name) 5320 p.assignmentExpression(f, n.AssignmentExpression, n.UnaryExpression.Operand.Type(), exprValue, flags) 5321 return 5322 } 5323 } 5324 5325 defer p.w(")%s", p.convertType(n, n.UnaryExpression.Operand.Type(), t, flags)) 5326 p.w("%sAssignPtr%s(", p.task.crt, p.helperType(n, n.UnaryExpression.Operand.Type())) 5327 p.unaryExpression(f, n.UnaryExpression, n.UnaryExpression.Operand.Type(), exprAddrOf, flags) 5328 p.w(", ") 5329 p.assignmentExpression(f, n.AssignmentExpression, n.UnaryExpression.Operand.Type(), exprValue, flags) 5330 } 5331 5332 func (p *project) assignmentExpressionVoid(f *function, n *cc.AssignmentExpression, t cc.Type, mode exprMode, flags flags) { 5333 switch n.Case { 5334 case cc.AssignmentExpressionCond: // ConditionalExpression 5335 p.conditionalExpression(f, n.ConditionalExpression, t, mode, flags) 5336 case cc.AssignmentExpressionAssign: // UnaryExpression '=' AssignmentExpression 5337 d := n.UnaryExpression.Declarator() 5338 lhs := n.UnaryExpression 5339 lt := lhs.Operand.Type() 5340 sv := f.condInitPrefix 5341 switch k := p.opKind(f, lhs, lt); k { 5342 case opArrayParameter: 5343 lt = lt.Decay() 5344 fallthrough 5345 case opNormal, opStruct: 5346 mode = exprValue 5347 if p.isArrayOrPinnedArray(f, n.AssignmentExpression, n.AssignmentExpression.Operand.Type()) { 5348 mode = exprDecay 5349 } 5350 switch { 5351 case flags&fNoCondAssignment == 0 && mode == exprValue && n.UnaryExpression.Declarator() != nil && p.isConditionalAssignmentExpr(n.AssignmentExpression): 5352 f.condInitPrefix = func() { 5353 p.unaryExpression(f, lhs, lt, exprLValue, flags) 5354 p.w(" = ") 5355 } 5356 p.assignmentExpression(f, n.AssignmentExpression, lt, exprCondInit, flags) 5357 p.w(";") 5358 default: 5359 if d != nil && p.isVolatileOrAtomic(d) { 5360 p.setVolatileDeclarator(d, f, n.AssignmentExpression, lt, mode, flags) 5361 return 5362 } 5363 5364 p.unaryExpression(f, lhs, lt, exprLValue, flags) 5365 p.w(" = ") 5366 p.assignmentExpression(f, n.AssignmentExpression, lt, mode, flags) 5367 } 5368 case opBitfield: 5369 bf := lt.BitField() 5370 p.w("%sSetBitFieldPtr%d%s(", p.task.crt, bf.BitFieldBlockWidth(), p.bfHelperType(lt)) 5371 p.unaryExpression(f, lhs, lt, exprAddrOf, flags) 5372 p.w(", ") 5373 p.assignmentExpression(f, n.AssignmentExpression, lt, exprValue, flags) 5374 p.w(", %d, %#x)", bf.BitFieldOffset(), bf.Mask()) 5375 case opUnion: 5376 p.unaryExpression(f, lhs, lt, exprLValue, flags) 5377 p.w(" = ") 5378 p.assignmentExpression(f, n.AssignmentExpression, lt, exprValue, flags) 5379 default: 5380 panic(todo("", n.Position(), k)) 5381 } 5382 f.condInitPrefix = sv 5383 case cc.AssignmentExpressionMul: // UnaryExpression "*=" AssignmentExpression 5384 p.assignOp(f, n, t, mode, "*", "Mul", flags) 5385 case cc.AssignmentExpressionDiv: // UnaryExpression "/=" AssignmentExpression 5386 p.assignOp(f, n, t, mode, "/", "Div", flags) 5387 case cc.AssignmentExpressionMod: // UnaryExpression "%=" AssignmentExpression 5388 p.assignOp(f, n, t, mode, "%", "Mod", flags) 5389 case cc.AssignmentExpressionAdd: // UnaryExpression "+=" AssignmentExpression 5390 p.assignOp(f, n, t, mode, "+", "Add", flags) 5391 case cc.AssignmentExpressionSub: // UnaryExpression "-=" AssignmentExpression 5392 p.assignOp(f, n, t, mode, "-", "Sub", flags) 5393 case cc.AssignmentExpressionLsh: // UnaryExpression "<<=" AssignmentExpression 5394 p.assignShiftOp(f, n, t, mode, "<<", "Shl", flags) 5395 case cc.AssignmentExpressionRsh: // UnaryExpression ">>=" AssignmentExpression 5396 p.assignShiftOp(f, n, t, mode, ">>", "Shr", flags) 5397 case cc.AssignmentExpressionAnd: // UnaryExpression "&=" AssignmentExpression 5398 p.assignOp(f, n, t, mode, "&", "And", flags) 5399 case cc.AssignmentExpressionXor: // UnaryExpression "^=" AssignmentExpression 5400 p.assignOp(f, n, t, mode, "^", "Xor", flags) 5401 case cc.AssignmentExpressionOr: // UnaryExpression "|=" AssignmentExpression 5402 p.assignOp(f, n, t, mode, "|", "Or", flags) 5403 default: 5404 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 5405 } 5406 } 5407 5408 func (p *project) setVolatileDeclarator(d *cc.Declarator, f *function, n *cc.AssignmentExpression, t cc.Type, mode exprMode, flags flags) { 5409 sz := d.Type().Size() 5410 switch sz { 5411 case 4, 8: 5412 // ok 5413 default: 5414 p.err(d, "unsupported volatile declarator size: %v", sz) 5415 return 5416 } 5417 5418 if local := f.locals[d]; local != nil { 5419 if local.isPinned { 5420 p.w("%sAtomicStoreP%s(%s%s /* %s */, ", p.task.crt, p.helperType(n, d.Type()), f.bpName, nonZeroUintptr(local.off), local.name) 5421 p.assignmentExpression(f, n, t, mode, flags) 5422 p.w(")") 5423 return 5424 } 5425 5426 p.atomicStoreNamedAddr(n, d.Type(), local.name, n, f, mode, flags) 5427 return 5428 } 5429 5430 if tld := p.tlds[d]; tld != nil { 5431 p.atomicStoreNamedAddr(n, d.Type(), tld.name, n, f, mode, flags) 5432 return 5433 } 5434 5435 if imp := p.imports[d.Name().String()]; imp != nil { 5436 p.atomicStoreNamedAddr(n, d.Type(), fmt.Sprintf("%sX%s", imp.qualifier, d.Name()), n, f, mode, flags) 5437 return 5438 } 5439 5440 panic(todo("", n.Position(), d.Position(), d.Name())) 5441 } 5442 5443 func (p *project) atomicStoreNamedAddr(n cc.Node, t cc.Type, nm string, expr *cc.AssignmentExpression, f *function, mode exprMode, flags flags) { 5444 sz := t.Size() 5445 switch sz { 5446 case 4, 8: 5447 // ok 5448 default: 5449 p.err(n, "unsupported volatile declarator size: %v", sz) 5450 return 5451 } 5452 5453 var ht string 5454 switch { 5455 case t.IsScalarType(): 5456 ht = p.helperType(n, t) 5457 default: 5458 p.err(n, "unsupported volatile declarator type: %v", t) 5459 return 5460 } 5461 5462 p.w("%sAtomicStore%s(&%s, %s(", p.task.crt, ht, nm, p.typ(n, t)) 5463 p.assignmentExpression(f, expr, t, mode, flags) 5464 p.w("))") 5465 } 5466 5467 func (p *project) atomicLoadNamedAddr(n cc.Node, t cc.Type, nm string) { 5468 sz := t.Size() 5469 switch sz { 5470 case 4, 8: 5471 // ok 5472 default: 5473 p.err(n, "unsupported volatile declarator size: %v", sz) 5474 return 5475 } 5476 5477 var ht string 5478 switch { 5479 case t.IsScalarType(): 5480 ht = p.helperType(n, t) 5481 default: 5482 p.err(n, "unsupported volatile declarator type: %v", t) 5483 return 5484 } 5485 5486 p.w("%sAtomicLoad%s(&%s)", p.task.crt, ht, nm) 5487 } 5488 5489 func isRealType(op cc.Operand) bool { 5490 switch op.Type().Kind() { 5491 case cc.Float, cc.Double: 5492 return true 5493 default: 5494 return false 5495 } 5496 } 5497 5498 func (p *project) bfHelperType(t cc.Type) string { 5499 switch { 5500 case t.IsSignedType(): 5501 return fmt.Sprintf("Int%d", t.Size()*8) 5502 default: 5503 return fmt.Sprintf("Uint%d", t.Size()*8) 5504 } 5505 } 5506 5507 func (p *project) helperType(n cc.Node, t cc.Type) string { 5508 for t.IsAliasType() { 5509 if t2 := t.Alias(); t2 != t { //TODO HDF5 H5O.c 5510 t = t2 5511 continue 5512 } 5513 5514 break 5515 } 5516 switch t.Kind() { 5517 case cc.Int128: 5518 return "Int128" 5519 case cc.UInt128: 5520 return "Uint128" 5521 } 5522 5523 s := p.typ(n, t) 5524 return strings.ToUpper(s[:1]) + s[1:] 5525 } 5526 5527 func (p *project) helperType2(n cc.Node, from, to cc.Type) string { 5528 if from.Kind() == to.Kind() { 5529 return fmt.Sprintf("%s%s", p.task.crt, p.helperType(n, from)) 5530 } 5531 5532 return fmt.Sprintf("%s%sFrom%s", p.task.crt, p.helperType(n, to), p.helperType(n, from)) 5533 } 5534 5535 func (p *project) conditionalExpression(f *function, n *cc.ConditionalExpression, t cc.Type, mode exprMode, flags flags) { 5536 switch mode { 5537 case exprValue: 5538 p.conditionalExpressionValue(f, n, t, mode, flags) 5539 case exprVoid: 5540 p.conditionalExpressionVoid(f, n, t, mode, flags) 5541 case exprAddrOf: 5542 p.conditionalExpressionAddrOf(f, n, t, mode, flags) 5543 case exprBool: 5544 p.conditionalExpressionBool(f, n, t, mode, flags) 5545 case exprLValue: 5546 p.conditionalExpressionLValue(f, n, t, mode, flags) 5547 case exprPSelect: 5548 p.conditionalExpressionPSelect(f, n, t, mode, flags) 5549 case exprFunc: 5550 p.conditionalExpressionFunc(f, n, t, mode, flags) 5551 case exprSelect: 5552 p.conditionalExpressionSelect(f, n, t, mode, flags) 5553 case exprCondReturn: 5554 p.conditionalExpressionReturn(f, n, t, mode, flags) 5555 case exprCondInit: 5556 p.conditionalExpressionInit(f, n, t, mode, flags) 5557 case exprDecay: 5558 p.conditionalExpressionDecay(f, n, t, mode, flags) 5559 default: 5560 panic(todo("", n.Position(), mode)) 5561 } 5562 } 5563 5564 func (p *project) conditionalExpressionDecay(f *function, n *cc.ConditionalExpression, t cc.Type, mode exprMode, flags flags) { 5565 switch n.Case { 5566 case cc.ConditionalExpressionLOr: // LogicalOrExpression 5567 p.logicalOrExpression(f, n.LogicalOrExpression, t, mode, flags) 5568 case cc.ConditionalExpressionCond: // LogicalOrExpression '?' Expression ':' ConditionalExpression 5569 t = t.Decay() 5570 p.w(" func() %s { if ", p.typ(n, t)) 5571 p.logicalOrExpression(f, n.LogicalOrExpression, n.LogicalOrExpression.Operand.Type(), exprBool, flags) 5572 p.w(" { return ") 5573 switch n.Expression.Operand.Type().Kind() { 5574 case cc.Array: 5575 p.expression(f, n.Expression, t, exprDecay, flags) 5576 case cc.Ptr: 5577 panic(todo("", n.Expression.Position(), n.Expression.Operand.Type())) 5578 default: 5579 panic(todo("", n.Expression.Position(), n.Expression.Operand.Type())) 5580 } 5581 p.w("}; return ") 5582 switch n.ConditionalExpression.Operand.Type().Kind() { 5583 case cc.Array: 5584 p.conditionalExpression(f, n.ConditionalExpression, t, exprDecay, flags) 5585 default: 5586 p.conditionalExpression(f, n.ConditionalExpression, t, exprValue, flags) 5587 } 5588 p.w("}()") 5589 default: 5590 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 5591 } 5592 } 5593 5594 func (p *project) conditionalExpressionInit(f *function, n *cc.ConditionalExpression, t cc.Type, mode exprMode, flags flags) { 5595 switch n.Case { 5596 case cc.ConditionalExpressionLOr: // LogicalOrExpression 5597 f.condInitPrefix() 5598 p.logicalOrExpression(f, n.LogicalOrExpression, t, exprValue, flags) 5599 case cc.ConditionalExpressionCond: // LogicalOrExpression '?' Expression ':' ConditionalExpression 5600 t = t.Decay() 5601 p.w("if ") 5602 p.logicalOrExpression(f, n.LogicalOrExpression, n.LogicalOrExpression.Operand.Type(), exprBool, flags) 5603 p.w(" {") 5604 p.expression(f, n.Expression, t, mode, flags) 5605 p.w("} else { ") 5606 p.conditionalExpression(f, n.ConditionalExpression, t, mode, flags) 5607 p.w("}") 5608 default: 5609 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 5610 } 5611 } 5612 5613 func (p *project) conditionalExpressionReturn(f *function, n *cc.ConditionalExpression, t cc.Type, mode exprMode, flags flags) { 5614 switch n.Case { 5615 case cc.ConditionalExpressionLOr: // LogicalOrExpression 5616 p.w("return ") 5617 p.logicalOrExpression(f, n.LogicalOrExpression, t, exprValue, flags) 5618 case cc.ConditionalExpressionCond: // LogicalOrExpression '?' Expression ':' ConditionalExpression 5619 t = t.Decay() 5620 p.w("if ") 5621 p.logicalOrExpression(f, n.LogicalOrExpression, n.LogicalOrExpression.Operand.Type(), exprBool, flags) 5622 p.w(" {") 5623 p.expression(f, n.Expression, t, mode, flags) 5624 p.w("}; ") 5625 p.conditionalExpression(f, n.ConditionalExpression, t, mode, flags) 5626 default: 5627 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 5628 } 5629 } 5630 5631 func (p *project) conditionalExpressionSelect(f *function, n *cc.ConditionalExpression, t cc.Type, mode exprMode, flags flags) { 5632 switch n.Case { 5633 case cc.ConditionalExpressionLOr: // LogicalOrExpression 5634 p.logicalOrExpression(f, n.LogicalOrExpression, t, mode, flags) 5635 case cc.ConditionalExpressionCond: // LogicalOrExpression '?' Expression ':' ConditionalExpression 5636 panic(todo("", p.pos(n))) 5637 default: 5638 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 5639 } 5640 } 5641 5642 func (p *project) conditionalExpressionFunc(f *function, n *cc.ConditionalExpression, t cc.Type, mode exprMode, flags flags) { 5643 switch n.Case { 5644 case cc.ConditionalExpressionLOr: // LogicalOrExpression 5645 p.logicalOrExpression(f, n.LogicalOrExpression, t, mode, flags) 5646 case cc.ConditionalExpressionCond: // LogicalOrExpression '?' Expression ':' ConditionalExpression 5647 switch ot := n.Operand.Type(); ot.Kind() { 5648 case cc.Function: 5649 if t.Kind() != cc.Function { 5650 panic(todo("", n.Position())) 5651 } 5652 default: 5653 panic(todo("", ot.Kind())) 5654 } 5655 5656 p.w(" func() ") 5657 p.functionSignature(n, f, t, "") 5658 p.w("{ if ") 5659 p.logicalOrExpression(f, n.LogicalOrExpression, n.LogicalOrExpression.Operand.Type(), exprBool, flags) 5660 p.w(" { return ") 5661 switch d := n.Expression.Declarator(); { 5662 case d != nil: 5663 p.declaratorDefault(n, d) 5664 default: 5665 panic(todo("", n.Position())) 5666 } 5667 p.w("}; return ") 5668 switch d := n.ConditionalExpression.Declarator(); { 5669 case d != nil: 5670 p.declaratorDefault(n, d) 5671 default: 5672 panic(todo("", n.Position())) 5673 } 5674 p.w("}()") 5675 default: 5676 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 5677 } 5678 } 5679 5680 func (p *project) conditionalExpressionPSelect(f *function, n *cc.ConditionalExpression, t cc.Type, mode exprMode, flags flags) { 5681 switch n.Case { 5682 case cc.ConditionalExpressionLOr: // LogicalOrExpression 5683 p.logicalOrExpression(f, n.LogicalOrExpression, t, mode, flags) 5684 case cc.ConditionalExpressionCond: // LogicalOrExpression '?' Expression ':' ConditionalExpression 5685 p.w("(*%s)(unsafe.Pointer(", p.typ(n, n.Operand.Type().Elem())) 5686 p.conditionalExpression(f, n, t, exprValue, flags) 5687 p.w("))") 5688 default: 5689 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 5690 } 5691 } 5692 5693 func (p *project) conditionalExpressionLValue(f *function, n *cc.ConditionalExpression, t cc.Type, mode exprMode, flags flags) { 5694 switch n.Case { 5695 case cc.ConditionalExpressionLOr: // LogicalOrExpression 5696 p.logicalOrExpression(f, n.LogicalOrExpression, t, mode, flags) 5697 case cc.ConditionalExpressionCond: // LogicalOrExpression '?' Expression ':' ConditionalExpression 5698 panic(todo("", p.pos(n))) 5699 default: 5700 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 5701 } 5702 } 5703 5704 func (p *project) conditionalExpressionBool(f *function, n *cc.ConditionalExpression, t cc.Type, mode exprMode, flags flags) { 5705 switch n.Case { 5706 case cc.ConditionalExpressionLOr: // LogicalOrExpression 5707 p.logicalOrExpression(f, n.LogicalOrExpression, t, mode, flags) 5708 case cc.ConditionalExpressionCond: // LogicalOrExpression '?' Expression ':' ConditionalExpression 5709 p.w("(") 5710 defer p.w(")") 5711 defer p.w(" != 0 ") 5712 p.conditionalExpression(f, n, t, exprValue, flags) 5713 default: 5714 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 5715 } 5716 } 5717 5718 func (p *project) conditionalExpressionAddrOf(f *function, n *cc.ConditionalExpression, t cc.Type, mode exprMode, flags flags) { 5719 switch n.Case { 5720 case cc.ConditionalExpressionLOr: // LogicalOrExpression 5721 p.logicalOrExpression(f, n.LogicalOrExpression, t, mode, flags) 5722 case cc.ConditionalExpressionCond: // LogicalOrExpression '?' Expression ':' ConditionalExpression 5723 t = t.Decay() 5724 p.w(" func() %s { if ", p.typ(n, t)) 5725 p.logicalOrExpression(f, n.LogicalOrExpression, n.LogicalOrExpression.Operand.Type(), exprBool, flags) 5726 p.w(" { return ") 5727 p.expression(f, n.Expression, t, exprValue, flags) 5728 p.w("}; return ") 5729 p.conditionalExpression(f, n.ConditionalExpression, t, exprValue, flags) 5730 p.w("}()") 5731 default: 5732 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 5733 } 5734 } 5735 5736 func (p *project) conditionalExpressionVoid(f *function, n *cc.ConditionalExpression, t cc.Type, mode exprMode, flags flags) { 5737 switch n.Case { 5738 case cc.ConditionalExpressionLOr: // LogicalOrExpression 5739 p.logicalOrExpression(f, n.LogicalOrExpression, t, mode, flags) 5740 case cc.ConditionalExpressionCond: // LogicalOrExpression '?' Expression ':' ConditionalExpression 5741 switch { 5742 case n.Expression.IsSideEffectsFree: 5743 p.w("if !(") 5744 p.logicalOrExpression(f, n.LogicalOrExpression, n.LogicalOrExpression.Operand.Type(), exprBool, flags) 5745 p.w(") {") 5746 p.conditionalExpression(f, n.ConditionalExpression, n.ConditionalExpression.Operand.Type(), mode, flags) 5747 p.w("}") 5748 default: 5749 p.w("if ") 5750 p.logicalOrExpression(f, n.LogicalOrExpression, n.LogicalOrExpression.Operand.Type(), exprBool, flags) 5751 p.w(" {") 5752 p.expression(f, n.Expression, n.Expression.Operand.Type(), mode, flags) 5753 p.w("} else {") 5754 p.conditionalExpression(f, n.ConditionalExpression, n.ConditionalExpression.Operand.Type(), mode, flags) 5755 p.w("}") 5756 } 5757 default: 5758 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 5759 } 5760 } 5761 5762 func (p *project) conditionalExpressionValue(f *function, n *cc.ConditionalExpression, t cc.Type, mode exprMode, flags flags) { 5763 switch n.Case { 5764 case cc.ConditionalExpressionLOr: // LogicalOrExpression 5765 p.logicalOrExpression(f, n.LogicalOrExpression, t, exprValue, flags) 5766 case cc.ConditionalExpressionCond: // LogicalOrExpression '?' Expression ':' ConditionalExpression 5767 t = t.Decay() 5768 p.w(" func() %s { if ", p.typ(n, t)) 5769 p.logicalOrExpression(f, n.LogicalOrExpression, n.LogicalOrExpression.Operand.Type(), exprBool, flags) 5770 p.w(" { return ") 5771 p.expression(f, n.Expression, t, exprValue, flags) 5772 p.w("}; return ") 5773 p.conditionalExpression(f, n.ConditionalExpression, t, exprValue, flags) 5774 p.w("}()") 5775 default: 5776 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 5777 } 5778 } 5779 5780 func (p *project) logicalOrExpression(f *function, n *cc.LogicalOrExpression, t cc.Type, mode exprMode, flags flags) { 5781 switch mode { 5782 case exprValue: 5783 p.logicalOrExpressionValue(f, n, t, mode, flags) 5784 case exprVoid: 5785 p.logicalOrExpressionVoid(f, n, t, mode, flags) 5786 case exprAddrOf: 5787 p.logicalOrExpressionAddrOf(f, n, t, mode, flags) 5788 case exprBool: 5789 p.logicalOrExpressionBool(f, n, t, mode, flags) 5790 case exprLValue: 5791 p.logicalOrExpressionLValue(f, n, t, mode, flags) 5792 case exprPSelect: 5793 p.logicalOrExpressionPSelect(f, n, t, mode, flags) 5794 case exprFunc: 5795 p.logicalOrExpressionFunc(f, n, t, mode, flags) 5796 case exprSelect: 5797 p.logicalOrExpressionSelect(f, n, t, mode, flags) 5798 case exprDecay: 5799 p.logicalOrExpressionDecay(f, n, t, mode, flags) 5800 default: 5801 panic(todo("", n.Position(), mode)) 5802 } 5803 } 5804 5805 func (p *project) logicalOrExpressionDecay(f *function, n *cc.LogicalOrExpression, t cc.Type, mode exprMode, flags flags) { 5806 switch n.Case { 5807 case cc.LogicalOrExpressionLAnd: // LogicalAndExpression 5808 p.logicalAndExpression(f, n.LogicalAndExpression, t, mode, flags) 5809 case cc.LogicalOrExpressionLOr: // LogicalOrExpression "||" LogicalAndExpression 5810 panic(todo("", p.pos(n))) 5811 default: 5812 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 5813 } 5814 } 5815 5816 func (p *project) logicalOrExpressionSelect(f *function, n *cc.LogicalOrExpression, t cc.Type, mode exprMode, flags flags) { 5817 switch n.Case { 5818 case cc.LogicalOrExpressionLAnd: // LogicalAndExpression 5819 p.logicalAndExpression(f, n.LogicalAndExpression, t, mode, flags) 5820 case cc.LogicalOrExpressionLOr: // LogicalOrExpression "||" LogicalAndExpression 5821 panic(todo("", p.pos(n))) 5822 default: 5823 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 5824 } 5825 } 5826 5827 func (p *project) logicalOrExpressionFunc(f *function, n *cc.LogicalOrExpression, t cc.Type, mode exprMode, flags flags) { 5828 switch n.Case { 5829 case cc.LogicalOrExpressionLAnd: // LogicalAndExpression 5830 p.logicalAndExpression(f, n.LogicalAndExpression, t, mode, flags) 5831 case cc.LogicalOrExpressionLOr: // LogicalOrExpression "||" LogicalAndExpression 5832 panic(todo("", p.pos(n))) 5833 default: 5834 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 5835 } 5836 } 5837 5838 func (p *project) logicalOrExpressionPSelect(f *function, n *cc.LogicalOrExpression, t cc.Type, mode exprMode, flags flags) { 5839 switch n.Case { 5840 case cc.LogicalOrExpressionLAnd: // LogicalAndExpression 5841 p.logicalAndExpression(f, n.LogicalAndExpression, t, mode, flags) 5842 case cc.LogicalOrExpressionLOr: // LogicalOrExpression "||" LogicalAndExpression 5843 panic(todo("", p.pos(n))) 5844 default: 5845 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 5846 } 5847 } 5848 5849 func (p *project) logicalOrExpressionLValue(f *function, n *cc.LogicalOrExpression, t cc.Type, mode exprMode, flags flags) { 5850 switch n.Case { 5851 case cc.LogicalOrExpressionLAnd: // LogicalAndExpression 5852 p.logicalAndExpression(f, n.LogicalAndExpression, t, mode, flags) 5853 case cc.LogicalOrExpressionLOr: // LogicalOrExpression "||" LogicalAndExpression 5854 panic(todo("", p.pos(n))) 5855 default: 5856 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 5857 } 5858 } 5859 5860 func (p *project) logicalOrExpressionBool(f *function, n *cc.LogicalOrExpression, t cc.Type, mode exprMode, flags flags) { 5861 switch n.Case { 5862 case cc.LogicalOrExpressionLAnd: // LogicalAndExpression 5863 p.logicalAndExpression(f, n.LogicalAndExpression, t, mode, flags) 5864 case cc.LogicalOrExpressionLOr: // LogicalOrExpression "||" LogicalAndExpression 5865 p.binaryLogicalOrExpression(f, n, t, mode, flags) 5866 default: 5867 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 5868 } 5869 } 5870 5871 func (p *project) logicalOrExpressionAddrOf(f *function, n *cc.LogicalOrExpression, t cc.Type, mode exprMode, flags flags) { 5872 switch n.Case { 5873 case cc.LogicalOrExpressionLAnd: // LogicalAndExpression 5874 p.logicalAndExpression(f, n.LogicalAndExpression, t, mode, flags) 5875 case cc.LogicalOrExpressionLOr: // LogicalOrExpression "||" LogicalAndExpression 5876 panic(todo("", p.pos(n))) 5877 default: 5878 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 5879 } 5880 } 5881 5882 func (p *project) logicalOrExpressionVoid(f *function, n *cc.LogicalOrExpression, t cc.Type, mode exprMode, flags flags) { 5883 switch n.Case { 5884 case cc.LogicalOrExpressionLAnd: // LogicalAndExpression 5885 p.logicalAndExpression(f, n.LogicalAndExpression, t, mode, flags) 5886 case cc.LogicalOrExpressionLOr: // LogicalOrExpression "||" LogicalAndExpression 5887 p.w("_ = ") 5888 p.logicalOrExpression(f, n, n.Operand.Type(), exprValue, flags) 5889 default: 5890 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 5891 } 5892 } 5893 5894 func (p *project) logicalOrExpressionValue(f *function, n *cc.LogicalOrExpression, t cc.Type, mode exprMode, flags flags) { 5895 switch n.Case { 5896 case cc.LogicalOrExpressionLAnd: // LogicalAndExpression 5897 p.logicalAndExpression(f, n.LogicalAndExpression, t, mode, flags) 5898 case cc.LogicalOrExpressionLOr: // LogicalOrExpression "||" LogicalAndExpression 5899 p.binaryLogicalOrExpression(f, n, t, mode, flags) 5900 default: 5901 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 5902 } 5903 } 5904 5905 func (p *project) binaryLogicalOrExpression(f *function, n *cc.LogicalOrExpression, t cc.Type, mode exprMode, flags flags) { 5906 switch mode { 5907 case exprValue: 5908 p.binaryLogicalOrExpressionValue(f, n, t, mode, flags) 5909 case exprBool: 5910 p.binaryLogicalOrExpressionBool(f, n, t, mode, flags) 5911 default: 5912 panic(todo("", n.Position(), mode)) 5913 } 5914 } 5915 5916 func (p *project) binaryLogicalOrExpressionBool(f *function, n *cc.LogicalOrExpression, t cc.Type, mode exprMode, flags flags) { 5917 defer p.w("%s", p.booleanBinaryExpression(n, n.Operand, n.Operand.Type(), &mode, flags)) 5918 p.logicalOrExpression(f, n.LogicalOrExpression, n.LogicalOrExpression.Operand.Type(), exprBool, flags) 5919 p.w(" ||%s", tidyComment(" ", &n.Token)) 5920 p.logicalAndExpression(f, n.LogicalAndExpression, n.LogicalAndExpression.Operand.Type(), exprBool, flags) 5921 } 5922 5923 func (p *project) binaryLogicalOrExpressionValue(f *function, n *cc.LogicalOrExpression, t cc.Type, mode exprMode, flags flags) { 5924 defer p.w("%s", p.booleanBinaryExpression(n, n.Operand, t, &mode, flags)) 5925 p.logicalOrExpression(f, n.LogicalOrExpression, n.LogicalOrExpression.Operand.Type(), exprBool, flags) 5926 p.w(" ||%s", tidyComment(" ", &n.Token)) 5927 p.logicalAndExpression(f, n.LogicalAndExpression, n.LogicalAndExpression.Operand.Type(), exprBool, flags) 5928 } 5929 5930 func (p *project) booleanBinaryExpression(n cc.Node, from cc.Operand, to cc.Type, mode *exprMode, flags flags) (r string) { 5931 p.w("(") 5932 r = ")" 5933 switch *mode { 5934 case exprBool: 5935 *mode = exprValue 5936 default: 5937 r = p.convert(n, from, to, flags) + r 5938 p.w("%sBool32(", p.task.crt) 5939 r = ")" + r 5940 } 5941 return r 5942 } 5943 5944 func (p *project) logicalAndExpression(f *function, n *cc.LogicalAndExpression, t cc.Type, mode exprMode, flags flags) { 5945 switch mode { 5946 case exprValue: 5947 p.logicalAndExpressionValue(f, n, t, mode, flags) 5948 case exprVoid: 5949 p.logicalAndExpressionVoid(f, n, t, mode, flags) 5950 case exprAddrOf: 5951 p.logicalAndExpressionAddrOf(f, n, t, mode, flags) 5952 case exprBool: 5953 p.logicalAndExpressionBool(f, n, t, mode, flags) 5954 case exprLValue: 5955 p.logicalAndExpressionLValue(f, n, t, mode, flags) 5956 case exprPSelect: 5957 p.logicalAndExpressionPSelect(f, n, t, mode, flags) 5958 case exprFunc: 5959 p.logicalAndExpressionFunc(f, n, t, mode, flags) 5960 case exprSelect: 5961 p.logicalAndExpressionSelect(f, n, t, mode, flags) 5962 case exprDecay: 5963 p.logicalAndExpressionDecay(f, n, t, mode, flags) 5964 default: 5965 panic(todo("", n.Position(), mode)) 5966 } 5967 } 5968 5969 func (p *project) logicalAndExpressionDecay(f *function, n *cc.LogicalAndExpression, t cc.Type, mode exprMode, flags flags) { 5970 switch n.Case { 5971 case cc.LogicalAndExpressionOr: // InclusiveOrExpression 5972 p.inclusiveOrExpression(f, n.InclusiveOrExpression, t, mode, flags) 5973 case cc.LogicalAndExpressionLAnd: // LogicalAndExpression "&&" InclusiveOrExpression 5974 panic(todo("", p.pos(n))) 5975 default: 5976 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 5977 } 5978 } 5979 5980 func (p *project) logicalAndExpressionSelect(f *function, n *cc.LogicalAndExpression, t cc.Type, mode exprMode, flags flags) { 5981 switch n.Case { 5982 case cc.LogicalAndExpressionOr: // InclusiveOrExpression 5983 p.inclusiveOrExpression(f, n.InclusiveOrExpression, t, mode, flags) 5984 case cc.LogicalAndExpressionLAnd: // LogicalAndExpression "&&" InclusiveOrExpression 5985 panic(todo("", p.pos(n))) 5986 default: 5987 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 5988 } 5989 } 5990 5991 func (p *project) logicalAndExpressionFunc(f *function, n *cc.LogicalAndExpression, t cc.Type, mode exprMode, flags flags) { 5992 switch n.Case { 5993 case cc.LogicalAndExpressionOr: // InclusiveOrExpression 5994 p.inclusiveOrExpression(f, n.InclusiveOrExpression, t, mode, flags) 5995 case cc.LogicalAndExpressionLAnd: // LogicalAndExpression "&&" InclusiveOrExpression 5996 panic(todo("", p.pos(n))) 5997 default: 5998 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 5999 } 6000 } 6001 6002 func (p *project) logicalAndExpressionPSelect(f *function, n *cc.LogicalAndExpression, t cc.Type, mode exprMode, flags flags) { 6003 switch n.Case { 6004 case cc.LogicalAndExpressionOr: // InclusiveOrExpression 6005 p.inclusiveOrExpression(f, n.InclusiveOrExpression, t, mode, flags) 6006 case cc.LogicalAndExpressionLAnd: // LogicalAndExpression "&&" InclusiveOrExpression 6007 panic(todo("", p.pos(n))) 6008 default: 6009 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 6010 } 6011 } 6012 6013 func (p *project) logicalAndExpressionLValue(f *function, n *cc.LogicalAndExpression, t cc.Type, mode exprMode, flags flags) { 6014 switch n.Case { 6015 case cc.LogicalAndExpressionOr: // InclusiveOrExpression 6016 p.inclusiveOrExpression(f, n.InclusiveOrExpression, t, mode, flags) 6017 case cc.LogicalAndExpressionLAnd: // LogicalAndExpression "&&" InclusiveOrExpression 6018 panic(todo("", p.pos(n))) 6019 default: 6020 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 6021 } 6022 } 6023 6024 func (p *project) logicalAndExpressionBool(f *function, n *cc.LogicalAndExpression, t cc.Type, mode exprMode, flags flags) { 6025 switch n.Case { 6026 case cc.LogicalAndExpressionOr: // InclusiveOrExpression 6027 p.inclusiveOrExpression(f, n.InclusiveOrExpression, t, mode, flags) 6028 case cc.LogicalAndExpressionLAnd: // LogicalAndExpression "&&" InclusiveOrExpression 6029 p.binaryLogicalAndExpression(f, n, t, mode, flags) 6030 default: 6031 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 6032 } 6033 } 6034 6035 func (p *project) logicalAndExpressionAddrOf(f *function, n *cc.LogicalAndExpression, t cc.Type, mode exprMode, flags flags) { 6036 switch n.Case { 6037 case cc.LogicalAndExpressionOr: // InclusiveOrExpression 6038 p.inclusiveOrExpression(f, n.InclusiveOrExpression, t, mode, flags) 6039 case cc.LogicalAndExpressionLAnd: // LogicalAndExpression "&&" InclusiveOrExpression 6040 panic(todo("", p.pos(n))) 6041 default: 6042 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 6043 } 6044 } 6045 6046 func (p *project) logicalAndExpressionVoid(f *function, n *cc.LogicalAndExpression, t cc.Type, mode exprMode, flags flags) { 6047 switch n.Case { 6048 case cc.LogicalAndExpressionOr: // InclusiveOrExpression 6049 p.inclusiveOrExpression(f, n.InclusiveOrExpression, t, mode, flags) 6050 case cc.LogicalAndExpressionLAnd: // LogicalAndExpression "&&" InclusiveOrExpression 6051 p.binaryLogicalAndExpressionValue(f, n, t, mode, flags) 6052 default: 6053 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 6054 } 6055 } 6056 6057 func (p *project) logicalAndExpressionValue(f *function, n *cc.LogicalAndExpression, t cc.Type, mode exprMode, flags flags) { 6058 switch n.Case { 6059 case cc.LogicalAndExpressionOr: // InclusiveOrExpression 6060 p.inclusiveOrExpression(f, n.InclusiveOrExpression, t, mode, flags) 6061 case cc.LogicalAndExpressionLAnd: // LogicalAndExpression "&&" InclusiveOrExpression 6062 p.binaryLogicalAndExpression(f, n, t, mode, flags) 6063 default: 6064 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 6065 } 6066 } 6067 6068 func (p *project) binaryLogicalAndExpression(f *function, n *cc.LogicalAndExpression, t cc.Type, mode exprMode, flags flags) { 6069 switch mode { 6070 case exprBool: 6071 p.binaryLogicalAndExpressionBool(f, n, t, mode, flags) 6072 case exprValue: 6073 p.binaryLogicalAndExpressionValue(f, n, t, mode, flags) 6074 default: 6075 panic(todo("", n.Position(), mode)) 6076 } 6077 } 6078 6079 func (p *project) binaryLogicalAndExpressionValue(f *function, n *cc.LogicalAndExpression, t cc.Type, mode exprMode, flags flags) { 6080 defer p.w("%s", p.booleanBinaryExpression(n, n.Operand, t, &mode, flags)) 6081 p.logicalAndExpression(f, n.LogicalAndExpression, n.LogicalAndExpression.Operand.Type(), exprBool, flags) 6082 p.w(" &&%s", tidyComment(" ", &n.Token)) 6083 p.inclusiveOrExpression(f, n.InclusiveOrExpression, n.InclusiveOrExpression.Operand.Type(), exprBool, flags) 6084 } 6085 6086 func (p *project) binaryLogicalAndExpressionBool(f *function, n *cc.LogicalAndExpression, t cc.Type, mode exprMode, flags flags) { 6087 defer p.w("%s", p.booleanBinaryExpression(n, n.Operand, t, &mode, flags)) 6088 p.logicalAndExpression(f, n.LogicalAndExpression, n.LogicalAndExpression.Operand.Type(), exprBool, flags) 6089 p.w(" &&%s", tidyComment(" ", &n.Token)) 6090 p.inclusiveOrExpression(f, n.InclusiveOrExpression, n.InclusiveOrExpression.Operand.Type(), exprBool, flags) 6091 } 6092 6093 func (p *project) inclusiveOrExpression(f *function, n *cc.InclusiveOrExpression, t cc.Type, mode exprMode, flags flags) { 6094 switch mode { 6095 case exprValue: 6096 p.inclusiveOrExpressionValue(f, n, t, mode, flags) 6097 case exprVoid: 6098 p.inclusiveOrExpressionVoid(f, n, t, mode, flags) 6099 case exprAddrOf: 6100 p.inclusiveOrExpressionAddrof(f, n, t, mode, flags) 6101 case exprBool: 6102 p.inclusiveOrExpressionBool(f, n, t, mode, flags) 6103 case exprLValue: 6104 p.inclusiveOrExpressionLValue(f, n, t, mode, flags) 6105 case exprPSelect: 6106 p.inclusiveOrExpressionPSelect(f, n, t, mode, flags) 6107 case exprFunc: 6108 p.inclusiveOrExpressionFunc(f, n, t, mode, flags) 6109 case exprSelect: 6110 p.inclusiveOrExpressionSelect(f, n, t, mode, flags) 6111 case exprDecay: 6112 p.inclusiveOrExpressionDecay(f, n, t, mode, flags) 6113 default: 6114 panic(todo("", n.Position(), mode)) 6115 } 6116 } 6117 6118 func (p *project) inclusiveOrExpressionDecay(f *function, n *cc.InclusiveOrExpression, t cc.Type, mode exprMode, flags flags) { 6119 switch n.Case { 6120 case cc.InclusiveOrExpressionXor: // ExclusiveOrExpression 6121 p.exclusiveOrExpression(f, n.ExclusiveOrExpression, t, mode, flags) 6122 case cc.InclusiveOrExpressionOr: // InclusiveOrExpression '|' ExclusiveOrExpression 6123 panic(todo("", p.pos(n))) 6124 default: 6125 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 6126 } 6127 } 6128 6129 func (p *project) inclusiveOrExpressionSelect(f *function, n *cc.InclusiveOrExpression, t cc.Type, mode exprMode, flags flags) { 6130 switch n.Case { 6131 case cc.InclusiveOrExpressionXor: // ExclusiveOrExpression 6132 p.exclusiveOrExpression(f, n.ExclusiveOrExpression, t, mode, flags) 6133 case cc.InclusiveOrExpressionOr: // InclusiveOrExpression '|' ExclusiveOrExpression 6134 panic(todo("", p.pos(n))) 6135 default: 6136 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 6137 } 6138 } 6139 6140 func (p *project) inclusiveOrExpressionFunc(f *function, n *cc.InclusiveOrExpression, t cc.Type, mode exprMode, flags flags) { 6141 switch n.Case { 6142 case cc.InclusiveOrExpressionXor: // ExclusiveOrExpression 6143 p.exclusiveOrExpression(f, n.ExclusiveOrExpression, t, mode, flags) 6144 case cc.InclusiveOrExpressionOr: // InclusiveOrExpression '|' ExclusiveOrExpression 6145 panic(todo("", p.pos(n))) 6146 default: 6147 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 6148 } 6149 } 6150 6151 func (p *project) inclusiveOrExpressionPSelect(f *function, n *cc.InclusiveOrExpression, t cc.Type, mode exprMode, flags flags) { 6152 switch n.Case { 6153 case cc.InclusiveOrExpressionXor: // ExclusiveOrExpression 6154 p.exclusiveOrExpression(f, n.ExclusiveOrExpression, t, mode, flags) 6155 case cc.InclusiveOrExpressionOr: // InclusiveOrExpression '|' ExclusiveOrExpression 6156 panic(todo("", p.pos(n))) 6157 default: 6158 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 6159 } 6160 } 6161 6162 func (p *project) inclusiveOrExpressionLValue(f *function, n *cc.InclusiveOrExpression, t cc.Type, mode exprMode, flags flags) { 6163 switch n.Case { 6164 case cc.InclusiveOrExpressionXor: // ExclusiveOrExpression 6165 p.exclusiveOrExpression(f, n.ExclusiveOrExpression, t, mode, flags) 6166 case cc.InclusiveOrExpressionOr: // InclusiveOrExpression '|' ExclusiveOrExpression 6167 panic(todo("", p.pos(n))) 6168 default: 6169 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 6170 } 6171 } 6172 6173 func (p *project) inclusiveOrExpressionBool(f *function, n *cc.InclusiveOrExpression, t cc.Type, mode exprMode, flags flags) { 6174 switch n.Case { 6175 case cc.InclusiveOrExpressionXor: // ExclusiveOrExpression 6176 p.exclusiveOrExpression(f, n.ExclusiveOrExpression, t, mode, flags) 6177 case cc.InclusiveOrExpressionOr: // InclusiveOrExpression '|' ExclusiveOrExpression 6178 p.binaryInclusiveOrExpression(f, n, t, mode, flags) 6179 default: 6180 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 6181 } 6182 } 6183 6184 func (p *project) inclusiveOrExpressionAddrof(f *function, n *cc.InclusiveOrExpression, t cc.Type, mode exprMode, flags flags) { 6185 switch n.Case { 6186 case cc.InclusiveOrExpressionXor: // ExclusiveOrExpression 6187 p.exclusiveOrExpression(f, n.ExclusiveOrExpression, t, mode, flags) 6188 case cc.InclusiveOrExpressionOr: // InclusiveOrExpression '|' ExclusiveOrExpression 6189 panic(todo("", p.pos(n))) 6190 default: 6191 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 6192 } 6193 } 6194 6195 func (p *project) inclusiveOrExpressionVoid(f *function, n *cc.InclusiveOrExpression, t cc.Type, mode exprMode, flags flags) { 6196 switch n.Case { 6197 case cc.InclusiveOrExpressionXor: // ExclusiveOrExpression 6198 p.exclusiveOrExpression(f, n.ExclusiveOrExpression, t, mode, flags) 6199 case cc.InclusiveOrExpressionOr: // InclusiveOrExpression '|' ExclusiveOrExpression 6200 p.w("_ = ") 6201 p.inclusiveOrExpression(f, n, n.Operand.Type(), exprValue, flags) 6202 default: 6203 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 6204 } 6205 } 6206 6207 func (p *project) inclusiveOrExpressionValue(f *function, n *cc.InclusiveOrExpression, t cc.Type, mode exprMode, flags flags) { 6208 switch n.Case { 6209 case cc.InclusiveOrExpressionXor: // ExclusiveOrExpression 6210 p.exclusiveOrExpression(f, n.ExclusiveOrExpression, t, mode, flags) 6211 case cc.InclusiveOrExpressionOr: // InclusiveOrExpression '|' ExclusiveOrExpression 6212 p.binaryInclusiveOrExpression(f, n, t, mode, flags) 6213 default: 6214 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 6215 } 6216 } 6217 6218 func (p *project) binaryInclusiveOrExpression(f *function, n *cc.InclusiveOrExpression, t cc.Type, mode exprMode, flags flags) { 6219 // InclusiveOrExpression '|' ExclusiveOrExpression 6220 switch mode { 6221 case exprBool: 6222 p.binaryInclusiveOrExpressionBool(f, n, t, mode, flags) 6223 case exprValue: 6224 p.binaryInclusiveOrExpressionValue(f, n, t, mode, flags) 6225 default: 6226 panic(todo("", n.Position(), mode)) 6227 } 6228 } 6229 6230 func (p *project) binaryInclusiveOrExpressionValue(f *function, n *cc.InclusiveOrExpression, t cc.Type, mode exprMode, flags flags) { 6231 // InclusiveOrExpression '|' ExclusiveOrExpression 6232 6233 lt := n.InclusiveOrExpression.Operand.Type() 6234 rt := n.ExclusiveOrExpression.Operand.Type() 6235 switch lk, rk := lt.Kind(), rt.Kind(); { 6236 case 6237 lk == cc.UInt128 || rk == cc.UInt128, 6238 lk == cc.Int128 || rk == cc.Int128: 6239 6240 p.binaryOrExpressionUint128(f, n, t, mode, flags) 6241 return 6242 } 6243 6244 defer p.w("%s", p.artithmeticBinaryExpression(n, n.Operand, t, &mode, flags)) 6245 switch { 6246 case orOverflows(n.InclusiveOrExpression.Operand, n.ExclusiveOrExpression.Operand, n.Promote()): 6247 p.inclusiveOrExpression(f, n.InclusiveOrExpression, n.Promote(), exprValue, flags) 6248 p.w(" |%s", tidyComment(" ", &n.Token)) 6249 p.exclusiveOrExpression(f, n.ExclusiveOrExpression, n.Promote(), exprValue, flags|fForceRuntimeConv) 6250 default: 6251 p.inclusiveOrExpression(f, n.InclusiveOrExpression, n.Promote(), exprValue, flags) 6252 p.w(" |%s", tidyComment(" ", &n.Token)) 6253 p.exclusiveOrExpression(f, n.ExclusiveOrExpression, n.Promote(), exprValue, flags) 6254 } 6255 } 6256 6257 func (p *project) binaryOrExpressionUint128(f *function, n *cc.InclusiveOrExpression, t cc.Type, mode exprMode, flags flags) { 6258 // InclusiveOrExpression '|' ExclusiveOrExpression 6259 defer p.w("%s", p.artithmeticBinaryExpression(n, n.Operand, t, &mode, flags)) 6260 p.inclusiveOrExpression(f, n.InclusiveOrExpression, n.Promote(), exprValue, flags) 6261 p.w(".Or(") 6262 p.exclusiveOrExpression(f, n.ExclusiveOrExpression, n.Promote(), exprValue, flags) 6263 p.w(")") 6264 } 6265 6266 func (p *project) binaryInclusiveOrExpressionBool(f *function, n *cc.InclusiveOrExpression, t cc.Type, mode exprMode, flags flags) { 6267 defer p.w("%s", p.artithmeticBinaryExpression(n, n.Operand, t, &mode, flags)) 6268 switch { 6269 case orOverflows(n.InclusiveOrExpression.Operand, n.ExclusiveOrExpression.Operand, n.Promote()): 6270 p.inclusiveOrExpression(f, n.InclusiveOrExpression, n.Promote(), exprValue, flags) 6271 p.w(" |%s", tidyComment(" ", &n.Token)) 6272 p.exclusiveOrExpression(f, n.ExclusiveOrExpression, n.Promote(), exprValue, flags|fForceRuntimeConv) 6273 default: 6274 p.inclusiveOrExpression(f, n.InclusiveOrExpression, n.Promote(), exprValue, flags) 6275 p.w(" |%s", tidyComment(" ", &n.Token)) 6276 p.exclusiveOrExpression(f, n.ExclusiveOrExpression, n.Promote(), exprValue, flags) 6277 } 6278 } 6279 6280 func orOverflows(lo, ro cc.Operand, promote cc.Type) bool { 6281 a, b, ok := getIntOperands(lo, ro) 6282 if !ok { 6283 return false 6284 } 6285 6286 return overflows(a.Or(a, b), promote) 6287 } 6288 6289 func (p *project) artithmeticBinaryExpression(n cc.Node, from cc.Operand, to cc.Type, mode *exprMode, flags flags) (r string) { 6290 p.w("(") 6291 r = ")" 6292 switch *mode { 6293 case exprBool: 6294 p.w("(") 6295 r = ") != 0" + r 6296 *mode = exprValue 6297 default: 6298 switch fk, tk := from.Type().Kind(), to.Kind(); { 6299 case fk != tk && fk == cc.Int128: 6300 return fmt.Sprintf(".%s()%s", p.helperType(n, to), r) 6301 case fk != tk && fk == cc.UInt128: 6302 return fmt.Sprintf(".%s()%s", p.helperType(n, to), r) 6303 default: 6304 r = p.convert(n, from, to, flags) + r 6305 } 6306 } 6307 return r 6308 } 6309 6310 func (p *project) exclusiveOrExpression(f *function, n *cc.ExclusiveOrExpression, t cc.Type, mode exprMode, flags flags) { 6311 switch mode { 6312 case exprValue: 6313 p.exclusiveOrExpressionValue(f, n, t, mode, flags) 6314 case exprVoid: 6315 p.exclusiveOrExpressionVoid(f, n, t, mode, flags) 6316 case exprAddrOf: 6317 p.exclusiveOrExpressionAddrOf(f, n, t, mode, flags) 6318 case exprBool: 6319 p.exclusiveOrExpressionBool(f, n, t, mode, flags) 6320 case exprLValue: 6321 p.exclusiveOrExpressionLValue(f, n, t, mode, flags) 6322 case exprPSelect: 6323 p.exclusiveOrExpressionPSelect(f, n, t, mode, flags) 6324 case exprFunc: 6325 p.exclusiveOrExpressionFunc(f, n, t, mode, flags) 6326 case exprSelect: 6327 p.exclusiveOrExpressionSelect(f, n, t, mode, flags) 6328 case exprDecay: 6329 p.exclusiveOrExpressionDecay(f, n, t, mode, flags) 6330 default: 6331 panic(todo("", n.Position(), mode)) 6332 } 6333 } 6334 6335 func (p *project) exclusiveOrExpressionDecay(f *function, n *cc.ExclusiveOrExpression, t cc.Type, mode exprMode, flags flags) { 6336 switch n.Case { 6337 case cc.ExclusiveOrExpressionAnd: // AndExpression 6338 p.andExpression(f, n.AndExpression, t, mode, flags) 6339 case cc.ExclusiveOrExpressionXor: // ExclusiveOrExpression '^' AndExpression 6340 panic(todo("", p.pos(n))) 6341 default: 6342 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 6343 } 6344 } 6345 6346 func (p *project) exclusiveOrExpressionSelect(f *function, n *cc.ExclusiveOrExpression, t cc.Type, mode exprMode, flags flags) { 6347 switch n.Case { 6348 case cc.ExclusiveOrExpressionAnd: // AndExpression 6349 p.andExpression(f, n.AndExpression, t, mode, flags) 6350 case cc.ExclusiveOrExpressionXor: // ExclusiveOrExpression '^' AndExpression 6351 panic(todo("", p.pos(n))) 6352 default: 6353 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 6354 } 6355 } 6356 6357 func (p *project) exclusiveOrExpressionFunc(f *function, n *cc.ExclusiveOrExpression, t cc.Type, mode exprMode, flags flags) { 6358 switch n.Case { 6359 case cc.ExclusiveOrExpressionAnd: // AndExpression 6360 p.andExpression(f, n.AndExpression, t, mode, flags) 6361 case cc.ExclusiveOrExpressionXor: // ExclusiveOrExpression '^' AndExpression 6362 panic(todo("", p.pos(n))) 6363 default: 6364 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 6365 } 6366 } 6367 6368 func (p *project) exclusiveOrExpressionPSelect(f *function, n *cc.ExclusiveOrExpression, t cc.Type, mode exprMode, flags flags) { 6369 switch n.Case { 6370 case cc.ExclusiveOrExpressionAnd: // AndExpression 6371 p.andExpression(f, n.AndExpression, t, mode, flags) 6372 case cc.ExclusiveOrExpressionXor: // ExclusiveOrExpression '^' AndExpression 6373 panic(todo("", p.pos(n))) 6374 default: 6375 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 6376 } 6377 } 6378 6379 func (p *project) exclusiveOrExpressionLValue(f *function, n *cc.ExclusiveOrExpression, t cc.Type, mode exprMode, flags flags) { 6380 switch n.Case { 6381 case cc.ExclusiveOrExpressionAnd: // AndExpression 6382 p.andExpression(f, n.AndExpression, t, mode, flags) 6383 case cc.ExclusiveOrExpressionXor: // ExclusiveOrExpression '^' AndExpression 6384 panic(todo("", p.pos(n))) 6385 default: 6386 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 6387 } 6388 } 6389 6390 func (p *project) exclusiveOrExpressionBool(f *function, n *cc.ExclusiveOrExpression, t cc.Type, mode exprMode, flags flags) { 6391 switch n.Case { 6392 case cc.ExclusiveOrExpressionAnd: // AndExpression 6393 p.andExpression(f, n.AndExpression, t, mode, flags) 6394 case cc.ExclusiveOrExpressionXor: // ExclusiveOrExpression '^' AndExpression 6395 p.binaryExclusiveOrExpression(f, n, t, mode, flags) 6396 default: 6397 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 6398 } 6399 } 6400 6401 func (p *project) exclusiveOrExpressionAddrOf(f *function, n *cc.ExclusiveOrExpression, t cc.Type, mode exprMode, flags flags) { 6402 switch n.Case { 6403 case cc.ExclusiveOrExpressionAnd: // AndExpression 6404 p.andExpression(f, n.AndExpression, t, mode, flags) 6405 case cc.ExclusiveOrExpressionXor: // ExclusiveOrExpression '^' AndExpression 6406 panic(todo("", p.pos(n))) 6407 default: 6408 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 6409 } 6410 } 6411 6412 func (p *project) exclusiveOrExpressionVoid(f *function, n *cc.ExclusiveOrExpression, t cc.Type, mode exprMode, flags flags) { 6413 switch n.Case { 6414 case cc.ExclusiveOrExpressionAnd: // AndExpression 6415 p.andExpression(f, n.AndExpression, t, mode, flags) 6416 case cc.ExclusiveOrExpressionXor: // ExclusiveOrExpression '^' AndExpression 6417 p.w("_ = ") 6418 p.exclusiveOrExpression(f, n, n.Operand.Type(), exprValue, flags) 6419 default: 6420 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 6421 } 6422 } 6423 6424 func (p *project) exclusiveOrExpressionValue(f *function, n *cc.ExclusiveOrExpression, t cc.Type, mode exprMode, flags flags) { 6425 switch n.Case { 6426 case cc.ExclusiveOrExpressionAnd: // AndExpression 6427 p.andExpression(f, n.AndExpression, t, mode, flags) 6428 case cc.ExclusiveOrExpressionXor: // ExclusiveOrExpression '^' AndExpression 6429 p.binaryExclusiveOrExpression(f, n, t, mode, flags) 6430 default: 6431 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 6432 } 6433 } 6434 6435 func (p *project) binaryExclusiveOrExpression(f *function, n *cc.ExclusiveOrExpression, t cc.Type, mode exprMode, flags flags) { 6436 // ExclusiveOrExpression '^' AndExpression 6437 switch mode { 6438 case exprValue, exprBool: 6439 p.binaryExclusiveOrExpressionValue(f, n, t, mode, flags) 6440 default: 6441 panic(todo("", n.Position(), mode)) 6442 } 6443 } 6444 6445 func (p *project) binaryExclusiveOrExpressionValue(f *function, n *cc.ExclusiveOrExpression, t cc.Type, mode exprMode, flags flags) { 6446 // ExclusiveOrExpression '^' AndExpression 6447 6448 lt := n.ExclusiveOrExpression.Operand.Type() 6449 rt := n.AndExpression.Operand.Type() 6450 switch lk, rk := lt.Kind(), rt.Kind(); { 6451 case 6452 lk == cc.UInt128 || rk == cc.UInt128, 6453 lk == cc.Int128 || rk == cc.Int128: 6454 6455 p.binaryExclusiveOrExpressionUint128(f, n, t, mode, flags) 6456 return 6457 } 6458 6459 defer p.w("%s", p.artithmeticBinaryExpression(n, n.Operand, t, &mode, flags)) 6460 switch { 6461 case xorOverflows(n.ExclusiveOrExpression.Operand, n.AndExpression.Operand, n.Promote()): 6462 p.exclusiveOrExpression(f, n.ExclusiveOrExpression, n.Promote(), exprValue, flags) 6463 p.w(" ^%s", tidyComment(" ", &n.Token)) 6464 p.andExpression(f, n.AndExpression, n.Promote(), exprValue, flags|fForceRuntimeConv) 6465 default: 6466 p.exclusiveOrExpression(f, n.ExclusiveOrExpression, n.Promote(), exprValue, flags) 6467 p.w(" ^%s", tidyComment(" ", &n.Token)) 6468 p.andExpression(f, n.AndExpression, n.Promote(), exprValue, flags) 6469 } 6470 } 6471 6472 func (p *project) binaryExclusiveOrExpressionUint128(f *function, n *cc.ExclusiveOrExpression, t cc.Type, mode exprMode, flags flags) { 6473 // ExclusiveOrExpression '^' AndExpression 6474 defer p.w("%s", p.artithmeticBinaryExpression(n, n.Operand, t, &mode, flags)) 6475 p.exclusiveOrExpression(f, n.ExclusiveOrExpression, n.Promote(), exprValue, flags) 6476 p.w(".Xor(") 6477 p.andExpression(f, n.AndExpression, n.Promote(), exprValue, flags) 6478 p.w(")") 6479 } 6480 6481 func xorOverflows(lo, ro cc.Operand, promote cc.Type) bool { 6482 a, b, ok := getIntOperands(lo, ro) 6483 if !ok { 6484 return false 6485 } 6486 6487 return !lo.Type().IsSignedType() && a.Sign() == 0 || 6488 !ro.Type().IsSignedType() && b.Sign() == 0 || 6489 overflows(a.Xor(a, b), promote) 6490 } 6491 6492 func (p *project) andExpression(f *function, n *cc.AndExpression, t cc.Type, mode exprMode, flags flags) { 6493 switch mode { 6494 case exprValue: 6495 p.andExpressionValue(f, n, t, mode, flags) 6496 case exprVoid: 6497 p.andExpressionVoid(f, n, t, mode, flags) 6498 case exprAddrOf: 6499 p.andExpressionAddrof(f, n, t, mode, flags) 6500 case exprBool: 6501 p.andExpressionBool(f, n, t, mode, flags) 6502 case exprLValue: 6503 p.andExpressionLValue(f, n, t, mode, flags) 6504 case exprPSelect: 6505 p.andExpressionPSelect(f, n, t, mode, flags) 6506 case exprFunc: 6507 p.andExpressionFunc(f, n, t, mode, flags) 6508 case exprSelect: 6509 p.andExpressionSelect(f, n, t, mode, flags) 6510 case exprDecay: 6511 p.andExpressionDecay(f, n, t, mode, flags) 6512 default: 6513 panic(todo("", n.Position(), mode)) 6514 } 6515 } 6516 6517 func (p *project) andExpressionDecay(f *function, n *cc.AndExpression, t cc.Type, mode exprMode, flags flags) { 6518 switch n.Case { 6519 case cc.AndExpressionEq: // EqualityExpression 6520 p.equalityExpression(f, n.EqualityExpression, t, mode, flags) 6521 case cc.AndExpressionAnd: // AndExpression '&' EqualityExpression 6522 panic(todo("", p.pos(n))) 6523 default: 6524 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 6525 } 6526 } 6527 6528 func (p *project) andExpressionSelect(f *function, n *cc.AndExpression, t cc.Type, mode exprMode, flags flags) { 6529 switch n.Case { 6530 case cc.AndExpressionEq: // EqualityExpression 6531 p.equalityExpression(f, n.EqualityExpression, t, mode, flags) 6532 case cc.AndExpressionAnd: // AndExpression '&' EqualityExpression 6533 panic(todo("", p.pos(n))) 6534 default: 6535 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 6536 } 6537 } 6538 6539 func (p *project) andExpressionFunc(f *function, n *cc.AndExpression, t cc.Type, mode exprMode, flags flags) { 6540 switch n.Case { 6541 case cc.AndExpressionEq: // EqualityExpression 6542 p.equalityExpression(f, n.EqualityExpression, t, mode, flags) 6543 case cc.AndExpressionAnd: // AndExpression '&' EqualityExpression 6544 panic(todo("", p.pos(n))) 6545 default: 6546 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 6547 } 6548 } 6549 6550 func (p *project) andExpressionPSelect(f *function, n *cc.AndExpression, t cc.Type, mode exprMode, flags flags) { 6551 switch n.Case { 6552 case cc.AndExpressionEq: // EqualityExpression 6553 p.equalityExpression(f, n.EqualityExpression, t, mode, flags) 6554 case cc.AndExpressionAnd: // AndExpression '&' EqualityExpression 6555 panic(todo("", p.pos(n))) 6556 default: 6557 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 6558 } 6559 } 6560 6561 func (p *project) andExpressionLValue(f *function, n *cc.AndExpression, t cc.Type, mode exprMode, flags flags) { 6562 switch n.Case { 6563 case cc.AndExpressionEq: // EqualityExpression 6564 p.equalityExpression(f, n.EqualityExpression, t, mode, flags) 6565 case cc.AndExpressionAnd: // AndExpression '&' EqualityExpression 6566 panic(todo("", p.pos(n))) 6567 default: 6568 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 6569 } 6570 } 6571 6572 func (p *project) andExpressionBool(f *function, n *cc.AndExpression, t cc.Type, mode exprMode, flags flags) { 6573 switch n.Case { 6574 case cc.AndExpressionEq: // EqualityExpression 6575 p.equalityExpression(f, n.EqualityExpression, t, mode, flags) 6576 case cc.AndExpressionAnd: // AndExpression '&' EqualityExpression 6577 p.binaryAndExpression(f, n, t, mode, flags) 6578 default: 6579 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 6580 } 6581 } 6582 6583 func (p *project) andExpressionAddrof(f *function, n *cc.AndExpression, t cc.Type, mode exprMode, flags flags) { 6584 switch n.Case { 6585 case cc.AndExpressionEq: // EqualityExpression 6586 p.equalityExpression(f, n.EqualityExpression, t, mode, flags) 6587 case cc.AndExpressionAnd: // AndExpression '&' EqualityExpression 6588 panic(todo("", p.pos(n))) 6589 default: 6590 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 6591 } 6592 } 6593 6594 func (p *project) andExpressionVoid(f *function, n *cc.AndExpression, t cc.Type, mode exprMode, flags flags) { 6595 switch n.Case { 6596 case cc.AndExpressionEq: // EqualityExpression 6597 p.equalityExpression(f, n.EqualityExpression, t, mode, flags) 6598 case cc.AndExpressionAnd: // AndExpression '&' EqualityExpression 6599 p.w("_ = ") 6600 p.andExpression(f, n, n.Operand.Type(), exprValue, flags) 6601 default: 6602 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 6603 } 6604 } 6605 6606 func (p *project) andExpressionValue(f *function, n *cc.AndExpression, t cc.Type, mode exprMode, flags flags) { 6607 switch n.Case { 6608 case cc.AndExpressionEq: // EqualityExpression 6609 p.equalityExpression(f, n.EqualityExpression, t, mode, flags) 6610 case cc.AndExpressionAnd: // AndExpression '&' EqualityExpression 6611 p.binaryAndExpression(f, n, t, mode, flags) 6612 default: 6613 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 6614 } 6615 } 6616 6617 func (p *project) binaryAndExpression(f *function, n *cc.AndExpression, t cc.Type, mode exprMode, flags flags) { 6618 // AndExpression '&' EqualityExpression 6619 switch mode { 6620 case exprValue: 6621 p.binaryAndExpressionValue(f, n, t, mode, flags) 6622 case exprBool: 6623 p.binaryAndExpressionBool(f, n, t, mode, flags) 6624 default: 6625 panic(todo("", n.Position(), mode)) 6626 } 6627 } 6628 6629 func (p *project) binaryAndExpressionBool(f *function, n *cc.AndExpression, t cc.Type, mode exprMode, flags flags) { 6630 defer p.w("%s", p.artithmeticBinaryExpression(n, n.Operand, n.Operand.Type(), &mode, flags)) 6631 switch { 6632 case andOverflows(n.AndExpression.Operand, n.EqualityExpression.Operand, n.Promote()): 6633 p.andExpression(f, n.AndExpression, n.Promote(), exprValue, flags) 6634 p.w(" &%s", tidyComment(" ", &n.Token)) 6635 p.equalityExpression(f, n.EqualityExpression, n.Promote(), exprValue, flags|fForceRuntimeConv) 6636 default: 6637 p.andExpression(f, n.AndExpression, n.Promote(), exprValue, flags) 6638 p.w(" &%s", tidyComment(" ", &n.Token)) 6639 p.equalityExpression(f, n.EqualityExpression, n.Promote(), exprValue, flags) 6640 } 6641 } 6642 6643 func (p *project) binaryAndExpressionValue(f *function, n *cc.AndExpression, t cc.Type, mode exprMode, flags flags) { 6644 // AndExpression '&' EqualityExpression 6645 6646 lt := n.AndExpression.Operand.Type() 6647 rt := n.EqualityExpression.Operand.Type() 6648 switch lk, rk := lt.Kind(), rt.Kind(); { 6649 case 6650 lk == cc.UInt128 || rk == cc.UInt128, 6651 lk == cc.Int128 || rk == cc.Int128: 6652 6653 p.binaryAndExpressionUint128(f, n, t, mode, flags) 6654 return 6655 } 6656 6657 defer p.w("%s", p.artithmeticBinaryExpression(n, n.Operand, t, &mode, flags)) 6658 switch { 6659 case andOverflows(n.AndExpression.Operand, n.EqualityExpression.Operand, n.Promote()): 6660 p.andExpression(f, n.AndExpression, n.Promote(), exprValue, flags) 6661 p.w(" &%s", tidyComment(" ", &n.Token)) 6662 p.equalityExpression(f, n.EqualityExpression, n.Promote(), exprValue, flags|fForceRuntimeConv) 6663 default: 6664 p.andExpression(f, n.AndExpression, n.Promote(), exprValue, flags) 6665 p.w(" &%s", tidyComment(" ", &n.Token)) 6666 p.equalityExpression(f, n.EqualityExpression, n.Promote(), exprValue, flags) 6667 } 6668 } 6669 6670 func (p *project) binaryAndExpressionUint128(f *function, n *cc.AndExpression, t cc.Type, mode exprMode, flags flags) { 6671 // AndExpression '&' EqualityExpression 6672 defer p.w("%s", p.artithmeticBinaryExpression(n, n.Operand, t, &mode, flags)) 6673 p.andExpression(f, n.AndExpression, n.Promote(), exprValue, flags) 6674 p.w(".And(") 6675 p.equalityExpression(f, n.EqualityExpression, n.Promote(), exprValue, flags) 6676 p.w(")") 6677 } 6678 6679 func andOverflows(lo, ro cc.Operand, promote cc.Type) bool { 6680 a, b, ok := getIntOperands(lo, ro) 6681 if !ok { 6682 return false 6683 } 6684 6685 return overflows(a.And(a, b), promote) 6686 } 6687 6688 func (p *project) equalityExpression(f *function, n *cc.EqualityExpression, t cc.Type, mode exprMode, flags flags) { 6689 switch mode { 6690 case exprValue: 6691 p.equalityExpressionValue(f, n, t, mode, flags) 6692 case exprVoid: 6693 p.equalityExpressionVoid(f, n, t, mode, flags) 6694 case exprAddrOf: 6695 p.equalityExpressionAddrOf(f, n, t, mode, flags) 6696 case exprBool: 6697 p.equalityExpressionBool(f, n, t, mode, flags) 6698 case exprLValue: 6699 p.equalityExpressionLValue(f, n, t, mode, flags) 6700 case exprPSelect: 6701 p.equalityExpressionPSelect(f, n, t, mode, flags) 6702 case exprFunc: 6703 p.equalityExpressionFunc(f, n, t, mode, flags) 6704 case exprSelect: 6705 p.equalityExpressionSelect(f, n, t, mode, flags) 6706 case exprDecay: 6707 p.equalityExpressionDecay(f, n, t, mode, flags) 6708 default: 6709 panic(todo("", n.Position(), mode)) 6710 } 6711 } 6712 6713 func (p *project) equalityExpressionDecay(f *function, n *cc.EqualityExpression, t cc.Type, mode exprMode, flags flags) { 6714 switch n.Case { 6715 case cc.EqualityExpressionRel: // RelationalExpression 6716 p.relationalExpression(f, n.RelationalExpression, t, mode, flags) 6717 case cc.EqualityExpressionEq: // EqualityExpression "==" RelationalExpression 6718 panic(todo("", p.pos(n))) 6719 case cc.EqualityExpressionNeq: // EqualityExpression "!=" RelationalExpression 6720 panic(todo("", p.pos(n))) 6721 default: 6722 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 6723 } 6724 } 6725 6726 func (p *project) equalityExpressionSelect(f *function, n *cc.EqualityExpression, t cc.Type, mode exprMode, flags flags) { 6727 switch n.Case { 6728 case cc.EqualityExpressionRel: // RelationalExpression 6729 p.relationalExpression(f, n.RelationalExpression, t, mode, flags) 6730 case cc.EqualityExpressionEq: // EqualityExpression "==" RelationalExpression 6731 panic(todo("", p.pos(n))) 6732 case cc.EqualityExpressionNeq: // EqualityExpression "!=" RelationalExpression 6733 panic(todo("", p.pos(n))) 6734 default: 6735 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 6736 } 6737 } 6738 6739 func (p *project) equalityExpressionFunc(f *function, n *cc.EqualityExpression, t cc.Type, mode exprMode, flags flags) { 6740 switch n.Case { 6741 case cc.EqualityExpressionRel: // RelationalExpression 6742 p.relationalExpression(f, n.RelationalExpression, t, mode, flags) 6743 case cc.EqualityExpressionEq: // EqualityExpression "==" RelationalExpression 6744 panic(todo("", p.pos(n))) 6745 case cc.EqualityExpressionNeq: // EqualityExpression "!=" RelationalExpression 6746 panic(todo("", p.pos(n))) 6747 default: 6748 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 6749 } 6750 } 6751 6752 func (p *project) equalityExpressionPSelect(f *function, n *cc.EqualityExpression, t cc.Type, mode exprMode, flags flags) { 6753 switch n.Case { 6754 case cc.EqualityExpressionRel: // RelationalExpression 6755 p.relationalExpression(f, n.RelationalExpression, t, mode, flags) 6756 case cc.EqualityExpressionEq: // EqualityExpression "==" RelationalExpression 6757 panic(todo("", p.pos(n))) 6758 case cc.EqualityExpressionNeq: // EqualityExpression "!=" RelationalExpression 6759 panic(todo("", p.pos(n))) 6760 default: 6761 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 6762 } 6763 } 6764 6765 func (p *project) equalityExpressionLValue(f *function, n *cc.EqualityExpression, t cc.Type, mode exprMode, flags flags) { 6766 switch n.Case { 6767 case cc.EqualityExpressionRel: // RelationalExpression 6768 p.relationalExpression(f, n.RelationalExpression, t, mode, flags) 6769 case cc.EqualityExpressionEq: // EqualityExpression "==" RelationalExpression 6770 panic(todo("", p.pos(n))) 6771 case cc.EqualityExpressionNeq: // EqualityExpression "!=" RelationalExpression 6772 panic(todo("", p.pos(n))) 6773 default: 6774 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 6775 } 6776 } 6777 6778 func (p *project) equalityExpressionBool(f *function, n *cc.EqualityExpression, t cc.Type, mode exprMode, flags flags) { 6779 switch n.Case { 6780 case cc.EqualityExpressionRel: // RelationalExpression 6781 p.relationalExpression(f, n.RelationalExpression, t, mode, flags) 6782 case cc.EqualityExpressionEq: // EqualityExpression "==" RelationalExpression 6783 p.binaryEqualityExpression(f, n, " == ", t, mode, flags) 6784 case cc.EqualityExpressionNeq: // EqualityExpression "!=" RelationalExpression 6785 p.binaryEqualityExpression(f, n, " != ", t, mode, flags) 6786 default: 6787 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 6788 } 6789 } 6790 6791 func (p *project) equalityExpressionAddrOf(f *function, n *cc.EqualityExpression, t cc.Type, mode exprMode, flags flags) { 6792 switch n.Case { 6793 case cc.EqualityExpressionRel: // RelationalExpression 6794 p.relationalExpression(f, n.RelationalExpression, t, mode, flags) 6795 case cc.EqualityExpressionEq: // EqualityExpression "==" RelationalExpression 6796 panic(todo("", p.pos(n))) 6797 case cc.EqualityExpressionNeq: // EqualityExpression "!=" RelationalExpression 6798 panic(todo("", p.pos(n))) 6799 default: 6800 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 6801 } 6802 } 6803 6804 func (p *project) equalityExpressionVoid(f *function, n *cc.EqualityExpression, t cc.Type, mode exprMode, flags flags) { 6805 switch n.Case { 6806 case cc.EqualityExpressionRel: // RelationalExpression 6807 p.relationalExpression(f, n.RelationalExpression, t, mode, flags) 6808 default: 6809 // case cc.EqualityExpressionEq: // EqualityExpression "==" RelationalExpression 6810 // case cc.EqualityExpressionNeq: // EqualityExpression "!=" RelationalExpression 6811 p.w("_ = ") 6812 p.equalityExpression(f, n, n.Operand.Type(), exprValue, flags) 6813 } 6814 } 6815 6816 func (p *project) equalityExpressionValue(f *function, n *cc.EqualityExpression, t cc.Type, mode exprMode, flags flags) { 6817 switch n.Case { 6818 case cc.EqualityExpressionRel: // RelationalExpression 6819 p.relationalExpression(f, n.RelationalExpression, t, mode, flags) 6820 case cc.EqualityExpressionEq: // EqualityExpression "==" RelationalExpression 6821 p.binaryEqualityExpression(f, n, " == ", t, mode, flags) 6822 case cc.EqualityExpressionNeq: // EqualityExpression "!=" RelationalExpression 6823 p.binaryEqualityExpression(f, n, " != ", t, mode, flags) 6824 default: 6825 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 6826 } 6827 } 6828 6829 func (p *project) binaryEqualityExpression(f *function, n *cc.EqualityExpression, oper string, t cc.Type, mode exprMode, flags flags) { 6830 switch mode { 6831 case exprValue: 6832 p.binaryEqualityExpressionValue(f, n, oper, t, mode, flags) 6833 case exprBool: 6834 p.binaryEqualityExpressionBool(f, n, oper, t, mode, flags) 6835 default: 6836 panic(todo("", n.Position(), mode)) 6837 } 6838 } 6839 6840 func (p *project) binaryEqualityExpressionBool(f *function, n *cc.EqualityExpression, oper string, t cc.Type, mode exprMode, flags flags) { 6841 defer p.w("%s", p.booleanBinaryExpression(n, n.Operand, t, &mode, flags)) 6842 p.equalityExpression(f, n.EqualityExpression, n.Promote(), exprValue, flags) 6843 p.w(" %s%s", oper, tidyComment(" ", &n.Token)) 6844 p.relationalExpression(f, n.RelationalExpression, n.Promote(), exprValue, flags) 6845 } 6846 6847 func (p *project) binaryEqualityExpressionValue(f *function, n *cc.EqualityExpression, oper string, t cc.Type, mode exprMode, flags flags) { 6848 defer p.w("%s", p.booleanBinaryExpression(n, n.Operand, t, &mode, flags)) 6849 p.equalityExpression(f, n.EqualityExpression, n.Promote(), exprValue, flags) 6850 p.w(" %s%s", oper, tidyComment(" ", &n.Token)) 6851 p.relationalExpression(f, n.RelationalExpression, n.Promote(), exprValue, flags) 6852 } 6853 6854 func (p *project) relationalExpression(f *function, n *cc.RelationalExpression, t cc.Type, mode exprMode, flags flags) { 6855 switch mode { 6856 case exprValue: 6857 p.relationalExpressionValue(f, n, t, mode, flags) 6858 case exprVoid: 6859 p.relationalExpressionVoid(f, n, t, mode, flags) 6860 case exprAddrOf: 6861 p.relationalExpressionAddrOf(f, n, t, mode, flags) 6862 case exprBool: 6863 p.relationalExpressionBool(f, n, t, mode, flags) 6864 case exprLValue: 6865 p.relationalExpressionLValue(f, n, t, mode, flags) 6866 case exprPSelect: 6867 p.relationalExpressionPSelect(f, n, t, mode, flags) 6868 case exprFunc: 6869 p.relationalExpressionFunc(f, n, t, mode, flags) 6870 case exprSelect: 6871 p.relationalExpressionSelect(f, n, t, mode, flags) 6872 case exprDecay: 6873 p.relationalExpressionDecay(f, n, t, mode, flags) 6874 default: 6875 panic(todo("", n.Position(), mode)) 6876 } 6877 } 6878 6879 func (p *project) relationalExpressionDecay(f *function, n *cc.RelationalExpression, t cc.Type, mode exprMode, flags flags) { 6880 switch n.Case { 6881 case cc.RelationalExpressionShift: // ShiftExpression 6882 p.shiftExpression(f, n.ShiftExpression, t, mode, flags) 6883 case cc.RelationalExpressionLt: // RelationalExpression '<' ShiftExpression 6884 panic(todo("", p.pos(n))) 6885 case cc.RelationalExpressionGt: // RelationalExpression '>' ShiftExpression 6886 panic(todo("", p.pos(n))) 6887 case cc.RelationalExpressionLeq: // RelationalExpression "<=" ShiftExpression 6888 panic(todo("", p.pos(n))) 6889 case cc.RelationalExpressionGeq: // RelationalExpression ">=" ShiftExpression 6890 panic(todo("", p.pos(n))) 6891 default: 6892 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 6893 } 6894 } 6895 6896 func (p *project) relationalExpressionSelect(f *function, n *cc.RelationalExpression, t cc.Type, mode exprMode, flags flags) { 6897 switch n.Case { 6898 case cc.RelationalExpressionShift: // ShiftExpression 6899 p.shiftExpression(f, n.ShiftExpression, t, mode, flags) 6900 case cc.RelationalExpressionLt: // RelationalExpression '<' ShiftExpression 6901 panic(todo("", p.pos(n))) 6902 case cc.RelationalExpressionGt: // RelationalExpression '>' ShiftExpression 6903 panic(todo("", p.pos(n))) 6904 case cc.RelationalExpressionLeq: // RelationalExpression "<=" ShiftExpression 6905 panic(todo("", p.pos(n))) 6906 case cc.RelationalExpressionGeq: // RelationalExpression ">=" ShiftExpression 6907 panic(todo("", p.pos(n))) 6908 default: 6909 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 6910 } 6911 } 6912 6913 func (p *project) relationalExpressionFunc(f *function, n *cc.RelationalExpression, t cc.Type, mode exprMode, flags flags) { 6914 switch n.Case { 6915 case cc.RelationalExpressionShift: // ShiftExpression 6916 p.shiftExpression(f, n.ShiftExpression, t, mode, flags) 6917 case cc.RelationalExpressionLt: // RelationalExpression '<' ShiftExpression 6918 panic(todo("", p.pos(n))) 6919 case cc.RelationalExpressionGt: // RelationalExpression '>' ShiftExpression 6920 panic(todo("", p.pos(n))) 6921 case cc.RelationalExpressionLeq: // RelationalExpression "<=" ShiftExpression 6922 panic(todo("", p.pos(n))) 6923 case cc.RelationalExpressionGeq: // RelationalExpression ">=" ShiftExpression 6924 panic(todo("", p.pos(n))) 6925 default: 6926 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 6927 } 6928 } 6929 6930 func (p *project) relationalExpressionPSelect(f *function, n *cc.RelationalExpression, t cc.Type, mode exprMode, flags flags) { 6931 switch n.Case { 6932 case cc.RelationalExpressionShift: // ShiftExpression 6933 p.shiftExpression(f, n.ShiftExpression, t, mode, flags) 6934 case cc.RelationalExpressionLt: // RelationalExpression '<' ShiftExpression 6935 panic(todo("", p.pos(n))) 6936 case cc.RelationalExpressionGt: // RelationalExpression '>' ShiftExpression 6937 panic(todo("", p.pos(n))) 6938 case cc.RelationalExpressionLeq: // RelationalExpression "<=" ShiftExpression 6939 panic(todo("", p.pos(n))) 6940 case cc.RelationalExpressionGeq: // RelationalExpression ">=" ShiftExpression 6941 panic(todo("", p.pos(n))) 6942 default: 6943 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 6944 } 6945 } 6946 6947 func (p *project) relationalExpressionLValue(f *function, n *cc.RelationalExpression, t cc.Type, mode exprMode, flags flags) { 6948 switch n.Case { 6949 case cc.RelationalExpressionShift: // ShiftExpression 6950 p.shiftExpression(f, n.ShiftExpression, t, mode, flags) 6951 case cc.RelationalExpressionLt: // RelationalExpression '<' ShiftExpression 6952 panic(todo("", p.pos(n))) 6953 case cc.RelationalExpressionGt: // RelationalExpression '>' ShiftExpression 6954 panic(todo("", p.pos(n))) 6955 case cc.RelationalExpressionLeq: // RelationalExpression "<=" ShiftExpression 6956 panic(todo("", p.pos(n))) 6957 case cc.RelationalExpressionGeq: // RelationalExpression ">=" ShiftExpression 6958 panic(todo("", p.pos(n))) 6959 default: 6960 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 6961 } 6962 } 6963 6964 func (p *project) relationalExpressionBool(f *function, n *cc.RelationalExpression, t cc.Type, mode exprMode, flags flags) { 6965 switch n.Case { 6966 case cc.RelationalExpressionShift: // ShiftExpression 6967 p.shiftExpression(f, n.ShiftExpression, t, mode, flags) 6968 case cc.RelationalExpressionLt: // RelationalExpression '<' ShiftExpression 6969 p.binaryRelationalExpression(f, n, " < ", t, mode, flags) 6970 case cc.RelationalExpressionGt: // RelationalExpression '>' ShiftExpression 6971 p.binaryRelationalExpression(f, n, " > ", t, mode, flags) 6972 case cc.RelationalExpressionLeq: // RelationalExpression "<=" ShiftExpression 6973 p.binaryRelationalExpression(f, n, " <= ", t, mode, flags) 6974 case cc.RelationalExpressionGeq: // RelationalExpression ">=" ShiftExpression 6975 p.binaryRelationalExpression(f, n, " >= ", t, mode, flags) 6976 default: 6977 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 6978 } 6979 } 6980 6981 func (p *project) relationalExpressionAddrOf(f *function, n *cc.RelationalExpression, t cc.Type, mode exprMode, flags flags) { 6982 switch n.Case { 6983 case cc.RelationalExpressionShift: // ShiftExpression 6984 p.shiftExpression(f, n.ShiftExpression, t, mode, flags) 6985 case cc.RelationalExpressionLt: // RelationalExpression '<' ShiftExpression 6986 panic(todo("", p.pos(n))) 6987 case cc.RelationalExpressionGt: // RelationalExpression '>' ShiftExpression 6988 panic(todo("", p.pos(n))) 6989 case cc.RelationalExpressionLeq: // RelationalExpression "<=" ShiftExpression 6990 panic(todo("", p.pos(n))) 6991 case cc.RelationalExpressionGeq: // RelationalExpression ">=" ShiftExpression 6992 panic(todo("", p.pos(n))) 6993 default: 6994 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 6995 } 6996 } 6997 6998 func (p *project) relationalExpressionVoid(f *function, n *cc.RelationalExpression, t cc.Type, mode exprMode, flags flags) { 6999 switch n.Case { 7000 case cc.RelationalExpressionShift: // ShiftExpression 7001 p.shiftExpression(f, n.ShiftExpression, t, mode, flags) 7002 default: 7003 // case cc.RelationalExpressionLt: // RelationalExpression '<' ShiftExpression 7004 // case cc.RelationalExpressionGt: // RelationalExpression '>' ShiftExpression 7005 // case cc.RelationalExpressionLeq: // RelationalExpression "<=" ShiftExpression 7006 // case cc.RelationalExpressionGeq: // RelationalExpression ">=" ShiftExpression 7007 p.w("_ = ") 7008 p.relationalExpression(f, n, n.Operand.Type(), exprValue, flags) 7009 } 7010 } 7011 7012 func (p *project) relationalExpressionValue(f *function, n *cc.RelationalExpression, t cc.Type, mode exprMode, flags flags) { 7013 switch n.Case { 7014 case cc.RelationalExpressionShift: // ShiftExpression 7015 p.shiftExpression(f, n.ShiftExpression, t, mode, flags) 7016 case cc.RelationalExpressionLt: // RelationalExpression '<' ShiftExpression 7017 p.binaryRelationalExpression(f, n, " < ", t, mode, flags) 7018 case cc.RelationalExpressionGt: // RelationalExpression '>' ShiftExpression 7019 p.binaryRelationalExpression(f, n, " > ", t, mode, flags) 7020 case cc.RelationalExpressionLeq: // RelationalExpression "<=" ShiftExpression 7021 p.binaryRelationalExpression(f, n, " <= ", t, mode, flags) 7022 case cc.RelationalExpressionGeq: // RelationalExpression ">=" ShiftExpression 7023 p.binaryRelationalExpression(f, n, " >= ", t, mode, flags) 7024 default: 7025 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 7026 } 7027 } 7028 7029 func (p *project) binaryRelationalExpression(f *function, n *cc.RelationalExpression, oper string, t cc.Type, mode exprMode, flags flags) { 7030 // RelationalExpression "<=" ShiftExpression 7031 lt := n.RelationalExpression.Operand.Type() 7032 rt := n.ShiftExpression.Operand.Type() 7033 switch lk, rk := lt.Kind(), rt.Kind(); { 7034 case 7035 lk == cc.UInt128 || rk == cc.UInt128, 7036 lk == cc.Int128 || rk == cc.Int128: 7037 7038 p.binaryRelationalExpressionInt128(f, n, oper, t, mode, flags) 7039 return 7040 } 7041 7042 defer p.w("%s", p.booleanBinaryExpression(n, n.Operand, t, &mode, flags)) 7043 p.relationalExpression(f, n.RelationalExpression, n.Promote(), exprValue, flags) 7044 p.w(" %s%s", oper, tidyComment(" ", &n.Token)) 7045 p.shiftExpression(f, n.ShiftExpression, n.Promote(), exprValue, flags) 7046 } 7047 7048 func (p *project) binaryRelationalExpressionInt128(f *function, n *cc.RelationalExpression, oper string, t cc.Type, mode exprMode, flags flags) { 7049 // RelationalExpression "<=" ShiftExpression 7050 defer p.w("%s", p.booleanBinaryExpression(n, n.Operand, t, &mode, flags)) 7051 p.relationalExpression(f, n.RelationalExpression, n.Promote(), exprValue, flags) 7052 p.w(".Cmp(") 7053 p.shiftExpression(f, n.ShiftExpression, n.Promote(), exprValue, flags) 7054 p.w(") %s 0", oper) 7055 } 7056 7057 func (p *project) shiftExpression(f *function, n *cc.ShiftExpression, t cc.Type, mode exprMode, flags flags) { 7058 switch mode { 7059 case exprValue: 7060 p.shiftExpressionValue(f, n, t, mode, flags) 7061 case exprVoid: 7062 p.shiftExpressionVoid(f, n, t, mode, flags) 7063 case exprAddrOf: 7064 p.shiftExpressionAddrOf(f, n, t, mode, flags) 7065 case exprBool: 7066 p.shiftExpressionBool(f, n, t, mode, flags) 7067 case exprLValue: 7068 p.shiftExpressionLValue(f, n, t, mode, flags) 7069 case exprPSelect: 7070 p.shiftExpressionPSelect(f, n, t, mode, flags) 7071 case exprFunc: 7072 p.shiftExpressionFunc(f, n, t, mode, flags) 7073 case exprSelect: 7074 p.shiftExpressionSelect(f, n, t, mode, flags) 7075 case exprDecay: 7076 p.shiftExpressionDecay(f, n, t, mode, flags) 7077 default: 7078 panic(todo("", n.Position(), mode)) 7079 } 7080 } 7081 7082 func (p *project) shiftExpressionDecay(f *function, n *cc.ShiftExpression, t cc.Type, mode exprMode, flags flags) { 7083 switch n.Case { 7084 case cc.ShiftExpressionAdd: // AdditiveExpression 7085 p.additiveExpression(f, n.AdditiveExpression, t, mode, flags) 7086 case cc.ShiftExpressionLsh: // ShiftExpression "<<" AdditiveExpression 7087 panic(todo("", p.pos(n))) 7088 case cc.ShiftExpressionRsh: // ShiftExpression ">>" AdditiveExpression 7089 panic(todo("", p.pos(n))) 7090 default: 7091 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 7092 } 7093 } 7094 7095 func (p *project) shiftExpressionSelect(f *function, n *cc.ShiftExpression, t cc.Type, mode exprMode, flags flags) { 7096 switch n.Case { 7097 case cc.ShiftExpressionAdd: // AdditiveExpression 7098 p.additiveExpression(f, n.AdditiveExpression, t, mode, flags) 7099 case cc.ShiftExpressionLsh: // ShiftExpression "<<" AdditiveExpression 7100 panic(todo("", p.pos(n))) 7101 case cc.ShiftExpressionRsh: // ShiftExpression ">>" AdditiveExpression 7102 panic(todo("", p.pos(n))) 7103 default: 7104 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 7105 } 7106 } 7107 7108 func (p *project) shiftExpressionFunc(f *function, n *cc.ShiftExpression, t cc.Type, mode exprMode, flags flags) { 7109 switch n.Case { 7110 case cc.ShiftExpressionAdd: // AdditiveExpression 7111 p.additiveExpression(f, n.AdditiveExpression, t, mode, flags) 7112 case cc.ShiftExpressionLsh: // ShiftExpression "<<" AdditiveExpression 7113 panic(todo("", p.pos(n))) 7114 case cc.ShiftExpressionRsh: // ShiftExpression ">>" AdditiveExpression 7115 panic(todo("", p.pos(n))) 7116 default: 7117 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 7118 } 7119 } 7120 7121 func (p *project) shiftExpressionPSelect(f *function, n *cc.ShiftExpression, t cc.Type, mode exprMode, flags flags) { 7122 switch n.Case { 7123 case cc.ShiftExpressionAdd: // AdditiveExpression 7124 p.additiveExpression(f, n.AdditiveExpression, t, mode, flags) 7125 case cc.ShiftExpressionLsh: // ShiftExpression "<<" AdditiveExpression 7126 panic(todo("", p.pos(n))) 7127 case cc.ShiftExpressionRsh: // ShiftExpression ">>" AdditiveExpression 7128 panic(todo("", p.pos(n))) 7129 default: 7130 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 7131 } 7132 } 7133 7134 func (p *project) shiftExpressionLValue(f *function, n *cc.ShiftExpression, t cc.Type, mode exprMode, flags flags) { 7135 switch n.Case { 7136 case cc.ShiftExpressionAdd: // AdditiveExpression 7137 p.additiveExpression(f, n.AdditiveExpression, t, mode, flags) 7138 case cc.ShiftExpressionLsh: // ShiftExpression "<<" AdditiveExpression 7139 panic(todo("", p.pos(n))) 7140 case cc.ShiftExpressionRsh: // ShiftExpression ">>" AdditiveExpression 7141 panic(todo("", p.pos(n))) 7142 default: 7143 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 7144 } 7145 } 7146 7147 func (p *project) shiftExpressionBool(f *function, n *cc.ShiftExpression, t cc.Type, mode exprMode, flags flags) { 7148 switch n.Case { 7149 case cc.ShiftExpressionAdd: // AdditiveExpression 7150 p.additiveExpression(f, n.AdditiveExpression, t, mode, flags) 7151 case cc.ShiftExpressionLsh: // ShiftExpression "<<" AdditiveExpression 7152 p.binaryShiftExpression(f, n, "<<", t, mode, flags) 7153 case cc.ShiftExpressionRsh: // ShiftExpression ">>" AdditiveExpression 7154 p.binaryShiftExpression(f, n, ">>", t, mode, flags) 7155 default: 7156 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 7157 } 7158 } 7159 7160 func (p *project) shiftExpressionAddrOf(f *function, n *cc.ShiftExpression, t cc.Type, mode exprMode, flags flags) { 7161 switch n.Case { 7162 case cc.ShiftExpressionAdd: // AdditiveExpression 7163 p.additiveExpression(f, n.AdditiveExpression, t, mode, flags) 7164 case cc.ShiftExpressionLsh: // ShiftExpression "<<" AdditiveExpression 7165 panic(todo("", p.pos(n))) 7166 case cc.ShiftExpressionRsh: // ShiftExpression ">>" AdditiveExpression 7167 panic(todo("", p.pos(n))) 7168 default: 7169 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 7170 } 7171 } 7172 7173 func (p *project) shiftExpressionVoid(f *function, n *cc.ShiftExpression, t cc.Type, mode exprMode, flags flags) { 7174 switch n.Case { 7175 case cc.ShiftExpressionAdd: // AdditiveExpression 7176 p.additiveExpression(f, n.AdditiveExpression, t, mode, flags) 7177 case cc.ShiftExpressionLsh: // ShiftExpression "<<" AdditiveExpression 7178 panic(todo("", p.pos(n))) 7179 case cc.ShiftExpressionRsh: // ShiftExpression ">>" AdditiveExpression 7180 panic(todo("", p.pos(n))) 7181 default: 7182 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 7183 } 7184 } 7185 7186 func (p *project) shiftExpressionValue(f *function, n *cc.ShiftExpression, t cc.Type, mode exprMode, flags flags) { 7187 switch n.Case { 7188 case cc.ShiftExpressionAdd: // AdditiveExpression 7189 p.additiveExpression(f, n.AdditiveExpression, t, mode, flags) 7190 case cc.ShiftExpressionLsh: // ShiftExpression "<<" AdditiveExpression 7191 p.binaryShiftExpression(f, n, "<<", t, mode, flags) 7192 case cc.ShiftExpressionRsh: // ShiftExpression ">>" AdditiveExpression 7193 p.binaryShiftExpression(f, n, ">>", t, mode, flags) 7194 default: 7195 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 7196 } 7197 } 7198 7199 func (p *project) binaryShiftExpression(f *function, n *cc.ShiftExpression, oper string, t cc.Type, mode exprMode, flags flags) { 7200 // ShiftExpression "<<" AdditiveExpression 7201 switch mode { 7202 case exprValue: 7203 p.binaryShiftExpressionValue(f, n, oper, t, mode, flags) 7204 case exprBool: 7205 p.binaryShiftExpressionBool(f, n, oper, t, mode, flags) 7206 default: 7207 panic(todo("", n.Position(), mode)) 7208 } 7209 } 7210 7211 func (p *project) todo(n cc.Node, t cc.Type) { 7212 p.w("func() %s { panic(`%v: TODO (%v)`)}()", p.typ(n, t), n.Position(), origin(2)) 7213 } 7214 7215 func (p *project) binaryShiftExpressionBool(f *function, n *cc.ShiftExpression, oper string, t cc.Type, mode exprMode, flags flags) { 7216 defer p.w("%s", p.artithmeticBinaryExpression(n, n.Operand, n.Operand.Type(), &mode, flags)) 7217 switch { 7218 case n.ShiftExpression.Operand.Type().IsBitFieldType(): 7219 p.w("(") 7220 p.shiftExpression(f, n.ShiftExpression, n.Operand.Type(), exprValue, flags) 7221 p.w(" %s%s", oper, tidyComment(" ", &n.Token)) 7222 p.additiveExpression(f, n.AdditiveExpression, n.Promote(), exprValue, flags) 7223 p.w(")&%#x", bfValueMask(n.ShiftExpression.Operand.Type().BitField())) 7224 case shiftOverflows(n, n.ShiftExpression.Operand, n.AdditiveExpression.Operand, oper, n.Operand.Type()): 7225 p.shiftExpression(f, n.ShiftExpression, n.Operand.Type(), exprValue, flags|fForceRuntimeConv) 7226 p.w(" %s%s", oper, tidyComment(" ", &n.Token)) 7227 p.additiveExpression(f, n.AdditiveExpression, n.Promote(), exprValue, flags) 7228 case isConstInteger(n.ShiftExpression.Operand): 7229 s := p.convertNil(n, n.Operand.Type(), 0) 7230 p.shiftExpression(f, n.ShiftExpression, n.Operand.Type(), exprValue, flags) 7231 p.w("%s %s%s", s, oper, tidyComment(" ", &n.Token)) 7232 p.additiveExpression(f, n.AdditiveExpression, n.Promote(), exprValue, flags) 7233 default: 7234 p.shiftExpression(f, n.ShiftExpression, n.Operand.Type(), exprValue, flags) 7235 p.w(" %s%s", oper, tidyComment(" ", &n.Token)) 7236 p.additiveExpression(f, n.AdditiveExpression, n.Promote(), exprValue, flags) 7237 } 7238 } 7239 7240 func shiftOp(s string) string { 7241 switch s { 7242 case "<<": 7243 return "Shl" 7244 case ">>": 7245 return "Shr" 7246 default: 7247 panic(todo("%q", s)) 7248 } 7249 } 7250 7251 func bfValueMask(bf cc.Field) uint64 { 7252 return uint64(1)<<bf.BitFieldWidth() - 1 7253 } 7254 7255 func (p *project) binaryShiftExpressionValue(f *function, n *cc.ShiftExpression, oper string, t cc.Type, mode exprMode, flags flags) { 7256 // ShiftExpression "<<" AdditiveExpression 7257 defer p.w("%s", p.artithmeticBinaryExpression(n, n.Operand, t, &mode, flags)) 7258 switch k := n.ShiftExpression.Operand.Type().Kind(); { 7259 case k == cc.Int128, k == cc.UInt128: 7260 p.w("(") 7261 p.shiftExpression(f, n.ShiftExpression, n.Operand.Type(), exprValue, flags) 7262 p.w(").%s(", shiftOp(oper)) 7263 p.additiveExpression(f, n.AdditiveExpression, p.intType, exprValue, flags) 7264 p.w(")") 7265 case n.ShiftExpression.Operand.Type().IsBitFieldType(): 7266 p.w("(") 7267 p.shiftExpression(f, n.ShiftExpression, n.Operand.Type(), exprValue, flags) 7268 p.w(" %s%s", oper, tidyComment(" ", &n.Token)) 7269 p.additiveExpression(f, n.AdditiveExpression, n.Promote(), exprValue, flags) 7270 p.w(")&%#x", bfValueMask(n.ShiftExpression.Operand.Type().BitField())) 7271 case shiftOverflows(n, n.ShiftExpression.Operand, n.AdditiveExpression.Operand, oper, n.Operand.Type()): 7272 p.shiftExpression(f, n.ShiftExpression, n.Operand.Type(), exprValue, flags|fForceRuntimeConv) 7273 p.w(" %s%s", oper, tidyComment(" ", &n.Token)) 7274 p.additiveExpression(f, n.AdditiveExpression, n.Promote(), exprValue, flags) 7275 case isConstInteger(n.ShiftExpression.Operand): 7276 s := p.convertNil(n, n.Operand.Type(), 0) 7277 p.shiftExpression(f, n.ShiftExpression, n.Operand.Type(), exprValue, flags) 7278 p.w("%s %s%s", s, oper, tidyComment(" ", &n.Token)) 7279 p.additiveExpression(f, n.AdditiveExpression, n.Promote(), exprValue, flags) 7280 default: 7281 p.shiftExpression(f, n.ShiftExpression, n.Operand.Type(), exprValue, flags) 7282 p.w(" %s%s", oper, tidyComment(" ", &n.Token)) 7283 p.additiveExpression(f, n.AdditiveExpression, n.Promote(), exprValue, flags) 7284 } 7285 } 7286 7287 func shiftOverflows(n cc.Node, lo, ro cc.Operand, oper string, result cc.Type) bool { 7288 a, b, ok := getIntOperands(lo, ro) 7289 if !ok { 7290 return false 7291 } 7292 7293 if !b.IsUint64() { 7294 return true 7295 } 7296 7297 bits := b.Uint64() 7298 if bits > mathutil.MaxUint { 7299 return true 7300 } 7301 7302 switch oper { 7303 case "<<": 7304 return overflows(a.Lsh(a, uint(bits)), result) 7305 case ">>": 7306 return overflows(a.Rsh(a, uint(bits)), result) 7307 default: 7308 panic(todo("", pos(n))) 7309 } 7310 } 7311 7312 func (p *project) additiveExpression(f *function, n *cc.AdditiveExpression, t cc.Type, mode exprMode, flags flags) { 7313 switch mode { 7314 case exprValue: 7315 p.additiveExpressionValue(f, n, t, mode, flags) 7316 case exprVoid: 7317 p.additiveExpressionVoid(f, n, t, mode, flags) 7318 case exprAddrOf: 7319 p.additiveExpressionAddrOf(f, n, t, mode, flags) 7320 case exprBool: 7321 p.additiveExpressionBool(f, n, t, mode, flags) 7322 case exprLValue: 7323 p.additiveExpressionLValue(f, n, t, mode, flags) 7324 case exprPSelect: 7325 p.additiveExpressionPSelect(f, n, t, mode, flags) 7326 case exprFunc: 7327 p.additiveExpressionFunc(f, n, t, mode, flags) 7328 case exprSelect: 7329 p.additiveExpressionSelect(f, n, t, mode, flags) 7330 case exprDecay: 7331 p.additiveExpressionDecay(f, n, t, mode, flags) 7332 default: 7333 panic(todo("", n.Position(), mode)) 7334 } 7335 } 7336 7337 func (p *project) additiveExpressionDecay(f *function, n *cc.AdditiveExpression, t cc.Type, mode exprMode, flags flags) { 7338 switch n.Case { 7339 case cc.AdditiveExpressionMul: // MultiplicativeExpression 7340 p.multiplicativeExpression(f, n.MultiplicativeExpression, t, mode, flags) 7341 case cc.AdditiveExpressionAdd: // AdditiveExpression '+' MultiplicativeExpression 7342 panic(todo("", p.pos(n))) 7343 case cc.AdditiveExpressionSub: // AdditiveExpression '-' MultiplicativeExpression 7344 panic(todo("", p.pos(n))) 7345 default: 7346 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 7347 } 7348 } 7349 7350 func (p *project) additiveExpressionSelect(f *function, n *cc.AdditiveExpression, t cc.Type, mode exprMode, flags flags) { 7351 switch n.Case { 7352 case cc.AdditiveExpressionMul: // MultiplicativeExpression 7353 p.multiplicativeExpression(f, n.MultiplicativeExpression, t, mode, flags) 7354 case cc.AdditiveExpressionAdd: // AdditiveExpression '+' MultiplicativeExpression 7355 panic(todo("", p.pos(n))) 7356 case cc.AdditiveExpressionSub: // AdditiveExpression '-' MultiplicativeExpression 7357 panic(todo("", p.pos(n))) 7358 default: 7359 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 7360 } 7361 } 7362 7363 func (p *project) additiveExpressionFunc(f *function, n *cc.AdditiveExpression, t cc.Type, mode exprMode, flags flags) { 7364 switch n.Case { 7365 case cc.AdditiveExpressionMul: // MultiplicativeExpression 7366 p.multiplicativeExpression(f, n.MultiplicativeExpression, t, mode, flags) 7367 case cc.AdditiveExpressionAdd: // AdditiveExpression '+' MultiplicativeExpression 7368 panic(todo("", p.pos(n))) 7369 case cc.AdditiveExpressionSub: // AdditiveExpression '-' MultiplicativeExpression 7370 panic(todo("", p.pos(n))) 7371 default: 7372 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 7373 } 7374 } 7375 7376 func (p *project) additiveExpressionPSelect(f *function, n *cc.AdditiveExpression, t cc.Type, mode exprMode, flags flags) { 7377 switch n.Case { 7378 case cc.AdditiveExpressionMul: // MultiplicativeExpression 7379 p.multiplicativeExpression(f, n.MultiplicativeExpression, t, mode, flags) 7380 case cc.AdditiveExpressionAdd: // AdditiveExpression '+' MultiplicativeExpression 7381 p.w("(*%s)(unsafe.Pointer(", p.typ(n, t.Elem())) 7382 p.additiveExpression(f, n, t, exprValue, flags) 7383 p.w("))") 7384 case cc.AdditiveExpressionSub: // AdditiveExpression '-' MultiplicativeExpression 7385 p.w("(*%s)(unsafe.Pointer(", p.typ(n, t.Elem())) 7386 p.additiveExpression(f, n, t, exprValue, flags) 7387 7388 default: 7389 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 7390 } 7391 } 7392 7393 func (p *project) additiveExpressionLValue(f *function, n *cc.AdditiveExpression, t cc.Type, mode exprMode, flags flags) { 7394 switch n.Case { 7395 case cc.AdditiveExpressionMul: // MultiplicativeExpression 7396 p.multiplicativeExpression(f, n.MultiplicativeExpression, t, mode, flags) 7397 case cc.AdditiveExpressionAdd: // AdditiveExpression '+' MultiplicativeExpression 7398 panic(todo("", p.pos(n))) 7399 case cc.AdditiveExpressionSub: // AdditiveExpression '-' MultiplicativeExpression 7400 panic(todo("", p.pos(n))) 7401 default: 7402 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 7403 } 7404 } 7405 7406 func (p *project) additiveExpressionBool(f *function, n *cc.AdditiveExpression, t cc.Type, mode exprMode, flags flags) { 7407 switch n.Case { 7408 case cc.AdditiveExpressionMul: // MultiplicativeExpression 7409 p.multiplicativeExpression(f, n.MultiplicativeExpression, t, mode, flags) 7410 case cc.AdditiveExpressionAdd: // AdditiveExpression '+' MultiplicativeExpression 7411 p.binaryAdditiveExpression(f, n, "+", t, mode, flags) 7412 case cc.AdditiveExpressionSub: // AdditiveExpression '-' MultiplicativeExpression 7413 p.binaryAdditiveExpression(f, n, "-", t, mode, flags) 7414 default: 7415 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 7416 } 7417 } 7418 7419 func (p *project) additiveExpressionAddrOf(f *function, n *cc.AdditiveExpression, t cc.Type, mode exprMode, flags flags) { 7420 switch n.Case { 7421 case cc.AdditiveExpressionMul: // MultiplicativeExpression 7422 p.multiplicativeExpression(f, n.MultiplicativeExpression, t, mode, flags) 7423 case cc.AdditiveExpressionAdd: // AdditiveExpression '+' MultiplicativeExpression 7424 panic(todo("", p.pos(n))) 7425 case cc.AdditiveExpressionSub: // AdditiveExpression '-' MultiplicativeExpression 7426 panic(todo("", p.pos(n))) 7427 default: 7428 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 7429 } 7430 } 7431 7432 func (p *project) additiveExpressionVoid(f *function, n *cc.AdditiveExpression, t cc.Type, mode exprMode, flags flags) { 7433 switch n.Case { 7434 case cc.AdditiveExpressionMul: // MultiplicativeExpression 7435 p.multiplicativeExpression(f, n.MultiplicativeExpression, t, mode, flags) 7436 case 7437 cc.AdditiveExpressionAdd, // AdditiveExpression '+' MultiplicativeExpression 7438 cc.AdditiveExpressionSub: // AdditiveExpression '-' MultiplicativeExpression 7439 7440 p.w("_ = ") 7441 p.additiveExpression(f, n, n.Operand.Type(), exprValue, flags) 7442 default: 7443 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 7444 } 7445 } 7446 7447 func (p *project) additiveExpressionValue(f *function, n *cc.AdditiveExpression, t cc.Type, mode exprMode, flags flags) { 7448 switch n.Case { 7449 case cc.AdditiveExpressionMul: // MultiplicativeExpression 7450 p.multiplicativeExpression(f, n.MultiplicativeExpression, t, mode, flags) 7451 case cc.AdditiveExpressionAdd: // AdditiveExpression '+' MultiplicativeExpression 7452 p.binaryAdditiveExpression(f, n, "+", t, mode, flags) 7453 case cc.AdditiveExpressionSub: // AdditiveExpression '-' MultiplicativeExpression 7454 p.binaryAdditiveExpression(f, n, "-", t, mode, flags) 7455 default: 7456 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 7457 } 7458 } 7459 7460 func (p *project) binaryAdditiveExpression(f *function, n *cc.AdditiveExpression, oper string, t cc.Type, mode exprMode, flags flags) { 7461 // AdditiveExpression '+' MultiplicativeExpression 7462 switch mode { 7463 case exprValue: 7464 p.binaryAdditiveExpressionValue(f, n, oper, t, mode, flags) 7465 case exprBool: 7466 p.binaryAdditiveExpressionBool(f, n, oper, t, mode, flags) 7467 default: 7468 panic(todo("", mode)) 7469 } 7470 } 7471 7472 func (p *project) binaryAdditiveExpressionBool(f *function, n *cc.AdditiveExpression, oper string, t cc.Type, mode exprMode, flags flags) { 7473 // AdditiveExpression '+' MultiplicativeExpression 7474 defer p.w("%s", p.artithmeticBinaryExpression(n, n.Operand, n.Operand.Type(), &mode, flags)) 7475 lo := n.AdditiveExpression.Operand 7476 ro := n.MultiplicativeExpression.Operand 7477 lt := lo.Type() 7478 rt := ro.Type() 7479 switch { 7480 case lt.Kind() == cc.Ptr && rt.Kind() == cc.Ptr && oper == "-": 7481 p.additiveExpression(f, n.AdditiveExpression, n.Promote(), exprValue, flags) 7482 p.w(" %s%s", oper, tidyComment(" ", &n.Token)) 7483 p.multiplicativeExpression(f, n.MultiplicativeExpression, n.Promote(), exprValue, flags) 7484 case lt.IsArithmeticType() && rt.IsArithmeticType(): // x +- y 7485 defer p.w("%s", p.bitFieldPatch2(n, lo, ro, n.Promote())) //TODO bit field big endian 7486 switch { 7487 case intAddOverflows(n, lo, ro, oper, n.Promote()): // i +- j 7488 p.additiveExpression(f, n.AdditiveExpression, n.Promote(), exprValue, flags) 7489 p.w(" %s%s", oper, tidyComment(" ", &n.Token)) 7490 p.multiplicativeExpression(f, n.MultiplicativeExpression, n.Promote(), exprValue, flags|fForceRuntimeConv) 7491 default: 7492 var s string 7493 if isRealType(n.Operand) && n.Operand.Value() != nil { 7494 s = p.convertNil(n, n.Promote(), flags) 7495 } 7496 p.additiveExpression(f, n.AdditiveExpression, n.Promote(), exprValue, flags) 7497 p.w("%s %s%s", s, oper, tidyComment(" ", &n.Token)) 7498 p.multiplicativeExpression(f, n.MultiplicativeExpression, n.Promote(), exprValue, flags) 7499 } 7500 default: 7501 panic(todo("", n.Position(), lt, rt, oper)) 7502 } 7503 } 7504 7505 func (p *project) binaryAdditiveExpressionValue(f *function, n *cc.AdditiveExpression, oper string, t cc.Type, mode exprMode, flags flags) { 7506 // AdditiveExpression '+' MultiplicativeExpression 7507 7508 lt := n.AdditiveExpression.Operand.Type() 7509 rt := n.MultiplicativeExpression.Operand.Type() 7510 switch lk, rk := lt.Kind(), rt.Kind(); { 7511 case 7512 lk == cc.UInt128 || rk == cc.UInt128, 7513 lk == cc.Int128 || rk == cc.Int128: 7514 7515 p.binaryAdditiveExpressionUint128(f, n, oper, t, mode, flags) 7516 return 7517 } 7518 7519 defer p.w("%s", p.artithmeticBinaryExpression(n, n.Operand, t, &mode, flags)) 7520 lo := n.AdditiveExpression.Operand 7521 ro := n.MultiplicativeExpression.Operand 7522 switch { 7523 case lt.IsArithmeticType() && rt.IsArithmeticType(): // x +- y 7524 defer p.w("%s", p.bitFieldPatch2(n, lo, ro, n.Promote())) //TODO bit field big endian 7525 switch { 7526 case intAddOverflows(n, lo, ro, oper, n.Promote()): // i +- j 7527 p.additiveExpression(f, n.AdditiveExpression, n.Promote(), exprValue, flags) 7528 p.w(" %s%s", oper, tidyComment(" ", &n.Token)) 7529 p.multiplicativeExpression(f, n.MultiplicativeExpression, n.Promote(), exprValue, flags|fForceRuntimeConv) 7530 default: 7531 var s string 7532 if isRealType(n.Operand) && n.Operand.Value() != nil { 7533 s = p.convertNil(n, n.Promote(), flags) 7534 } 7535 p.additiveExpression(f, n.AdditiveExpression, n.Promote(), exprValue, flags) 7536 p.w("%s %s%s", s, oper, tidyComment(" ", &n.Token)) 7537 p.multiplicativeExpression(f, n.MultiplicativeExpression, n.Promote(), exprValue, flags) 7538 } 7539 case lt.Kind() == cc.Ptr && rt.IsIntegerType(): // p +- i 7540 p.additiveExpression(f, n.AdditiveExpression, lt, exprValue, flags) 7541 p.w(" %s%s uintptr(", oper, tidyComment(" ", &n.Token)) 7542 p.multiplicativeExpression(f, n.MultiplicativeExpression, rt, exprValue, flags) 7543 p.w(")") 7544 if sz := lt.Elem().Size(); sz != 1 { 7545 p.w("*%d", sz) 7546 } 7547 case lt.Kind() == cc.Array && rt.IsIntegerType(): // p +- i 7548 p.additiveExpression(f, n.AdditiveExpression, lt, exprDecay, flags) 7549 p.w(" %s%s uintptr(", oper, tidyComment(" ", &n.Token)) 7550 p.multiplicativeExpression(f, n.MultiplicativeExpression, rt, exprValue, flags) 7551 p.w(")") 7552 if sz := lt.Elem().Size(); sz != 1 { 7553 p.w("*%d", sz) 7554 } 7555 case lt.IsIntegerType() && rt.Kind() == cc.Ptr: // i +- p 7556 p.w("uintptr(") 7557 p.additiveExpression(f, n.AdditiveExpression, lt, exprValue, flags) 7558 p.w(")") 7559 if sz := rt.Elem().Size(); sz != 1 { 7560 p.w("*%d", sz) 7561 } 7562 p.w(" %s%s ", oper, tidyComment(" ", &n.Token)) 7563 p.multiplicativeExpression(f, n.MultiplicativeExpression, rt, exprValue, flags) 7564 case lt.IsIntegerType() && rt.Kind() == cc.Array: // i +- p 7565 panic(todo("", p.pos(n))) 7566 case lt.Kind() == cc.Ptr && rt.Kind() == cc.Ptr && oper == "-": // p - q 7567 p.w("(") 7568 p.additiveExpression(f, n.AdditiveExpression, n.Operand.Type(), exprValue, flags) 7569 p.w(" %s%s", oper, tidyComment(" ", &n.Token)) 7570 p.multiplicativeExpression(f, n.MultiplicativeExpression, n.Operand.Type(), exprValue, flags) 7571 p.w(")/%d", lt.Elem().Size()) 7572 case lt.Kind() == cc.Ptr && rt.Kind() == cc.Array && oper == "-": // p - q 7573 defer p.w("%s", p.convertType(n, nil, n.Operand.Type(), 0)) 7574 p.w("(") 7575 p.additiveExpression(f, n.AdditiveExpression, lt, exprValue, flags) 7576 p.w(" %s%s", oper, tidyComment(" ", &n.Token)) 7577 p.multiplicativeExpression(f, n.MultiplicativeExpression, rt.Decay(), exprDecay, flags) 7578 p.w(")/%d", lt.Elem().Size()) 7579 case lt.Kind() == cc.Array && rt.Kind() == cc.Ptr && oper == "-": // p - q 7580 panic(todo("", p.pos(n))) 7581 case lt.Kind() == cc.Array && rt.Kind() == cc.Array && oper == "-": // p - q 7582 panic(todo("", p.pos(n))) 7583 default: 7584 panic(todo("", n.Position(), lt, rt, oper)) 7585 } 7586 } 7587 7588 func (p *project) binaryAdditiveExpressionUint128(f *function, n *cc.AdditiveExpression, oper string, t cc.Type, mode exprMode, flags flags) { 7589 // AdditiveExpression '+' MultiplicativeExpression 7590 defer p.w("%s", p.artithmeticBinaryExpression(n, n.Operand, t, &mode, flags)) 7591 p.additiveExpression(f, n.AdditiveExpression, n.Promote(), exprValue, flags) 7592 switch oper { 7593 case "+": 7594 p.w(".Add(") 7595 case "-": 7596 p.w(".Sub(") 7597 default: 7598 panic(todo("%q", oper)) 7599 } 7600 p.multiplicativeExpression(f, n.MultiplicativeExpression, n.Promote(), exprValue, flags) 7601 p.w(")") 7602 } 7603 7604 func (p *project) bitFieldPatch2(n cc.Node, a, b cc.Operand, promote cc.Type) string { 7605 //TODO bit field big endian 7606 var m uint64 7607 var w int 7608 switch { 7609 case a.Type().IsBitFieldType(): 7610 bf := a.Type().BitField() 7611 w = bf.BitFieldWidth() 7612 m = bf.Mask() >> bf.BitFieldOffset() 7613 if b.Type().IsBitFieldType() { 7614 bf = b.Type().BitField() 7615 w2 := bf.BitFieldWidth() 7616 if w2 != w { 7617 panic(todo("", p.pos(n))) 7618 } 7619 } 7620 case b.Type().IsBitFieldType(): 7621 bf := b.Type().BitField() 7622 w = bf.BitFieldWidth() 7623 m = bf.Mask() >> bf.BitFieldOffset() 7624 default: 7625 return "" 7626 } 7627 7628 p.w("((") 7629 switch { 7630 case promote.IsSignedType(): 7631 n := int(promote.Size())*8 - w 7632 var s string 7633 switch promote.Size() { 7634 case 4: 7635 s = fmt.Sprintf(")&%#x", int32(m)) 7636 default: 7637 s = fmt.Sprintf(")&%#x", m) 7638 } 7639 if n != 0 { 7640 s += fmt.Sprintf("<<%d>>%[1]d", n) 7641 } 7642 return ")" + s 7643 default: 7644 return fmt.Sprintf(")&%#x)", m) 7645 } 7646 } 7647 7648 func intAddOverflows(n cc.Node, lo, ro cc.Operand, oper string, promote cc.Type) bool { 7649 a, b, ok := getIntOperands(lo, ro) 7650 if !ok { 7651 return false 7652 } 7653 7654 switch oper { 7655 case "+": 7656 return overflows(a.Add(a, b), promote) 7657 case "-": 7658 return overflows(a.Sub(a, b), promote) 7659 default: 7660 panic(todo("", pos(n))) 7661 } 7662 } 7663 7664 func getIntOperands(a, b cc.Operand) (x, y *big.Int, ok bool) { 7665 switch n := a.Value().(type) { 7666 case cc.Int64Value: 7667 x = big.NewInt(int64(n)) 7668 case cc.Uint64Value: 7669 x = big.NewInt(0).SetUint64(uint64(n)) 7670 default: 7671 return nil, nil, false 7672 } 7673 7674 switch n := b.Value().(type) { 7675 case cc.Int64Value: 7676 return x, big.NewInt(int64(n)), true 7677 case cc.Uint64Value: 7678 return x, big.NewInt(0).SetUint64(uint64(n)), true 7679 default: 7680 return nil, nil, false 7681 } 7682 } 7683 7684 func overflows(n *big.Int, promote cc.Type) bool { 7685 switch k := promote.Kind(); { 7686 case k == cc.Int128, k == cc.UInt128: 7687 return false 7688 case isSigned(promote): 7689 switch promote.Size() { 7690 case 4: 7691 return n.Cmp(minInt32) < 0 || n.Cmp(maxInt32) > 0 7692 case 8: 7693 return n.Cmp(minInt64) < 0 || n.Cmp(maxInt64) > 0 7694 } 7695 default: 7696 switch promote.Size() { 7697 case 4: 7698 return n.Sign() < 0 || n.Cmp(maxUint32) > 0 7699 case 8: 7700 return n.Sign() < 0 || n.Cmp(maxUint64) > 0 7701 } 7702 } 7703 panic(todo("", promote.Size(), promote)) 7704 } 7705 7706 func (p *project) multiplicativeExpression(f *function, n *cc.MultiplicativeExpression, t cc.Type, mode exprMode, flags flags) { 7707 switch mode { 7708 case exprValue: 7709 p.multiplicativeExpressionValue(f, n, t, mode, flags) 7710 case exprVoid: 7711 p.multiplicativeExpressionVoid(f, n, t, mode, flags) 7712 case exprAddrOf: 7713 p.multiplicativeExpressionAddrOf(f, n, t, mode, flags) 7714 case exprBool: 7715 p.multiplicativeExpressionBool(f, n, t, mode, flags) 7716 case exprLValue: 7717 p.multiplicativeExpressionLValue(f, n, t, mode, flags) 7718 case exprPSelect: 7719 p.multiplicativeExpressionPSelect(f, n, t, mode, flags) 7720 case exprFunc: 7721 p.multiplicativeExpressionFunc(f, n, t, mode, flags) 7722 case exprSelect: 7723 p.multiplicativeExpressionSelect(f, n, t, mode, flags) 7724 case exprDecay: 7725 p.multiplicativeExpressionDecay(f, n, t, mode, flags) 7726 default: 7727 panic(todo("", n.Position(), mode)) 7728 } 7729 } 7730 7731 func (p *project) multiplicativeExpressionDecay(f *function, n *cc.MultiplicativeExpression, t cc.Type, mode exprMode, flags flags) { 7732 switch n.Case { 7733 case cc.MultiplicativeExpressionCast: // CastExpression 7734 p.castExpression(f, n.CastExpression, t, mode, flags) 7735 case cc.MultiplicativeExpressionMul: // MultiplicativeExpression '*' CastExpression 7736 panic(todo("", p.pos(n))) 7737 case cc.MultiplicativeExpressionDiv: // MultiplicativeExpression '/' CastExpression 7738 panic(todo("", p.pos(n))) 7739 case cc.MultiplicativeExpressionMod: // MultiplicativeExpression '%' CastExpression 7740 panic(todo("", p.pos(n))) 7741 default: 7742 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 7743 } 7744 } 7745 7746 func (p *project) multiplicativeExpressionSelect(f *function, n *cc.MultiplicativeExpression, t cc.Type, mode exprMode, flags flags) { 7747 switch n.Case { 7748 case cc.MultiplicativeExpressionCast: // CastExpression 7749 p.castExpression(f, n.CastExpression, t, mode, flags) 7750 case cc.MultiplicativeExpressionMul: // MultiplicativeExpression '*' CastExpression 7751 panic(todo("", p.pos(n))) 7752 case cc.MultiplicativeExpressionDiv: // MultiplicativeExpression '/' CastExpression 7753 panic(todo("", p.pos(n))) 7754 case cc.MultiplicativeExpressionMod: // MultiplicativeExpression '%' CastExpression 7755 panic(todo("", p.pos(n))) 7756 default: 7757 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 7758 } 7759 } 7760 7761 func (p *project) multiplicativeExpressionFunc(f *function, n *cc.MultiplicativeExpression, t cc.Type, mode exprMode, flags flags) { 7762 switch n.Case { 7763 case cc.MultiplicativeExpressionCast: // CastExpression 7764 p.castExpression(f, n.CastExpression, t, mode, flags) 7765 case cc.MultiplicativeExpressionMul: // MultiplicativeExpression '*' CastExpression 7766 panic(todo("", p.pos(n))) 7767 case cc.MultiplicativeExpressionDiv: // MultiplicativeExpression '/' CastExpression 7768 panic(todo("", p.pos(n))) 7769 case cc.MultiplicativeExpressionMod: // MultiplicativeExpression '%' CastExpression 7770 panic(todo("", p.pos(n))) 7771 default: 7772 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 7773 } 7774 } 7775 7776 func (p *project) multiplicativeExpressionPSelect(f *function, n *cc.MultiplicativeExpression, t cc.Type, mode exprMode, flags flags) { 7777 switch n.Case { 7778 case cc.MultiplicativeExpressionCast: // CastExpression 7779 p.castExpression(f, n.CastExpression, t, mode, flags) 7780 case cc.MultiplicativeExpressionMul: // MultiplicativeExpression '*' CastExpression 7781 panic(todo("", p.pos(n))) 7782 case cc.MultiplicativeExpressionDiv: // MultiplicativeExpression '/' CastExpression 7783 panic(todo("", p.pos(n))) 7784 case cc.MultiplicativeExpressionMod: // MultiplicativeExpression '%' CastExpression 7785 panic(todo("", p.pos(n))) 7786 default: 7787 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 7788 } 7789 } 7790 7791 func (p *project) multiplicativeExpressionLValue(f *function, n *cc.MultiplicativeExpression, t cc.Type, mode exprMode, flags flags) { 7792 switch n.Case { 7793 case cc.MultiplicativeExpressionCast: // CastExpression 7794 p.castExpression(f, n.CastExpression, t, mode, flags) 7795 case cc.MultiplicativeExpressionMul: // MultiplicativeExpression '*' CastExpression 7796 panic(todo("", p.pos(n))) 7797 case cc.MultiplicativeExpressionDiv: // MultiplicativeExpression '/' CastExpression 7798 panic(todo("", p.pos(n))) 7799 case cc.MultiplicativeExpressionMod: // MultiplicativeExpression '%' CastExpression 7800 panic(todo("", p.pos(n))) 7801 default: 7802 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 7803 } 7804 } 7805 7806 func (p *project) multiplicativeExpressionBool(f *function, n *cc.MultiplicativeExpression, t cc.Type, mode exprMode, flags flags) { 7807 switch n.Case { 7808 case cc.MultiplicativeExpressionCast: // CastExpression 7809 p.castExpression(f, n.CastExpression, t, mode, flags) 7810 case 7811 cc.MultiplicativeExpressionMul, // MultiplicativeExpression '*' CastExpression 7812 cc.MultiplicativeExpressionDiv, // MultiplicativeExpression '/' CastExpression 7813 cc.MultiplicativeExpressionMod: // MultiplicativeExpression '%' CastExpression 7814 7815 p.w("(") 7816 defer p.w(")") 7817 defer p.w(" != 0 ") 7818 p.multiplicativeExpression(f, n, t, exprValue, flags) 7819 default: 7820 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 7821 } 7822 } 7823 7824 func (p *project) multiplicativeExpressionAddrOf(f *function, n *cc.MultiplicativeExpression, t cc.Type, mode exprMode, flags flags) { 7825 switch n.Case { 7826 case cc.MultiplicativeExpressionCast: // CastExpression 7827 p.castExpression(f, n.CastExpression, t, mode, flags) 7828 case cc.MultiplicativeExpressionMul: // MultiplicativeExpression '*' CastExpression 7829 panic(todo("", p.pos(n))) 7830 case cc.MultiplicativeExpressionDiv: // MultiplicativeExpression '/' CastExpression 7831 panic(todo("", p.pos(n))) 7832 case cc.MultiplicativeExpressionMod: // MultiplicativeExpression '%' CastExpression 7833 panic(todo("", p.pos(n))) 7834 default: 7835 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 7836 } 7837 } 7838 7839 func (p *project) multiplicativeExpressionVoid(f *function, n *cc.MultiplicativeExpression, t cc.Type, mode exprMode, flags flags) { 7840 switch n.Case { 7841 case cc.MultiplicativeExpressionCast: // CastExpression 7842 p.castExpression(f, n.CastExpression, t, mode, flags) 7843 case cc.MultiplicativeExpressionMul: // MultiplicativeExpression '*' CastExpression 7844 panic(todo("", p.pos(n))) 7845 case cc.MultiplicativeExpressionDiv: // MultiplicativeExpression '/' CastExpression 7846 panic(todo("", p.pos(n))) 7847 case cc.MultiplicativeExpressionMod: // MultiplicativeExpression '%' CastExpression 7848 panic(todo("", p.pos(n))) 7849 default: 7850 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 7851 } 7852 } 7853 7854 func (p *project) multiplicativeExpressionValue(f *function, n *cc.MultiplicativeExpression, t cc.Type, mode exprMode, flags flags) { 7855 switch n.Case { 7856 case cc.MultiplicativeExpressionCast: // CastExpression 7857 p.castExpression(f, n.CastExpression, t, mode, flags) 7858 case cc.MultiplicativeExpressionMul: // MultiplicativeExpression '*' CastExpression 7859 p.binaryMultiplicativeExpression(f, n, "*", t, mode, flags) 7860 case cc.MultiplicativeExpressionDiv: // MultiplicativeExpression '/' CastExpression 7861 p.binaryMultiplicativeExpression(f, n, "/", t, mode, flags) 7862 case cc.MultiplicativeExpressionMod: // MultiplicativeExpression '%' CastExpression 7863 p.binaryMultiplicativeExpression(f, n, "%", t, mode, flags) 7864 default: 7865 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 7866 } 7867 } 7868 7869 func (p *project) binaryMultiplicativeExpression(f *function, n *cc.MultiplicativeExpression, oper string, t cc.Type, mode exprMode, flags flags) { 7870 // MultiplicativeExpression '*' CastExpression 7871 switch mode { 7872 case exprValue: 7873 p.binaryMultiplicativeExpressionValue(f, n, oper, t, mode, flags) 7874 default: 7875 panic(todo("", n.Position(), mode)) 7876 } 7877 } 7878 7879 func (p *project) binaryMultiplicativeExpressionValue(f *function, n *cc.MultiplicativeExpression, oper string, t cc.Type, mode exprMode, flags flags) { 7880 // MultiplicativeExpression '*' CastExpression 7881 7882 lt := n.MultiplicativeExpression.Operand.Type() 7883 rt := n.CastExpression.Operand.Type() 7884 switch lk, rk := lt.Kind(), rt.Kind(); { 7885 case 7886 lk == cc.UInt128 || rk == cc.UInt128, 7887 lk == cc.Int128 || rk == cc.Int128: 7888 7889 p.binaryMultiplicativeExpressionUint128(f, n, oper, t, mode, flags) 7890 return 7891 } 7892 7893 defer p.w("%s", p.artithmeticBinaryExpression(n, n.Operand, t, &mode, flags)) 7894 switch { 7895 case intMulOverflows(n, n.Operand, n.MultiplicativeExpression.Operand, n.CastExpression.Operand, oper, n.Promote()): 7896 p.multiplicativeExpression(f, n.MultiplicativeExpression, n.Promote(), exprValue, flags|fForceRuntimeConv) 7897 p.w(" %s%s", oper, tidyComment(" ", &n.Token)) 7898 p.castExpression(f, n.CastExpression, n.Promote(), exprValue, flags|fForceRuntimeConv) 7899 default: 7900 defer p.w("%s", p.bitFieldPatch2(n, n.MultiplicativeExpression.Operand, n.CastExpression.Operand, n.Promote())) //TODO bit field big endian 7901 var s string 7902 if isRealType(n.Operand) && n.Operand.Value() != nil { 7903 s = p.convertNil(n, n.Promote(), flags) 7904 } 7905 p.multiplicativeExpression(f, n.MultiplicativeExpression, n.Promote(), exprValue, flags) 7906 p.w("%s %s%s", s, oper, tidyComment(" ", &n.Token)) 7907 if (oper == "/" || oper == "%") && (isZeroReal(n.MultiplicativeExpression.Operand) || isZeroReal(n.CastExpression.Operand)) { 7908 p.w("%s%sFrom%[2]s(", p.task.crt, p.helperType(n, n.Promote())) 7909 defer p.w(")") 7910 } 7911 p.castExpression(f, n.CastExpression, n.Promote(), exprValue, flags) 7912 } 7913 } 7914 7915 func (p *project) binaryMultiplicativeExpressionUint128(f *function, n *cc.MultiplicativeExpression, oper string, t cc.Type, mode exprMode, flags flags) { 7916 // MultiplicativeExpression '*' CastExpression 7917 defer p.w("%s", p.artithmeticBinaryExpression(n, n.Operand, t, &mode, flags)) 7918 p.multiplicativeExpression(f, n.MultiplicativeExpression, n.Promote(), exprValue, flags) 7919 switch oper { 7920 case "*": 7921 p.w(".Mul(") 7922 case "/": 7923 p.w(".Div(") 7924 case "%": 7925 p.w(".Mod(") 7926 default: 7927 panic(todo("%q", oper)) 7928 } 7929 p.castExpression(f, n.CastExpression, n.Promote(), exprValue, flags) 7930 p.w(")") 7931 } 7932 7933 func isZeroReal(op cc.Operand) bool { 7934 switch x := op.Value().(type) { 7935 case cc.Float32Value: 7936 return x == 0 7937 case cc.Float64Value: 7938 return x == 0 7939 default: 7940 return false 7941 } 7942 } 7943 7944 func intMulOverflows(n cc.Node, r, lo, ro cc.Operand, oper string, promote cc.Type) bool { 7945 if (isReal(lo) && !isInf(lo) || isReal(ro) && !isInf(ro)) && isInf(r) { 7946 return true 7947 } 7948 7949 a, b, ok := getIntOperands(lo, ro) 7950 if !ok { 7951 return false 7952 } 7953 7954 switch oper { 7955 case "*": 7956 return overflows(a.Mul(a, b), promote) 7957 case "/": 7958 if b.Sign() == 0 { 7959 return true 7960 } 7961 7962 return overflows(a.Div(a, b), promote) 7963 case "%": 7964 if b.Sign() == 0 { 7965 return true 7966 } 7967 7968 return overflows(a.Mod(a, b), promote) 7969 default: 7970 panic(todo("", pos(n))) 7971 } 7972 } 7973 7974 func isReal(op cc.Operand) bool { 7975 switch op.Value().(type) { 7976 case cc.Float32Value, cc.Float64Value: 7977 return true 7978 default: 7979 return false 7980 } 7981 } 7982 7983 func isInf(op cc.Operand) bool { 7984 switch x := op.Value().(type) { 7985 case cc.Float32Value: 7986 return math.IsInf(float64(x), 0) 7987 case cc.Float64Value: 7988 return math.IsInf(float64(x), 0) 7989 default: 7990 return false 7991 } 7992 } 7993 7994 func (p *project) castExpression(f *function, n *cc.CastExpression, t cc.Type, mode exprMode, flags flags) { 7995 if n.Case == cc.CastExpressionCast { 7996 if f != nil && n.CastExpression.Operand.Type().Kind() == cc.Ptr { // void *__ccgo_va_arg(__builtin_va_list ap); 7997 sv := f.vaType 7998 f.vaType = n.TypeName.Type() 7999 defer func() { f.vaType = sv }() 8000 } 8001 } 8002 switch mode { 8003 case exprValue: 8004 p.castExpressionValue(f, n, t, mode, flags) 8005 case exprVoid: 8006 p.castExpressionVoid(f, n, t, mode, flags) 8007 case exprAddrOf: 8008 p.castExpressionAddrOf(f, n, t, mode, flags) 8009 case exprBool: 8010 p.castExpressionBool(f, n, t, mode, flags) 8011 case exprLValue: 8012 p.castExpressionLValue(f, n, t, mode, flags) 8013 case exprPSelect: 8014 p.castExpressionPSelect(f, n, t, mode, flags) 8015 case exprFunc: 8016 p.castExpressionFunc(f, n, t, mode, flags) 8017 case exprSelect: 8018 p.castExpressionSelect(f, n, t, mode, flags) 8019 case exprDecay: 8020 p.castExpressionDecay(f, n, t, mode, flags) 8021 default: 8022 panic(todo("", n.Position(), mode)) 8023 } 8024 } 8025 8026 func (p *project) castExpressionDecay(f *function, n *cc.CastExpression, t cc.Type, mode exprMode, flags flags) { 8027 switch n.Case { 8028 case cc.CastExpressionUnary: // UnaryExpression 8029 p.unaryExpression(f, n.UnaryExpression, t, mode, flags) 8030 case cc.CastExpressionCast: // '(' TypeName ')' CastExpression 8031 panic(todo("", p.pos(n))) 8032 default: 8033 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 8034 } 8035 } 8036 8037 func (p *project) castExpressionSelect(f *function, n *cc.CastExpression, t cc.Type, mode exprMode, flags flags) { 8038 switch n.Case { 8039 case cc.CastExpressionUnary: // UnaryExpression 8040 p.unaryExpression(f, n.UnaryExpression, t, mode, flags) 8041 case cc.CastExpressionCast: // '(' TypeName ')' CastExpression 8042 p.castExpression(f, n.CastExpression, n.TypeName.Type(), mode, flags) 8043 default: 8044 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 8045 } 8046 } 8047 8048 func (p *project) castExpressionFunc(f *function, n *cc.CastExpression, t cc.Type, mode exprMode, flags flags) { 8049 switch n.Case { 8050 case cc.CastExpressionUnary: // UnaryExpression 8051 p.unaryExpression(f, n.UnaryExpression, t, mode, flags) 8052 case cc.CastExpressionCast: // '(' TypeName ')' CastExpression 8053 ot := n.CastExpression.Operand.Type() 8054 tn := n.TypeName.Type() 8055 var ft cc.Type 8056 switch tn.Kind() { 8057 case cc.Ptr: 8058 switch et := ot.Elem(); et.Kind() { 8059 case cc.Function, cc.Void: 8060 // ok 8061 default: 8062 panic(todo("", p.pos(n), et, et.Kind())) 8063 } 8064 default: 8065 panic(todo("%v: %v, %v -> %v, %v -> %v, %v", p.pos(n), ot, ot.Kind(), tn, tn.Kind(), t, t.Kind())) 8066 } 8067 switch t.Kind() { 8068 case cc.Ptr: 8069 switch et := t.Elem(); et.Kind() { 8070 case cc.Function: 8071 ft = et 8072 default: 8073 panic(todo("", p.pos(n), et, et.Kind())) 8074 } 8075 default: 8076 panic(todo("%v: %v, %v -> %v, %v -> %v, %v", p.pos(n), ot, ot.Kind(), tn, tn.Kind(), t, t.Kind())) 8077 } 8078 switch ot.Kind() { 8079 case cc.Ptr: 8080 switch et := ot.Elem(); et.Kind() { 8081 case cc.Function, cc.Void: 8082 p.w("(*(*") 8083 p.functionSignature(n, f, ft, "") 8084 p.w(")(unsafe.Pointer(") 8085 p.castExpression(f, n.CastExpression, ot, exprAddrOf, flags) 8086 p.w(")))") 8087 default: 8088 panic(todo("", p.pos(n), et, et.Kind())) 8089 } 8090 default: 8091 panic(todo("%v: %v, %v -> %v, %v -> %v, %v", p.pos(n), ot, ot.Kind(), tn, tn.Kind(), t, t.Kind())) 8092 } 8093 default: 8094 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 8095 } 8096 } 8097 8098 func (p *project) castExpressionPSelect(f *function, n *cc.CastExpression, t cc.Type, mode exprMode, flags flags) { 8099 switch n.Case { 8100 case cc.CastExpressionUnary: // UnaryExpression 8101 p.unaryExpression(f, n.UnaryExpression, t, mode, flags) 8102 case cc.CastExpressionCast: // '(' TypeName ')' CastExpression 8103 p.castExpression(f, n.CastExpression, n.TypeName.Type(), mode, flags) 8104 default: 8105 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 8106 } 8107 } 8108 8109 func (p *project) castExpressionLValue(f *function, n *cc.CastExpression, t cc.Type, mode exprMode, flags flags) { 8110 switch n.Case { 8111 case cc.CastExpressionUnary: // UnaryExpression 8112 p.unaryExpression(f, n.UnaryExpression, t, mode, flags) 8113 case cc.CastExpressionCast: // '(' TypeName ')' CastExpression 8114 panic(todo("", p.pos(n))) 8115 default: 8116 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 8117 } 8118 } 8119 8120 func (p *project) castExpressionBool(f *function, n *cc.CastExpression, t cc.Type, mode exprMode, flags flags) { 8121 switch n.Case { 8122 case cc.CastExpressionUnary: // UnaryExpression 8123 p.unaryExpression(f, n.UnaryExpression, t, mode, flags) 8124 case cc.CastExpressionCast: // '(' TypeName ')' CastExpression 8125 p.w("(") 8126 defer p.w(")") 8127 defer p.w(" != 0 ") 8128 p.castExpression(f, n, n.Operand.Type(), exprValue, flags) 8129 default: 8130 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 8131 } 8132 } 8133 8134 func (p *project) castExpressionAddrOf(f *function, n *cc.CastExpression, t cc.Type, mode exprMode, flags flags) { 8135 switch n.Case { 8136 case cc.CastExpressionUnary: // UnaryExpression 8137 p.unaryExpression(f, n.UnaryExpression, t, mode, flags) 8138 case cc.CastExpressionCast: // '(' TypeName ')' CastExpression 8139 p.castExpressionAddrOf(f, n.CastExpression, t, mode, flags) 8140 default: 8141 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 8142 } 8143 } 8144 8145 func (p *project) castExpressionVoid(f *function, n *cc.CastExpression, t cc.Type, mode exprMode, flags flags) { 8146 switch n.Case { 8147 case cc.CastExpressionUnary: // UnaryExpression 8148 p.unaryExpression(f, n.UnaryExpression, t, mode, flags) 8149 case cc.CastExpressionCast: // '(' TypeName ')' CastExpression 8150 p.castExpression(f, n.CastExpression, t, mode, flags) 8151 default: 8152 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 8153 } 8154 } 8155 8156 func (p *project) castExpressionValue(f *function, n *cc.CastExpression, t cc.Type, mode exprMode, flags flags) { 8157 switch n.Case { 8158 case cc.CastExpressionUnary: // UnaryExpression 8159 p.unaryExpression(f, n.UnaryExpression, t, mode, flags) 8160 case cc.CastExpressionCast: // '(' TypeName ')' CastExpression 8161 if f != nil && p.pass1 && n.TypeName.Type().IsIntegerType() && n.CastExpression.Operand.Type().Kind() == cc.Array { 8162 if d := n.CastExpression.Declarator(); d != nil { 8163 f.pin(n, d) 8164 } 8165 } 8166 switch k := p.opKind(f, n.CastExpression, n.CastExpression.Operand.Type()); k { 8167 case opNormal, opBitfield: 8168 p.castExpressionValueNormal(f, n, t, mode, flags) 8169 case opArray: 8170 p.castExpressionValueArray(f, n, t, mode, flags) 8171 case opFunction: 8172 p.castExpressionValueFunction(f, n, t, mode, flags) 8173 case opArrayParameter: 8174 p.castExpressionValueNormal(f, n, t, mode, flags) 8175 default: 8176 panic(todo("", n.Position(), k)) 8177 } 8178 default: 8179 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 8180 } 8181 } 8182 8183 func (p *project) castExpressionValueArrayParameter(f *function, n *cc.CastExpression, t cc.Type, mode exprMode, flags flags) { 8184 // '(' TypeName ')' CastExpression 8185 tn := n.TypeName.Type() 8186 defer p.w("%s", p.convertType(n, tn, t, flags)) 8187 p.castExpression(f, n.CastExpression, tn, mode, flags) 8188 } 8189 8190 func (p *project) castExpressionValueFunction(f *function, n *cc.CastExpression, t cc.Type, mode exprMode, flags flags) { 8191 // '(' TypeName ')' CastExpression 8192 op := n.CastExpression.Operand 8193 tn := n.TypeName.Type() 8194 switch { 8195 case op.Type().Kind() == cc.Function: 8196 switch { 8197 case tn.Kind() == cc.Ptr && t.Kind() == cc.Ptr: 8198 p.castExpression(f, n.CastExpression, op.Type(), exprValue, flags) 8199 case tn.IsIntegerType(): 8200 p.w("%s(", p.typ(n, tn)) 8201 p.castExpression(f, n.CastExpression, op.Type(), exprValue, flags) 8202 p.w(")") 8203 default: 8204 panic(todo("%v: tn %v expr %v", n.Position(), tn, op.Type())) 8205 } 8206 default: 8207 panic(todo("%v: %v -> %v -> %v", p.pos(n), op.Type(), tn, t)) 8208 } 8209 } 8210 8211 func (p *project) castExpressionValueArray(f *function, n *cc.CastExpression, t cc.Type, mode exprMode, flags flags) { 8212 // '(' TypeName ')' CastExpression 8213 tn := n.TypeName.Type() 8214 switch { 8215 case tn.IsScalarType(): 8216 defer p.w("%s", p.convertType(n, nil, t, flags)) 8217 p.castExpression(f, n.CastExpression, tn, exprDecay, flags) 8218 default: 8219 panic(todo("", p.pos(n))) 8220 } 8221 } 8222 8223 func (p *project) castExpressionValueNormal(f *function, n *cc.CastExpression, t cc.Type, mode exprMode, flags flags) { 8224 // '(' TypeName ')' CastExpression 8225 op := n.CastExpression.Operand 8226 tn := n.TypeName.Type() 8227 switch { 8228 case op.Type().Kind() == cc.Ptr && tn.IsArithmeticType(): 8229 defer p.w("%s", p.convertType(n, nil, t, flags|fForceConv)) 8230 p.castExpression(f, n.CastExpression, op.Type(), mode, flags) 8231 case tn.IsArithmeticType(): 8232 switch { 8233 case (tn.Kind() == cc.Float || tn.Kind() == cc.Double) && op.Type().IsIntegerType() && op.Value() != nil && t.IsIntegerType(): 8234 panic(todo("", p.pos(n))) 8235 case isNegativeInt(op) && isUnsigned(t): 8236 defer p.w("%s", p.convertType(n, tn, t, flags|fForceConv)) 8237 p.castExpression(f, n.CastExpression, tn, exprValue, flags) 8238 default: 8239 defer p.w("%s", p.convertType(n, tn, t, flags)) 8240 p.castExpression(f, n.CastExpression, tn, exprValue, flags) 8241 } 8242 default: 8243 switch tn.Kind() { 8244 case cc.Ptr: 8245 switch { 8246 case t.Kind() == cc.Ptr && isNegativeInt(op): 8247 p.w("%s(", p.helperType2(n, op.Type(), tn)) 8248 defer p.w(")") 8249 p.castExpression(f, n.CastExpression, op.Type(), mode, flags) 8250 default: 8251 defer p.w("%s", p.convertType(n, tn, t, flags)) 8252 p.castExpression(f, n.CastExpression, tn, mode, flags) 8253 } 8254 case cc.Void: 8255 p.castExpression(f, n.CastExpression, tn, exprVoid, flags) 8256 default: 8257 panic(todo("%s: %s %s -> %s %s -> %s %s", n.Position(), op.Type(), op.Type().Kind(), tn, tn.Kind(), t, t.Kind())) 8258 } 8259 } 8260 } 8261 8262 func (p *project) unaryExpression(f *function, n *cc.UnaryExpression, t cc.Type, mode exprMode, flags flags) { 8263 switch mode { 8264 case exprLValue: 8265 p.unaryExpressionLValue(f, n, t, mode, flags) 8266 case exprValue: 8267 p.unaryExpressionValue(f, n, t, mode, flags) 8268 case exprVoid: 8269 p.unaryExpressionVoid(f, n, t, mode, flags) 8270 case exprAddrOf: 8271 p.unaryExpressionAddrOf(f, n, t, mode, flags) 8272 case exprBool: 8273 p.unaryExpressionBool(f, n, t, mode, flags) 8274 case exprPSelect: 8275 p.unaryExpressionPSelect(f, n, t, mode, flags) 8276 case exprFunc: 8277 p.unaryExpressionFunc(f, n, t, mode, flags) 8278 case exprSelect: 8279 p.unaryExpressionSelect(f, n, t, mode, flags) 8280 case exprDecay: 8281 p.unaryExpressionDecay(f, n, t, mode, flags) 8282 default: 8283 panic(todo("", n.Position(), mode)) 8284 } 8285 } 8286 8287 func (p *project) unaryExpressionDecay(f *function, n *cc.UnaryExpression, t cc.Type, mode exprMode, flags flags) { 8288 switch n.Case { 8289 case cc.UnaryExpressionPostfix: // PostfixExpression 8290 p.postfixExpression(f, n.PostfixExpression, t, mode, flags) 8291 case cc.UnaryExpressionInc: // "++" UnaryExpression 8292 panic(todo("", p.pos(n))) 8293 case cc.UnaryExpressionDec: // "--" UnaryExpression 8294 panic(todo("", p.pos(n))) 8295 case cc.UnaryExpressionAddrof: // '&' CastExpression 8296 panic(todo("", p.pos(n))) 8297 case cc.UnaryExpressionDeref: // '*' CastExpression 8298 p.castExpression(f, n.CastExpression, n.CastExpression.Operand.Type(), exprValue, flags) 8299 case cc.UnaryExpressionPlus: // '+' CastExpression 8300 panic(todo("", p.pos(n))) 8301 case cc.UnaryExpressionMinus: // '-' CastExpression 8302 panic(todo("", p.pos(n))) 8303 case cc.UnaryExpressionCpl: // '~' CastExpression 8304 panic(todo("", p.pos(n))) 8305 case cc.UnaryExpressionNot: // '!' CastExpression 8306 panic(todo("", p.pos(n))) 8307 case cc.UnaryExpressionSizeofExpr: // "sizeof" UnaryExpression 8308 panic(todo("", p.pos(n))) 8309 case cc.UnaryExpressionSizeofType: // "sizeof" '(' TypeName ')' 8310 panic(todo("", p.pos(n))) 8311 case cc.UnaryExpressionLabelAddr: // "&&" IDENTIFIER 8312 panic(todo("", p.pos(n))) 8313 case cc.UnaryExpressionAlignofExpr: // "_Alignof" UnaryExpression 8314 panic(todo("", p.pos(n))) 8315 case cc.UnaryExpressionAlignofType: // "_Alignof" '(' TypeName ')' 8316 panic(todo("", p.pos(n))) 8317 case cc.UnaryExpressionImag: // "__imag__" UnaryExpression 8318 panic(todo("", p.pos(n))) 8319 case cc.UnaryExpressionReal: // "__real__" UnaryExpression 8320 panic(todo("", p.pos(n))) 8321 default: 8322 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 8323 } 8324 } 8325 8326 func (p *project) unaryExpressionSelect(f *function, n *cc.UnaryExpression, t cc.Type, mode exprMode, flags flags) { 8327 switch n.Case { 8328 case cc.UnaryExpressionPostfix: // PostfixExpression 8329 p.postfixExpression(f, n.PostfixExpression, t, mode, flags) 8330 case cc.UnaryExpressionInc: // "++" UnaryExpression 8331 panic(todo("", n.Position())) 8332 case cc.UnaryExpressionDec: // "--" UnaryExpression 8333 panic(todo("", n.Position())) 8334 case cc.UnaryExpressionAddrof: // '&' CastExpression 8335 panic(todo("", p.pos(n))) 8336 case cc.UnaryExpressionDeref: // '*' CastExpression 8337 ot := n.CastExpression.Operand.Type() 8338 switch ot.Kind() { 8339 case cc.Ptr: 8340 switch et := ot.Elem(); et.Kind() { 8341 case 8342 cc.Struct, 8343 cc.Union: 8344 8345 p.w("(*(*%s)(unsafe.Pointer(", p.typ(n, n.Operand.Type())) 8346 p.castExpression(f, n.CastExpression, n.CastExpression.Operand.Type(), exprValue, flags) 8347 p.w(")))") 8348 default: 8349 panic(todo("", p.pos(n), et, et.Kind())) 8350 } 8351 case cc.Array: 8352 p.w("(*(*%s)(unsafe.Pointer(", p.typ(n, n.Operand.Type())) 8353 p.castExpression(f, n.CastExpression, n.CastExpression.Operand.Type(), exprAddrOf, flags) 8354 p.w(")))") 8355 default: 8356 panic(todo("", p.pos(n), ot, ot.Kind())) 8357 } 8358 case cc.UnaryExpressionPlus: // '+' CastExpression 8359 panic(todo("", p.pos(n))) 8360 case cc.UnaryExpressionMinus: // '-' CastExpression 8361 panic(todo("", p.pos(n))) 8362 case cc.UnaryExpressionCpl: // '~' CastExpression 8363 panic(todo("", p.pos(n))) 8364 case cc.UnaryExpressionNot: // '!' CastExpression 8365 panic(todo("", p.pos(n))) 8366 case cc.UnaryExpressionSizeofExpr: // "sizeof" UnaryExpression 8367 panic(todo("", p.pos(n))) 8368 case cc.UnaryExpressionSizeofType: // "sizeof" '(' TypeName ')' 8369 panic(todo("", p.pos(n))) 8370 case cc.UnaryExpressionLabelAddr: // "&&" IDENTIFIER 8371 panic(todo("", p.pos(n))) 8372 case cc.UnaryExpressionAlignofExpr: // "_Alignof" UnaryExpression 8373 panic(todo("", p.pos(n))) 8374 case cc.UnaryExpressionAlignofType: // "_Alignof" '(' TypeName ')' 8375 panic(todo("", p.pos(n))) 8376 case cc.UnaryExpressionImag: // "__imag__" UnaryExpression 8377 panic(todo("", p.pos(n))) 8378 case cc.UnaryExpressionReal: // "__real__" UnaryExpression 8379 panic(todo("", p.pos(n))) 8380 default: 8381 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 8382 } 8383 } 8384 8385 func (p *project) unaryExpressionFunc(f *function, n *cc.UnaryExpression, t cc.Type, mode exprMode, flags flags) { 8386 switch n.Case { 8387 case cc.UnaryExpressionPostfix: // PostfixExpression 8388 p.postfixExpression(f, n.PostfixExpression, t, mode, flags) 8389 case cc.UnaryExpressionInc: // "++" UnaryExpression 8390 panic(todo("", p.pos(n))) 8391 case cc.UnaryExpressionDec: // "--" UnaryExpression 8392 panic(todo("", p.pos(n))) 8393 case cc.UnaryExpressionAddrof: // '&' CastExpression 8394 panic(todo("", p.pos(n))) 8395 case cc.UnaryExpressionDeref: // '*' CastExpression 8396 ot := n.CastExpression.Operand.Type() 8397 switch ot.Kind() { 8398 case cc.Ptr: 8399 switch et := ot.Elem(); et.Kind() { 8400 case cc.Function: 8401 p.castExpression(f, n.CastExpression, ot, mode, flags|fAddrOfFuncPtrOk) 8402 case cc.Ptr: 8403 switch et2 := et.Elem(); et2.Kind() { 8404 case cc.Function: 8405 // C: (**)() 8406 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) 8407 default: 8408 panic(todo("", p.pos(n), et2, et2.Kind())) 8409 } 8410 default: 8411 panic(todo("", p.pos(n), et, et.Kind())) 8412 } 8413 case cc.Function: 8414 p.castExpression(f, n.CastExpression, ot, mode, flags|fAddrOfFuncPtrOk) 8415 default: 8416 panic(todo("", p.pos(n), ot, ot.Kind(), mode)) 8417 } 8418 case cc.UnaryExpressionPlus: // '+' CastExpression 8419 panic(todo("", p.pos(n))) 8420 case cc.UnaryExpressionMinus: // '-' CastExpression 8421 panic(todo("", p.pos(n))) 8422 case cc.UnaryExpressionCpl: // '~' CastExpression 8423 panic(todo("", p.pos(n))) 8424 case cc.UnaryExpressionNot: // '!' CastExpression 8425 panic(todo("", p.pos(n))) 8426 case cc.UnaryExpressionSizeofExpr: // "sizeof" UnaryExpression 8427 panic(todo("", p.pos(n))) 8428 case cc.UnaryExpressionSizeofType: // "sizeof" '(' TypeName ')' 8429 panic(todo("", p.pos(n))) 8430 case cc.UnaryExpressionLabelAddr: // "&&" IDENTIFIER 8431 panic(todo("", p.pos(n))) 8432 case cc.UnaryExpressionAlignofExpr: // "_Alignof" UnaryExpression 8433 panic(todo("", p.pos(n))) 8434 case cc.UnaryExpressionAlignofType: // "_Alignof" '(' TypeName ')' 8435 panic(todo("", p.pos(n))) 8436 case cc.UnaryExpressionImag: // "__imag__" UnaryExpression 8437 panic(todo("", p.pos(n))) 8438 case cc.UnaryExpressionReal: // "__real__" UnaryExpression 8439 panic(todo("", p.pos(n))) 8440 default: 8441 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 8442 } 8443 } 8444 8445 func (p *project) unaryExpressionPSelect(f *function, n *cc.UnaryExpression, t cc.Type, mode exprMode, flags flags) { 8446 switch n.Case { 8447 case cc.UnaryExpressionPostfix: // PostfixExpression 8448 p.postfixExpression(f, n.PostfixExpression, t, mode, flags) 8449 case cc.UnaryExpressionInc: // "++" UnaryExpression 8450 panic(todo("", n.Position())) 8451 case cc.UnaryExpressionDec: // "--" UnaryExpression 8452 panic(todo("", n.Position())) 8453 case cc.UnaryExpressionAddrof: // '&' CastExpression 8454 panic(todo("", n.Position())) 8455 //TODO- p.w("(*%s)(unsafe.Pointer(", p.typ(n, n.Operand.Type().Elem())) 8456 //TODO- p.unaryExpression(f, n, t, exprValue, flags) 8457 //TODO- p.w("))") 8458 case cc.UnaryExpressionDeref: // '*' CastExpression 8459 panic(todo("", n.Position())) 8460 //TODO- ot := n.CastExpression.Operand.Type() 8461 //TODO- switch ot.Kind() { 8462 //TODO- case cc.Ptr: 8463 //TODO- switch et := ot.Elem(); { 8464 //TODO- case et.Kind() == cc.Ptr: 8465 //TODO- switch et2 := et.Elem(); et2.Kind() { 8466 //TODO- case cc.Struct: 8467 //TODO- if et2.IsIncomplete() { 8468 //TODO- p.w("(*(**uintptr)(unsafe.Pointer(") 8469 //TODO- p.castExpression(f, n.CastExpression, t, exprValue, flags) 8470 //TODO- p.w(")))") 8471 //TODO- break 8472 //TODO- } 8473 8474 //TODO- p.w("(*(**%s)(unsafe.Pointer(", p.typ(n, n.Operand.Type().Elem())) 8475 //TODO- p.castExpression(f, n.CastExpression, t, exprValue, flags) 8476 //TODO- p.w(")))") 8477 //TODO- default: 8478 //TODO- panic(todo("", p.pos(n), et2, et2.Kind())) 8479 //TODO- } 8480 //TODO- default: 8481 //TODO- panic(todo("", p.pos(n), et, et.Kind())) 8482 //TODO- } 8483 //TODO- default: 8484 //TODO- panic(todo("", p.pos(n), ot, ot.Kind())) 8485 //TODO- } 8486 case cc.UnaryExpressionPlus: // '+' CastExpression 8487 panic(todo("", p.pos(n))) 8488 case cc.UnaryExpressionMinus: // '-' CastExpression 8489 panic(todo("", p.pos(n))) 8490 case cc.UnaryExpressionCpl: // '~' CastExpression 8491 panic(todo("", p.pos(n))) 8492 case cc.UnaryExpressionNot: // '!' CastExpression 8493 panic(todo("", p.pos(n))) 8494 case cc.UnaryExpressionSizeofExpr: // "sizeof" UnaryExpression 8495 panic(todo("", p.pos(n))) 8496 case cc.UnaryExpressionSizeofType: // "sizeof" '(' TypeName ')' 8497 panic(todo("", p.pos(n))) 8498 case cc.UnaryExpressionLabelAddr: // "&&" IDENTIFIER 8499 panic(todo("", p.pos(n))) 8500 case cc.UnaryExpressionAlignofExpr: // "_Alignof" UnaryExpression 8501 panic(todo("", p.pos(n))) 8502 case cc.UnaryExpressionAlignofType: // "_Alignof" '(' TypeName ')' 8503 panic(todo("", p.pos(n))) 8504 case cc.UnaryExpressionImag: // "__imag__" UnaryExpression 8505 panic(todo("", p.pos(n))) 8506 case cc.UnaryExpressionReal: // "__real__" UnaryExpression 8507 panic(todo("", p.pos(n))) 8508 default: 8509 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 8510 } 8511 } 8512 8513 func (p *project) unaryExpressionBool(f *function, n *cc.UnaryExpression, t cc.Type, mode exprMode, flags flags) { 8514 switch n.Case { 8515 case cc.UnaryExpressionPostfix: // PostfixExpression 8516 p.postfixExpression(f, n.PostfixExpression, t, mode, flags) 8517 case cc.UnaryExpressionNot: // '!' CastExpression 8518 p.w("!(") 8519 p.castExpression(f, n.CastExpression, t, mode, flags) 8520 p.w(")") 8521 default: 8522 p.w("(") 8523 defer p.w(")") 8524 defer p.w(" != 0 ") 8525 p.unaryExpression(f, n, t, exprValue, flags) 8526 } 8527 } 8528 8529 func (p *project) unaryExpressionAddrOf(f *function, n *cc.UnaryExpression, t cc.Type, mode exprMode, flags flags) { 8530 switch n.Case { 8531 case cc.UnaryExpressionPostfix: // PostfixExpression 8532 p.postfixExpression(f, n.PostfixExpression, t, mode, flags) 8533 case cc.UnaryExpressionInc: // "++" UnaryExpression 8534 panic(todo("", n.Position())) 8535 case cc.UnaryExpressionDec: // "--" UnaryExpression 8536 panic(todo("", n.Position())) 8537 case cc.UnaryExpressionAddrof: // '&' CastExpression 8538 panic(todo("", n.Position())) 8539 case cc.UnaryExpressionDeref: // '*' CastExpression 8540 ot := n.CastExpression.Operand.Type() 8541 switch ot.Kind() { 8542 case cc.Ptr: 8543 switch et := ot.Elem(); { 8544 case 8545 et.IsScalarType(), 8546 et.Kind() == cc.Struct, 8547 et.Kind() == cc.Union, 8548 et.Kind() == cc.Array: 8549 8550 p.unaryExpressionDeref(f, n, t, mode, flags) 8551 default: 8552 panic(todo("", p.pos(n), et, et.Kind())) 8553 } 8554 default: 8555 panic(todo("", p.pos(n), ot, ot.Kind())) 8556 } 8557 case cc.UnaryExpressionPlus: // '+' CastExpression 8558 panic(todo("", n.Position())) 8559 case cc.UnaryExpressionMinus: // '-' CastExpression 8560 panic(todo("", n.Position())) 8561 case cc.UnaryExpressionCpl: // '~' CastExpression 8562 panic(todo("", n.Position())) 8563 case cc.UnaryExpressionNot: // '!' CastExpression 8564 panic(todo("", n.Position())) 8565 case cc.UnaryExpressionSizeofExpr: // "sizeof" UnaryExpression 8566 panic(todo("", n.Position())) 8567 case cc.UnaryExpressionSizeofType: // "sizeof" '(' TypeName ')' 8568 panic(todo("", n.Position())) 8569 case cc.UnaryExpressionLabelAddr: // "&&" IDENTIFIER 8570 panic(todo("", n.Position())) 8571 case cc.UnaryExpressionAlignofExpr: // "_Alignof" UnaryExpression 8572 panic(todo("", n.Position())) 8573 case cc.UnaryExpressionAlignofType: // "_Alignof" '(' TypeName ')' 8574 panic(todo("", n.Position())) 8575 case cc.UnaryExpressionImag: // "__imag__" UnaryExpression 8576 panic(todo("", n.Position())) 8577 case cc.UnaryExpressionReal: // "__real__" UnaryExpression 8578 panic(todo("", n.Position())) 8579 default: 8580 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 8581 } 8582 } 8583 8584 func (p *project) unaryExpressionVoid(f *function, n *cc.UnaryExpression, t cc.Type, mode exprMode, flags flags) { 8585 switch n.Case { 8586 case cc.UnaryExpressionPostfix: // PostfixExpression 8587 p.postfixExpression(f, n.PostfixExpression, t, mode, flags) 8588 case cc.UnaryExpressionInc: // "++" UnaryExpression 8589 p.unaryExpressionPreIncDec(f, n, "++", "+=", t, mode, flags) 8590 case cc.UnaryExpressionDec: // "--" UnaryExpression 8591 p.unaryExpressionPreIncDec(f, n, "--", "-=", t, mode, flags) 8592 case cc.UnaryExpressionAddrof: // '&' CastExpression 8593 p.w("_ = ") 8594 switch { 8595 case n.CastExpression.Operand.Type().Kind() == cc.Array: 8596 panic(todo("", p.pos(n))) 8597 default: 8598 p.castExpression(f, n.CastExpression, n.CastExpression.Operand.Type(), exprAddrOf, flags) 8599 } 8600 case cc.UnaryExpressionDeref: // '*' CastExpression 8601 p.w("_ = *(*byte)(unsafe.Pointer(") 8602 p.castExpression(f, n.CastExpression, n.CastExpression.Operand.Type(), exprValue, flags) 8603 p.w("))") 8604 case 8605 cc.UnaryExpressionPlus, // '+' CastExpression 8606 cc.UnaryExpressionMinus, // '-' CastExpression 8607 cc.UnaryExpressionNot, // '!' CastExpression 8608 cc.UnaryExpressionCpl: // '~' CastExpression 8609 8610 p.w("_ = ") 8611 defer p.w("%s", p.convert(n, n.CastExpression.Operand, p.intType, flags)) 8612 p.castExpression(f, n.CastExpression, n.CastExpression.Operand.Type(), exprValue, flags) 8613 case cc.UnaryExpressionSizeofExpr: // "sizeof" UnaryExpression 8614 // nop 8615 case cc.UnaryExpressionSizeofType: // "sizeof" '(' TypeName ')' 8616 // nop 8617 case cc.UnaryExpressionLabelAddr: // "&&" IDENTIFIER 8618 panic(todo("", n.Position())) 8619 case cc.UnaryExpressionAlignofExpr: // "_Alignof" UnaryExpression 8620 panic(todo("", n.Position())) 8621 case cc.UnaryExpressionAlignofType: // "_Alignof" '(' TypeName ')' 8622 panic(todo("", n.Position())) 8623 case cc.UnaryExpressionImag: // "__imag__" UnaryExpression 8624 panic(todo("", n.Position())) 8625 case cc.UnaryExpressionReal: // "__real__" UnaryExpression 8626 panic(todo("", n.Position())) 8627 default: 8628 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 8629 } 8630 } 8631 8632 func (p *project) unaryExpressionValue(f *function, n *cc.UnaryExpression, t cc.Type, mode exprMode, flags flags) { 8633 switch n.Case { 8634 case cc.UnaryExpressionPostfix: // PostfixExpression 8635 p.postfixExpression(f, n.PostfixExpression, t, mode, flags) 8636 case cc.UnaryExpressionInc: // "++" UnaryExpression 8637 p.unaryExpressionPreIncDec(f, n, "++", "+=", t, mode, flags) 8638 case cc.UnaryExpressionDec: // "--" UnaryExpression 8639 p.unaryExpressionPreIncDec(f, n, "--", "-=", t, mode, flags) 8640 case cc.UnaryExpressionAddrof: // '&' CastExpression 8641 if t.Kind() != cc.Ptr { 8642 defer p.w("%s", p.convert(n, n.Operand, t, flags)) 8643 } 8644 switch { 8645 case n.CastExpression.Operand.Type().Kind() == cc.Array: 8646 panic(todo("", p.pos(n))) 8647 default: 8648 p.castExpression(f, n.CastExpression, n.CastExpression.Operand.Type(), exprAddrOf, flags) 8649 } 8650 case cc.UnaryExpressionDeref: // '*' CastExpression 8651 ot := n.CastExpression.Operand.Type() 8652 switch ot.Kind() { 8653 case cc.Ptr, cc.Array: 8654 switch et := ot.Elem(); { 8655 case 8656 et.IsScalarType(), 8657 et.Kind() == cc.Array, 8658 et.Kind() == cc.Struct, 8659 et.Kind() == cc.Union: 8660 8661 p.unaryExpressionDeref(f, n, t, mode, flags) 8662 case et.Kind() == cc.Function: 8663 p.castExpression(f, n.CastExpression, t, mode, flags) 8664 default: 8665 panic(todo("", p.pos(n), et, et.Kind())) 8666 } 8667 default: 8668 panic(todo("", p.pos(n), ot, ot.Kind())) 8669 } 8670 case cc.UnaryExpressionPlus: // '+' CastExpression 8671 p.w(" +") 8672 p.castExpression(f, n.CastExpression, t, mode, flags) 8673 case cc.UnaryExpressionMinus: // '-' CastExpression 8674 switch { 8675 case isNonNegativeInt(n.CastExpression.Operand) && t.Kind() == cc.Ptr: 8676 p.w(" -%sUintptr(", p.task.crt) 8677 p.castExpression(f, n.CastExpression, n.CastExpression.Operand.Type(), exprValue, flags) 8678 p.w(")") 8679 case isZeroReal(n.CastExpression.Operand): 8680 p.w(" -") 8681 defer p.w("%s", p.convert(n, n.CastExpression.Operand, t, flags)) 8682 p.w("%s%sFrom%[2]s(", p.task.crt, p.helperType(n, n.CastExpression.Operand.Type())) 8683 p.castExpression(f, n.CastExpression, n.CastExpression.Operand.Type(), exprValue, flags) 8684 p.w(")") 8685 case isNonNegativeInt(n.CastExpression.Operand) && isUnsigned(n.Operand.Type()): 8686 defer p.w("%s", p.convert(n, n.CastExpression.Operand, t, flags)) 8687 p.w("%sNeg%s(", p.task.crt, p.helperType(n, n.CastExpression.Operand.Type())) 8688 p.castExpression(f, n.CastExpression, n.CastExpression.Operand.Type(), exprValue, flags) 8689 p.w(")") 8690 default: 8691 defer p.w("%s", p.convert(n, n.Operand, t, flags)) 8692 p.w(" -") 8693 p.castExpression(f, n.CastExpression, n.Operand.Type(), exprValue, flags) 8694 } 8695 case cc.UnaryExpressionCpl: // '~' CastExpression 8696 defer p.w("%s", p.convert(n, n.Operand, t, flags)) 8697 switch { 8698 case n.CastExpression.Operand.Value() != nil: 8699 switch { 8700 case !t.IsIntegerType(): 8701 p.w(" ^") 8702 p.castExpression(f, n.CastExpression, n.Operand.Type(), exprValue, flags|fForceRuntimeConv) 8703 default: 8704 p.w("%sCpl%s(", p.task.crt, p.helperType(n, n.Operand.Type())) 8705 p.castExpression(f, n.CastExpression, n.Operand.Type(), exprValue, flags) 8706 p.w(")") 8707 } 8708 default: 8709 p.w(" ^") 8710 p.castExpression(f, n.CastExpression, n.Operand.Type(), exprValue, flags) 8711 } 8712 case cc.UnaryExpressionNot: // '!' CastExpression 8713 p.w("%sBool%s(!(", p.task.crt, p.helperType(n, t)) 8714 p.castExpression(f, n.CastExpression, n.CastExpression.Operand.Type(), exprBool, flags) 8715 p.w("))") 8716 case cc.UnaryExpressionSizeofExpr: // "sizeof" UnaryExpression 8717 p.checkSizeof(n.UnaryExpression, n.UnaryExpression.Operand.Type()) 8718 defer p.w("%s", p.convertNil(n, t, flags)) 8719 if d := n.UnaryExpression.Declarator(); d != nil { 8720 var isLocal bool 8721 if f != nil { 8722 if local := f.locals[d]; local != nil { 8723 isLocal = true 8724 if !local.isPinned { 8725 p.w("unsafe.Sizeof(%s)", local.name) 8726 return 8727 } 8728 } 8729 } 8730 8731 if !isLocal { 8732 if tld := p.tlds[d]; tld != nil { 8733 p.w("unsafe.Sizeof(%s)", tld.name) 8734 break 8735 } 8736 8737 nm := d.Name().String() 8738 if imp := p.imports[nm]; imp != nil { 8739 imp.used = true 8740 p.w("unsafe.Sizeof(%sX%s)", imp.qualifier, nm) 8741 break 8742 } 8743 } 8744 } 8745 8746 t := n.UnaryExpression.Operand.Type() 8747 if p.isArray(f, n.UnaryExpression, t) { 8748 p.w("%d", t.Len()*t.Elem().Size()) 8749 break 8750 } 8751 8752 s := "(0)" 8753 if !t.IsArithmeticType() { 8754 switch t.Kind() { 8755 case cc.Ptr: 8756 // ok 8757 case cc.Struct, cc.Union, cc.Array: 8758 s = "{}" 8759 default: 8760 panic(todo("", t.Kind())) 8761 } 8762 } 8763 switch t.Kind() { 8764 case cc.Int128, cc.UInt128: 8765 s = "{}" 8766 } 8767 p.w("unsafe.Sizeof(%s%s)", p.typ(n, t), s) 8768 case cc.UnaryExpressionSizeofType: // "sizeof" '(' TypeName ')' 8769 defer p.w("%s", p.convertNil(n, t, flags)) 8770 t := n.TypeName.Type() 8771 p.checkSizeof(n.TypeName, t) 8772 if t.Kind() == cc.Array { 8773 p.w("%d", t.Len()*t.Elem().Size()) 8774 break 8775 } 8776 8777 s := "(0)" 8778 if !t.IsArithmeticType() { 8779 switch t.Kind() { 8780 case cc.Ptr: 8781 // ok 8782 case cc.Struct, cc.Union: 8783 s = "{}" 8784 default: 8785 panic(todo("", t.Kind())) 8786 } 8787 } 8788 switch t.Kind() { 8789 case cc.Int128, cc.UInt128: 8790 s = "{}" 8791 } 8792 p.w("unsafe.Sizeof(%s%s)", p.typ(n, t), s) 8793 case cc.UnaryExpressionLabelAddr: // "&&" IDENTIFIER 8794 panic(todo("", n.Position())) 8795 case cc.UnaryExpressionAlignofExpr: // "_Alignof" UnaryExpression 8796 if n.TypeName.Type().Kind() == cc.Void { 8797 p.intConst(n, "", n.Operand, t, flags) 8798 break 8799 } 8800 8801 defer p.w("%s", p.convertNil(n, t, flags)) 8802 t := n.UnaryExpression.Operand.Type() 8803 if p.isArray(f, n.UnaryExpression, t) { 8804 p.w("%d", t.Len()*t.Elem().Size()) 8805 break 8806 } 8807 8808 s := "(0)" 8809 if !t.IsArithmeticType() { 8810 switch t.Kind() { 8811 case cc.Ptr: 8812 // ok 8813 case cc.Struct, cc.Union: 8814 s = "{}" 8815 default: 8816 panic(todo("", t.Kind())) 8817 } 8818 } 8819 p.w("unsafe.Alignof(%s%s)", p.typ(n, t), s) 8820 case cc.UnaryExpressionAlignofType: // "_Alignof" '(' TypeName ')' 8821 if n.TypeName.Type().Kind() == cc.Void { 8822 p.intConst(n, "", n.Operand, t, flags) 8823 break 8824 } 8825 8826 defer p.w("%s", p.convertNil(n, t, flags)) 8827 t := n.TypeName.Type() 8828 if t.Kind() == cc.Array { 8829 p.w("%d", t.Len()*t.Elem().Size()) 8830 break 8831 } 8832 8833 s := "(0)" 8834 if !t.IsArithmeticType() { 8835 switch t.Kind() { 8836 case cc.Ptr: 8837 // ok 8838 case cc.Struct, cc.Union: 8839 s = "{}" 8840 default: 8841 panic(todo("", t.Kind())) 8842 } 8843 } 8844 p.w("unsafe.Alignof(%s%s)", p.typ(n, t), s) 8845 case cc.UnaryExpressionImag: // "__imag__" UnaryExpression 8846 panic(todo("", n.Position())) 8847 case cc.UnaryExpressionReal: // "__real__" UnaryExpression 8848 panic(todo("", n.Position())) 8849 default: 8850 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 8851 } 8852 } 8853 8854 func (p *project) checkSizeof(n cc.Node, t cc.Type) { 8855 if !p.checkSizeof0(n, t) { 8856 p.err(n, "sizeof type %s: not supported", t.Alias()) 8857 } 8858 } 8859 8860 func (p *project) checkSizeof0(n cc.Node, t cc.Type) (ok bool) { 8861 switch t.Kind() { 8862 case cc.Array: 8863 return !t.IsVLA() 8864 case cc.Struct, cc.Union: 8865 nf := t.NumField() 8866 for i := []int{0}; i[0] < nf; i[0]++ { 8867 if !p.checkSizeof0(n, t.FieldByIndex(i).Type()) { 8868 return false 8869 } 8870 } 8871 } 8872 return true 8873 } 8874 8875 func (p *project) unaryExpressionLValue(f *function, n *cc.UnaryExpression, t cc.Type, mode exprMode, flags flags) { 8876 switch n.Case { 8877 case cc.UnaryExpressionPostfix: // PostfixExpression 8878 p.postfixExpression(f, n.PostfixExpression, t, mode, flags) 8879 case cc.UnaryExpressionInc: // "++" UnaryExpression 8880 panic(todo("", p.pos(n))) 8881 case cc.UnaryExpressionDec: // "--" UnaryExpression 8882 panic(todo("", p.pos(n))) 8883 case cc.UnaryExpressionAddrof: // '&' CastExpression 8884 panic(todo("", n.Position())) 8885 case cc.UnaryExpressionDeref: // '*' CastExpression 8886 ot := n.CastExpression.Operand.Type() 8887 switch ot.Kind() { 8888 case cc.Ptr, cc.Array: 8889 switch et := ot.Elem(); { 8890 case 8891 et.IsScalarType(), 8892 et.Kind() == cc.Struct, 8893 et.Kind() == cc.Union: 8894 8895 p.unaryExpressionDeref(f, n, t, mode, flags) 8896 default: 8897 panic(todo("", p.pos(n), et, et.Kind())) 8898 } 8899 default: 8900 panic(todo("", p.pos(n), ot, ot.Kind())) 8901 } 8902 case cc.UnaryExpressionPlus: // '+' CastExpression 8903 panic(todo("", n.Position())) 8904 case cc.UnaryExpressionMinus: // '-' CastExpression 8905 panic(todo("", n.Position())) 8906 case cc.UnaryExpressionCpl: // '~' CastExpression 8907 panic(todo("", n.Position())) 8908 case cc.UnaryExpressionNot: // '!' CastExpression 8909 panic(todo("", n.Position())) 8910 case cc.UnaryExpressionSizeofExpr: // "sizeof" UnaryExpression 8911 panic(todo("", n.Position())) 8912 case cc.UnaryExpressionSizeofType: // "sizeof" '(' TypeName ')' 8913 panic(todo("", n.Position())) 8914 case cc.UnaryExpressionLabelAddr: // "&&" IDENTIFIER 8915 panic(todo("", n.Position())) 8916 case cc.UnaryExpressionAlignofExpr: // "_Alignof" UnaryExpression 8917 panic(todo("", n.Position())) 8918 case cc.UnaryExpressionAlignofType: // "_Alignof" '(' TypeName ')' 8919 panic(todo("", n.Position())) 8920 case cc.UnaryExpressionImag: // "__imag__" UnaryExpression 8921 panic(todo("", n.Position())) 8922 case cc.UnaryExpressionReal: // "__real__" UnaryExpression 8923 panic(todo("", n.Position())) 8924 default: 8925 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 8926 } 8927 } 8928 8929 func isSigned(t cc.Type) bool { return t.IsIntegerType() && t.IsSignedType() } 8930 func isUnsigned(t cc.Type) bool { return t.IsIntegerType() && !t.IsSignedType() } 8931 8932 func isConstInteger(op cc.Operand) bool { 8933 switch op.Value().(type) { 8934 case cc.Int64Value, cc.Uint64Value: 8935 return true 8936 default: 8937 return false 8938 } 8939 } 8940 8941 func isNegativeInt(op cc.Operand) bool { 8942 switch x := op.Value().(type) { 8943 case cc.Int64Value: 8944 return x < 0 8945 default: 8946 return false 8947 } 8948 } 8949 8950 func isNonNegativeInt(op cc.Operand) bool { 8951 switch x := op.Value().(type) { 8952 case cc.Int64Value: 8953 return x >= 0 8954 case cc.Uint64Value: 8955 return true 8956 default: 8957 return false 8958 } 8959 } 8960 8961 func (p *project) unaryExpressionPreIncDec(f *function, n *cc.UnaryExpression, oper, oper2 string, t cc.Type, mode exprMode, flags flags) { 8962 // "++" UnaryExpression etc. 8963 switch mode { 8964 case exprValue: 8965 p.unaryExpressionPreIncDecValue(f, n, oper, oper2, t, mode, flags) 8966 case exprVoid: 8967 p.unaryExpressionPreIncDecVoid(f, n, oper, oper2, t, mode, flags) 8968 default: 8969 panic(todo("", p.pos(n), mode)) 8970 } 8971 } 8972 8973 func (p *project) unaryExpressionPreIncDecVoid(f *function, n *cc.UnaryExpression, oper, oper2 string, t cc.Type, mode exprMode, flags flags) { 8974 // "++" UnaryExpression etc. 8975 switch n.UnaryExpression.Operand.Type().Kind() { 8976 case cc.Int128, cc.UInt128: 8977 p.unaryExpressionLValue(f, n.UnaryExpression, n.UnaryExpression.Operand.Type(), exprLValue, 0) 8978 switch oper { 8979 case "++": 8980 p.w(".LValueInc()") 8981 case "--": 8982 p.w(".LValueDec()") 8983 default: 8984 panic(todo("internal error: %q", oper)) 8985 } 8986 return 8987 } 8988 8989 // "++" UnaryExpression etc. 8990 switch k := p.opKind(f, n.UnaryExpression, n.UnaryExpression.Operand.Type()); k { 8991 case opNormal: 8992 p.unaryExpressionPreIncDecVoidNormal(f, n, oper, oper2, t, mode, flags) 8993 case opArrayParameter: 8994 p.unaryExpressionPreIncDecVoidArrayParameter(f, n, oper, oper2, t, mode, flags) 8995 default: 8996 panic(todo("", n.Position(), k)) 8997 } 8998 } 8999 9000 func (p *project) unaryExpressionPreIncDecVoidArrayParameter(f *function, n *cc.UnaryExpression, oper, oper2 string, t cc.Type, mode exprMode, flags flags) { 9001 // "++" UnaryExpression etc. 9002 ut := n.UnaryExpression.Operand.Type() 9003 p.unaryExpression(f, n.UnaryExpression, n.UnaryExpression.Operand.Type(), exprLValue, flags) 9004 switch d := p.incDelta(n, ut); d { 9005 case 1: 9006 p.w("%s", oper) 9007 default: 9008 p.w("%s %d", oper2, d) 9009 } 9010 } 9011 9012 func (p *project) unaryExpressionPreIncDecVoidNormal(f *function, n *cc.UnaryExpression, oper, oper2 string, t cc.Type, mode exprMode, flags flags) { 9013 // "++" UnaryExpression etc. 9014 ut := n.UnaryExpression.Operand.Type() 9015 if d := n.UnaryExpression.Declarator(); d != nil && p.isVolatileOrAtomic(d) { 9016 x := "Dec" 9017 if oper == "++" { 9018 x = "Inc" 9019 } 9020 p.w("%sPre%sAtomic%s(&", p.task.crt, x, p.helperType(n, d.Type())) 9021 switch local, tld := f.locals[d], p.tlds[d]; { 9022 case local != nil: 9023 p.w("%s", local.name) 9024 case tld != nil: 9025 p.w("%s", tld.name) 9026 default: 9027 panic(todo("")) 9028 } 9029 p.w(", %d)", p.incDelta(n.PostfixExpression, ut)) 9030 return 9031 } 9032 9033 p.unaryExpression(f, n.UnaryExpression, n.UnaryExpression.Operand.Type(), exprLValue, flags) 9034 if ut.IsIntegerType() || ut.Kind() == cc.Ptr && p.incDelta(n, ut) == 1 { 9035 p.w("%s", oper) 9036 return 9037 } 9038 9039 switch ut.Kind() { 9040 case cc.Ptr, cc.Double, cc.Float: 9041 p.w("%s %d", oper2, p.incDelta(n, ut)) 9042 return 9043 } 9044 9045 panic(todo("", p.pos(n))) 9046 } 9047 9048 func (p *project) unaryExpressionPreIncDecValue(f *function, n *cc.UnaryExpression, oper, oper2 string, t cc.Type, mode exprMode, flags flags) { 9049 // "++" UnaryExpression etc. 9050 switch k := p.opKind(f, n.UnaryExpression, n.UnaryExpression.Operand.Type()); k { 9051 case opNormal: 9052 p.unaryExpressionPreIncDecValueNormal(f, n, oper, oper2, t, mode, flags) 9053 default: 9054 panic(todo("", n.Position(), k)) 9055 } 9056 } 9057 9058 func (p *project) unaryExpressionPreIncDecValueNormal(f *function, n *cc.UnaryExpression, oper, oper2 string, t cc.Type, mode exprMode, flags flags) { 9059 // "++" UnaryExpression etc. 9060 defer p.w("%s", p.convert(n, n.UnaryExpression.Operand, t, flags)) 9061 x := "Dec" 9062 if oper == "++" { 9063 x = "Inc" 9064 } 9065 ut := n.UnaryExpression.Operand.Type() 9066 p.w("%sPre%s%s(&", p.task.crt, x, p.helperType(n, ut)) 9067 p.unaryExpression(f, n.UnaryExpression, ut, exprLValue, flags) 9068 p.w(", %d)", p.incDelta(n.PostfixExpression, ut)) 9069 } 9070 9071 func (p *project) unaryExpressionDeref(f *function, n *cc.UnaryExpression, t cc.Type, mode exprMode, flags flags) { 9072 // '*' CastExpression 9073 switch mode { 9074 case exprValue: 9075 p.unaryExpressionDerefValue(f, n, t, mode, flags) 9076 case exprLValue: 9077 p.unaryExpressionDerefLValue(f, n, t, mode, flags) 9078 case exprAddrOf: 9079 p.unaryExpressionDerefAddrOf(f, n, t, mode, flags) 9080 case exprBool: 9081 p.unaryExpressionDerefBool(f, n, t, mode, flags) 9082 default: 9083 panic(todo("", n.Position(), mode)) 9084 } 9085 } 9086 9087 func (p *project) unaryExpressionDerefBool(f *function, n *cc.UnaryExpression, t cc.Type, mode exprMode, flags flags) { 9088 // '*' CastExpression 9089 p.w("(") 9090 defer p.w(")") 9091 p.w("*(*%s)(unsafe.Pointer(", p.typ(n, n.Operand.Type())) 9092 p.castExpression(f, n.CastExpression, n.CastExpression.Operand.Type(), exprValue, flags) 9093 p.w(")) != 0") 9094 } 9095 9096 func (p *project) unaryExpressionDerefAddrOf(f *function, n *cc.UnaryExpression, t cc.Type, mode exprMode, flags flags) { 9097 // '*' CastExpression 9098 p.castExpression(f, n.CastExpression, n.CastExpression.Operand.Type(), exprValue, flags) 9099 } 9100 9101 func (p *project) unaryExpressionDerefLValue(f *function, n *cc.UnaryExpression, t cc.Type, mode exprMode, flags flags) { 9102 // '*' CastExpression 9103 switch k := p.opKind(f, n.CastExpression, n.CastExpression.Operand.Type()); k { 9104 case opNormal: 9105 p.unaryExpressionDerefLValueNormal(f, n, t, mode, flags) 9106 case opArray: 9107 panic(todo("", p.pos(n))) 9108 p.unaryExpressionDerefLValueArray(f, n, t, mode, flags) 9109 case opArrayParameter: 9110 p.unaryExpressionDerefLValueNormal(f, n, t, mode, flags) 9111 default: 9112 panic(todo("", n.Position(), k)) 9113 } 9114 } 9115 9116 func (p *project) unaryExpressionDerefLValueArray(f *function, n *cc.UnaryExpression, t cc.Type, mode exprMode, flags flags) { 9117 defer p.w("))%s", p.convertType(n, n.CastExpression.Operand.Type().Elem(), t, flags)) 9118 p.w("*(*%s)(unsafe.Pointer(", p.typ(n, n.Operand.Type())) 9119 p.castExpression(f, n.CastExpression, n.CastExpression.Operand.Type(), exprValue, flags) 9120 } 9121 9122 func (p *project) unaryExpressionDerefLValueNormal(f *function, n *cc.UnaryExpression, t cc.Type, mode exprMode, flags flags) { 9123 defer p.w("))%s", p.convertType(n, n.CastExpression.Operand.Type().Elem(), t, flags)) 9124 p.w("*(*%s)(unsafe.Pointer(", p.typ(n, n.Operand.Type())) 9125 p.castExpression(f, n.CastExpression, n.CastExpression.Operand.Type(), exprValue, flags) 9126 } 9127 9128 func (p *project) unaryExpressionDerefValue(f *function, n *cc.UnaryExpression, t cc.Type, mode exprMode, flags flags) { 9129 // '*' CastExpression 9130 switch k := p.opKind(f, n.CastExpression, n.CastExpression.Operand.Type()); k { 9131 case opNormal, opArrayParameter: 9132 p.unaryExpressionDerefValueNormal(f, n, t, mode, flags) 9133 case opArray: 9134 p.unaryExpressionDerefValueArray(f, n, t, mode, flags) 9135 default: 9136 panic(todo("", n.Position(), k)) 9137 } 9138 } 9139 9140 func (p *project) unaryExpressionDerefValueArray(f *function, n *cc.UnaryExpression, t cc.Type, mode exprMode, flags flags) { 9141 defer p.w("%s", p.convertType(n, n.CastExpression.Operand.Type().Elem(), t, flags)) 9142 p.castExpression(f, n.CastExpression, n.CastExpression.Operand.Type(), exprValue, flags) 9143 p.w("[0]") 9144 } 9145 9146 func (p *project) unaryExpressionDerefValueNormal(f *function, n *cc.UnaryExpression, t cc.Type, mode exprMode, flags flags) { 9147 // '*' CastExpression 9148 switch op := n.Operand.Type(); { 9149 case op.Kind() == cc.Array: 9150 p.castExpression(f, n.CastExpression, n.CastExpression.Operand.Type(), mode, flags) 9151 default: 9152 defer p.w("))%s", p.convertType(n, n.CastExpression.Operand.Type().Elem(), t, flags)) 9153 p.w("*(*%s)(unsafe.Pointer(", p.typ(n, n.Operand.Type())) 9154 p.castExpression(f, n.CastExpression, n.CastExpression.Operand.Type(), mode, flags) 9155 } 9156 } 9157 9158 func (p *project) postfixExpression(f *function, n *cc.PostfixExpression, t cc.Type, mode exprMode, flags flags) { 9159 switch mode { 9160 case exprLValue: 9161 p.postfixExpressionLValue(f, n, t, mode, flags) 9162 case exprValue: 9163 p.postfixExpressionValue(f, n, t, mode, flags) 9164 case exprVoid: 9165 p.postfixExpressionVoid(f, n, t, mode, flags) 9166 case exprFunc: 9167 p.postfixExpressionFunc(f, n, t, mode, flags) 9168 case exprAddrOf: 9169 p.postfixExpressionAddrOf(f, n, t, mode, flags) 9170 case exprSelect: 9171 p.postfixExpressionSelect(f, n, t, mode, flags) 9172 case exprPSelect: 9173 p.postfixExpressionPSelect(f, n, t, mode, flags) 9174 case exprBool: 9175 p.postfixExpressionBool(f, n, t, mode, flags) 9176 case exprDecay: 9177 p.postfixExpressionDecay(f, n, t, mode, flags) 9178 default: 9179 panic(todo("", n.Position(), mode)) 9180 } 9181 } 9182 9183 func (p *project) postfixExpressionDecay(f *function, n *cc.PostfixExpression, t cc.Type, mode exprMode, flags flags) { 9184 switch n.Case { 9185 case cc.PostfixExpressionPrimary: // PrimaryExpression 9186 p.primaryExpression(f, n.PrimaryExpression, t, mode, flags) 9187 case cc.PostfixExpressionIndex: // PostfixExpression '[' Expression ']' 9188 defer p.w("%s", p.convert(n, n.Operand, t, flags)) 9189 pe := n.PostfixExpression.Operand.Type() 9190 p.w("(") 9191 switch { 9192 case pe.Kind() == cc.Array: 9193 p.postfixExpression(f, n.PostfixExpression, pe, exprDecay, flags) 9194 case pe.Kind() == cc.Ptr: 9195 p.postfixExpression(f, n.PostfixExpression, pe, exprValue, flags) 9196 default: 9197 panic(todo("", p.pos(n))) 9198 } 9199 if !n.Expression.Operand.IsZero() { 9200 p.nzUintptr(n, func() { p.expression(f, n.Expression, n.Expression.Operand.Type(), exprValue, flags) }, n.Expression.Operand) 9201 if sz := pe.Elem().Size(); sz != 1 { 9202 p.w("*%d", sz) 9203 } 9204 } 9205 p.w(")") 9206 case cc.PostfixExpressionCall: // PostfixExpression '(' ArgumentExpressionList ')' 9207 panic(todo("", p.pos(n))) 9208 case cc.PostfixExpressionSelect: // PostfixExpression '.' IDENTIFIER 9209 p.postfixExpression(f, n, t, exprAddrOf, flags) 9210 case cc.PostfixExpressionPSelect: // PostfixExpression "->" IDENTIFIER 9211 p.postfixExpression(f, n, t, exprAddrOf, flags) 9212 case cc.PostfixExpressionInc: // PostfixExpression "++" 9213 panic(todo("", p.pos(n))) 9214 case cc.PostfixExpressionDec: // PostfixExpression "--" 9215 panic(todo("", p.pos(n))) 9216 case cc.PostfixExpressionComplit: // '(' TypeName ')' '{' InitializerList ',' '}' 9217 panic(todo("", p.pos(n))) 9218 case cc.PostfixExpressionTypeCmp: // "__builtin_types_compatible_p" '(' TypeName ',' TypeName ')' 9219 panic(todo("", p.pos(n))) 9220 case cc.PostfixExpressionChooseExpr: 9221 panic(todo("", p.pos(n))) 9222 default: 9223 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 9224 } 9225 } 9226 9227 func (p *project) postfixExpressionBool(f *function, n *cc.PostfixExpression, t cc.Type, mode exprMode, flags flags) { 9228 switch n.Case { 9229 case cc.PostfixExpressionPrimary: // PrimaryExpression 9230 p.primaryExpression(f, n.PrimaryExpression, t, mode, flags) 9231 case cc.PostfixExpressionIndex: // PostfixExpression '[' Expression ']' 9232 p.w("(") 9233 defer p.w(")") 9234 defer p.w(" != 0") 9235 p.postfixExpression(f, n, t, exprValue, flags) 9236 case cc.PostfixExpressionCall: // PostfixExpression '(' ArgumentExpressionList ')' 9237 p.postfixExpressionCall(f, n, t, mode, flags) 9238 case cc.PostfixExpressionSelect: // PostfixExpression '.' IDENTIFIER 9239 p.w("(") 9240 defer p.w(")") 9241 defer p.w(" != 0") 9242 p.postfixExpression(f, n, t, exprValue, flags) 9243 case cc.PostfixExpressionPSelect: // PostfixExpression "->" IDENTIFIER 9244 p.w("(") 9245 defer p.w(")") 9246 defer p.w(" != 0") 9247 p.postfixExpression(f, n, t, exprValue, flags) 9248 case cc.PostfixExpressionInc: // PostfixExpression "++" 9249 p.w("(") 9250 defer p.w(")") 9251 defer p.w(" != 0") 9252 p.postfixExpression(f, n, t, exprValue, flags) 9253 case cc.PostfixExpressionDec: // PostfixExpression "--" 9254 p.w("(") 9255 defer p.w(")") 9256 defer p.w(" != 0") 9257 p.postfixExpression(f, n, t, exprValue, flags) 9258 case cc.PostfixExpressionComplit: // '(' TypeName ')' '{' InitializerList ',' '}' 9259 panic(todo("", p.pos(n))) 9260 case cc.PostfixExpressionTypeCmp: // "__builtin_types_compatible_p" '(' TypeName ',' TypeName ')' 9261 panic(todo("", p.pos(n))) 9262 case cc.PostfixExpressionChooseExpr: 9263 p.w("(") 9264 defer p.w(")") 9265 defer p.w(" != 0") 9266 p.postfixExpression(f, n, t, exprValue, flags) 9267 default: 9268 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 9269 } 9270 } 9271 9272 func (p *project) postfixExpressionPSelect(f *function, n *cc.PostfixExpression, t cc.Type, mode exprMode, flags flags) { 9273 // PostfixExpression "->" IDENTIFIER 9274 switch n.Case { 9275 case cc.PostfixExpressionPrimary: // PrimaryExpression 9276 p.primaryExpression(f, n.PrimaryExpression, t, mode, flags) 9277 case cc.PostfixExpressionIndex: // PostfixExpression '[' Expression ']' 9278 p.postfixExpressionPSelectIndex(f, n, t, mode, flags) 9279 case cc.PostfixExpressionCall: // PostfixExpression '(' ArgumentExpressionList ')' 9280 p.postfixExpressionPSelectCall(f, n, t, mode, flags) 9281 case cc.PostfixExpressionSelect: // PostfixExpression '.' IDENTIFIER 9282 p.postfixExpressionPSelectSelect(f, n, t, mode, flags) 9283 case cc.PostfixExpressionPSelect: // PostfixExpression "->" IDENTIFIER 9284 p.postfixExpressionPSelectPSelect(f, n, t, mode, flags) 9285 case cc.PostfixExpressionInc: // PostfixExpression "++" 9286 panic(todo("", p.pos(n))) 9287 case cc.PostfixExpressionDec: // PostfixExpression "--" 9288 panic(todo("", p.pos(n))) 9289 case cc.PostfixExpressionComplit: // '(' TypeName ')' '{' InitializerList ',' '}' 9290 panic(todo("", p.pos(n))) 9291 case cc.PostfixExpressionTypeCmp: // "__builtin_types_compatible_p" '(' TypeName ',' TypeName ')' 9292 panic(todo("", p.pos(n))) 9293 case cc.PostfixExpressionChooseExpr: 9294 panic(todo("", p.pos(n))) 9295 default: 9296 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 9297 } 9298 } 9299 9300 func (p *project) postfixExpressionPSelectSelect(f *function, n *cc.PostfixExpression, t cc.Type, mode exprMode, flags flags) { 9301 // PostfixExpression '.' IDENTIFIER 9302 switch k := p.opKind(f, n.PostfixExpression, n.PostfixExpression.Operand.Type()); k { 9303 case opStruct: 9304 p.postfixExpressionPSelectSelectStruct(f, n, t, mode, flags) 9305 case opUnion: 9306 p.postfixExpressionPSelectSelectUnion(f, n, t, mode, flags) 9307 default: 9308 panic(todo("", n.Position(), k)) 9309 } 9310 } 9311 9312 func (p *project) postfixExpressionPSelectSelectUnion(f *function, n *cc.PostfixExpression, t cc.Type, mode exprMode, flags flags) { 9313 // PostfixExpression '.' IDENTIFIER 9314 fld := n.Field 9315 if fld.Offset() != 0 { 9316 p.err(&n.Token2, "internal error, union field with non-zero offset: %s %v", n.Token2.Value, fld.Offset()) 9317 } 9318 switch { 9319 case n.Operand.Type().IsBitFieldType(): 9320 panic(todo("", p.pos(n))) 9321 default: 9322 if fld.IsBitField() { 9323 p.err(&n.Token2, "internal error, wrong function for accessing a bit field: %s", n.Token2.Value) 9324 } 9325 pe := n.PostfixExpression.Operand.Type() 9326 defer p.w("%s", p.convert(n, n.Operand, t, flags)) 9327 p.w("(*(**%s)(unsafe.Pointer(", p.typ(n, n.Operand.Type().Elem())) 9328 p.postfixExpression(f, n.PostfixExpression, pe, exprAddrOf, flags) 9329 p.w("/* .%s */", p.fieldName(n, n.Token2.Value)) 9330 p.w(")))") 9331 } 9332 } 9333 9334 func (p *project) postfixExpressionPSelectSelectStruct(f *function, n *cc.PostfixExpression, t cc.Type, mode exprMode, flags flags) { 9335 // PostfixExpression '.' IDENTIFIER 9336 fld := n.Field 9337 switch { 9338 case n.Operand.Type().IsBitFieldType(): 9339 panic(todo("", p.pos(n))) 9340 default: 9341 if fld.IsBitField() { 9342 p.err(&n.Token2, "internal error, wrong function for accessing a bit field: %s", n.Token2.Value) 9343 } 9344 pe := n.PostfixExpression.Operand.Type() 9345 p.w("(*%s)(unsafe.Pointer(", p.typ(n, t.Elem())) 9346 p.postfixExpression(f, n.PostfixExpression, pe, exprSelect, flags) 9347 p.w(".%s", p.fieldName(n, n.Token2.Value)) 9348 p.w("))") 9349 9350 } 9351 } 9352 9353 func (p *project) postfixExpressionPSelectCall(f *function, n *cc.PostfixExpression, t cc.Type, mode exprMode, flags flags) { 9354 p.w("(*%s)(unsafe.Pointer(", p.typ(n, n.Operand.Type().Elem())) 9355 p.postfixExpressionCall(f, n, t, exprValue, flags) 9356 p.w("))") 9357 } 9358 9359 func (p *project) postfixExpressionPSelectIndex(f *function, n *cc.PostfixExpression, t cc.Type, mode exprMode, flags flags) { 9360 // PostfixExpression '[' Expression ']' 9361 switch k := p.opKind(f, n.PostfixExpression, n.PostfixExpression.Operand.Type()); k { 9362 // case opArray: 9363 // p.postfixExpressionSelectIndexArray(f, n, t, mode, flags) 9364 case opNormal: 9365 p.postfixExpressionPSelectIndexNormal(f, n, t, mode, flags) 9366 case opArrayParameter: 9367 p.postfixExpressionSelectIndexArrayParamater(f, n, t, mode, flags) 9368 default: 9369 panic(todo("", n.Position(), k)) 9370 } 9371 } 9372 9373 func (p *project) postfixExpressionPSelectIndexNormal(f *function, n *cc.PostfixExpression, t cc.Type, mode exprMode, flags flags) { 9374 pe := n.PostfixExpression.Operand.Type() 9375 // PostfixExpression '[' Expression ']' 9376 switch { 9377 case n.Operand.Type().IsBitFieldType(): 9378 panic(todo("", p.pos(n))) 9379 case n.Operand.Type().Kind() == cc.Array: 9380 panic(todo("", p.pos(n))) 9381 case pe.Kind() == cc.Array: 9382 p.w("(") 9383 defer p.w(")") 9384 p.w("(*(**%s)(unsafe.Pointer(", p.typ(n, n.Operand.Type().Elem())) 9385 p.postfixExpression(f, n.PostfixExpression, pe, exprAddrOf, flags) 9386 if !n.Expression.Operand.IsZero() { 9387 p.nzUintptr(n, func() { p.expression(f, n.Expression, n.Expression.Operand.Type(), exprValue, flags) }, n.Expression.Operand) 9388 if sz := pe.Decay().Elem().Size(); sz != 1 { 9389 p.w("*%d", sz) 9390 } 9391 } 9392 p.w(")))") 9393 default: 9394 p.w("(") 9395 defer p.w(")") 9396 p.w("(*(**%s)(unsafe.Pointer(", p.typ(n, n.Operand.Type().Elem())) 9397 p.postfixExpression(f, n.PostfixExpression, pe, exprValue, flags) 9398 if !n.Expression.Operand.IsZero() { 9399 p.nzUintptr(n, func() { p.expression(f, n.Expression, n.Expression.Operand.Type(), exprValue, flags) }, n.Expression.Operand) 9400 if sz := pe.Decay().Elem().Size(); sz != 1 { 9401 p.w("*%d", sz) 9402 } 9403 } 9404 p.w(")))") 9405 } 9406 } 9407 9408 func (p *project) postfixExpressionSelect(f *function, n *cc.PostfixExpression, t cc.Type, mode exprMode, flags flags) { 9409 // PostfixExpression '.' IDENTIFIER 9410 switch n.Case { 9411 case cc.PostfixExpressionPrimary: // PrimaryExpression 9412 p.primaryExpression(f, n.PrimaryExpression, t, mode, flags) 9413 case cc.PostfixExpressionIndex: // PostfixExpression '[' Expression ']' 9414 p.postfixExpressionSelectIndex(f, n, t, mode, flags) 9415 case cc.PostfixExpressionCall: // PostfixExpression '(' ArgumentExpressionList ')' 9416 p.postfixExpression(f, n, t, exprValue, flags) 9417 case cc.PostfixExpressionSelect: // PostfixExpression '.' IDENTIFIER 9418 p.postfixExpressionSelectSelect(f, n, t, mode, flags) 9419 case cc.PostfixExpressionPSelect: // PostfixExpression "->" IDENTIFIER 9420 p.postfixExpressionSelectPSelect(f, n, t, mode, flags) 9421 case cc.PostfixExpressionInc: // PostfixExpression "++" 9422 panic(todo("", p.pos(n))) 9423 case cc.PostfixExpressionDec: // PostfixExpression "--" 9424 panic(todo("", p.pos(n))) 9425 case cc.PostfixExpressionComplit: // '(' TypeName ')' '{' InitializerList ',' '}' 9426 panic(todo("", p.pos(n))) 9427 case cc.PostfixExpressionTypeCmp: // "__builtin_types_compatible_p" '(' TypeName ',' TypeName ')' 9428 panic(todo("", p.pos(n))) 9429 case cc.PostfixExpressionChooseExpr: 9430 panic(todo("", p.pos(n))) 9431 default: 9432 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 9433 } 9434 } 9435 9436 func (p *project) postfixExpressionPSelectPSelect(f *function, n *cc.PostfixExpression, t cc.Type, mode exprMode, flags flags) { 9437 // PostfixExpression "->" IDENTIFIER 9438 switch k := p.opKind(f, n.PostfixExpression, n.PostfixExpression.Operand.Type().Elem()); k { 9439 case opStruct: 9440 p.postfixExpressionPSelectPSelectStruct(f, n, t, mode, flags) 9441 default: 9442 panic(todo("", n.Position(), k)) 9443 } 9444 } 9445 9446 func (p *project) postfixExpressionPSelectPSelectStruct(f *function, n *cc.PostfixExpression, t cc.Type, mode exprMode, flags flags) { 9447 // PostfixExpression "->" IDENTIFIER 9448 fld := n.Field 9449 switch { 9450 case n.Operand.Type().IsBitFieldType(): 9451 panic(todo("", p.pos(n))) 9452 default: 9453 if fld.IsBitField() { 9454 p.err(&n.Token2, "internal error, wrong function for accessing a bit field: %s", n.Token2.Value) 9455 } 9456 pe := n.PostfixExpression.Operand.Type() 9457 defer p.w("%s", p.convert(n, n.Operand, t, flags)) 9458 p.w("(*%s)(unsafe.Pointer(", p.typ(n, t.Elem())) 9459 p.postfixExpression(f, n.PostfixExpression, pe, exprPSelect, flags) 9460 p.w(".%s", p.fieldName(n, n.Token2.Value)) 9461 p.w("))") 9462 } 9463 } 9464 9465 func (p *project) postfixExpressionSelectPSelect(f *function, n *cc.PostfixExpression, t cc.Type, mode exprMode, flags flags) { 9466 // PostfixExpression "->" IDENTIFIER 9467 switch k := p.opKind(f, n.PostfixExpression, n.PostfixExpression.Operand.Type().Elem()); k { 9468 case opStruct: 9469 p.postfixExpressionSelectPSelectStruct(f, n, t, mode, flags) 9470 case opUnion: 9471 p.postfixExpressionSelectPSelectUnion(f, n, t, mode, flags) 9472 default: 9473 panic(todo("", n.Position(), k)) 9474 } 9475 } 9476 9477 func (p *project) postfixExpressionSelectPSelectUnion(f *function, n *cc.PostfixExpression, t cc.Type, mode exprMode, flags flags) { 9478 // PostfixExpression "->" IDENTIFIER 9479 fld := n.Field 9480 if fld.Offset() != 0 { 9481 p.err(&n.Token2, "internal error, union field with non-zero offset: %s %v", n.Token2.Value, fld.Offset()) 9482 } 9483 switch { 9484 case n.Operand.Type().IsBitFieldType(): 9485 panic(todo("", p.pos(n))) 9486 case n.Operand.Type().Kind() == cc.Array: 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, n.Operand.Type())) 9495 p.postfixExpression(f, n.PostfixExpression, pe, exprValue, flags) 9496 p.w("))") 9497 } 9498 } 9499 9500 func (p *project) postfixExpressionSelectPSelectStruct(f *function, n *cc.PostfixExpression, t cc.Type, mode exprMode, flags flags) { 9501 // PostfixExpression "->" IDENTIFIER 9502 fld := n.Field 9503 switch { 9504 case n.Operand.Type().IsBitFieldType(): 9505 panic(todo("", p.pos(n))) 9506 default: 9507 if fld.IsBitField() { 9508 p.err(&n.Token2, "internal error, wrong function for accessing a bit field: %s", n.Token2.Value) 9509 } 9510 pe := n.PostfixExpression.Operand.Type() 9511 defer p.w("%s", p.convert(n, n.Operand, t, flags)) 9512 et := n.PostfixExpression.Operand.Type().Elem() 9513 fld, path, ok := et.FieldByName2(n.Token2.Value) 9514 switch { 9515 case !ok: 9516 panic(todo("", n.Token.Position())) 9517 case fld.InUnion(): 9518 p.w("(*(*%s)(unsafe.Pointer(", p.typ(n, n.Operand.Type())) 9519 p.postfixExpression(f, n.PostfixExpression, pe, exprValue, flags) 9520 p.w("%s)))", nonZeroUintptr(pathOff(et, path))) 9521 case len(path) != 1: 9522 panic(todo("", n.Token.Position())) 9523 default: 9524 p.w("(*%s)(unsafe.Pointer(", p.typ(n, pe.Elem())) 9525 switch { 9526 case pe.Kind() == cc.Array: 9527 p.postfixExpression(f, n.PostfixExpression, pe, exprAddrOf, flags) 9528 default: 9529 p.postfixExpression(f, n.PostfixExpression, pe, exprValue, flags) 9530 } 9531 p.w(")).%s", p.fieldName(n, n.Token2.Value)) 9532 } 9533 } 9534 } 9535 9536 func (p *project) postfixExpressionSelectSelect(f *function, n *cc.PostfixExpression, t cc.Type, mode exprMode, flags flags) { 9537 // PostfixExpression '.' IDENTIFIER 9538 switch k := p.structOrUnion(n); k { 9539 case opUnion: 9540 p.postfixExpressionSelectSelectUnion(f, n, t, mode, flags) 9541 case opStruct: 9542 p.postfixExpressionSelectSelectStruct(f, n, t, mode, flags) 9543 default: 9544 panic(todo("", n.Position(), k)) 9545 } 9546 } 9547 9548 func (p *project) structOrUnion(n *cc.PostfixExpression) opKind { 9549 t := n.PostfixExpression.Operand.Type() 9550 switch n.Case { 9551 case cc.PostfixExpressionSelect: // PostfixExpression '.' IDENTIFIER 9552 // ok 9553 case cc.PostfixExpressionPSelect: // PostfixExpression "->" IDENTIFIER 9554 if t.Kind() == cc.Ptr { 9555 t = t.Elem() 9556 break 9557 } 9558 9559 p.err(n, "expected pointer type: %s", t) 9560 return opStruct 9561 } 9562 f, path, ok := t.FieldByName2(n.Token2.Src) 9563 if !ok { 9564 p.err(&n.Token, "unknown field: %s", n.Token2) 9565 return opStruct 9566 } 9567 9568 for len(path) > 1 { 9569 f = t.FieldByIndex(path[:1]) 9570 path = path[1:] 9571 t = f.Type() 9572 } 9573 if t.Kind() == cc.Union { 9574 // trc("%v: %q %v", n.Token2.Position(), n.Token2.Src, opUnion) 9575 return opUnion 9576 } 9577 9578 // trc("%v: %q %v", n.Token2.Position(), n.Token2.Src, opStruct) 9579 return opStruct 9580 } 9581 9582 func (p *project) postfixExpressionSelectSelectStruct(f *function, n *cc.PostfixExpression, t cc.Type, mode exprMode, flags flags) { 9583 // PostfixExpression '.' IDENTIFIER 9584 fld := n.Field 9585 switch { 9586 case n.Operand.Type().IsBitFieldType(): 9587 panic(todo("", p.pos(n))) 9588 case n.Operand.Type().Kind() == cc.Array: 9589 panic(todo("", p.pos(n))) 9590 default: 9591 if fld.IsBitField() { 9592 p.err(&n.Token2, "internal error, wrong function for accessing a bit field: %s", n.Token2.Value) 9593 } 9594 pe := n.PostfixExpression.Operand.Type() 9595 p.postfixExpression(f, n.PostfixExpression, pe, exprSelect, flags) 9596 p.w(".%s", p.fieldName(n, n.Token2.Value)) 9597 } 9598 } 9599 9600 func (p *project) postfixExpressionSelectSelectUnion(f *function, n *cc.PostfixExpression, t cc.Type, mode exprMode, flags flags) { 9601 // PostfixExpression '.' IDENTIFIER 9602 fld := n.Field 9603 if fld.Offset() != 0 { 9604 p.err(&n.Token2, "internal error, union field with non-zero offset: %s %v", n.Token2.Value, fld.Offset()) 9605 } 9606 switch { 9607 case n.Operand.Type().IsBitFieldType(): 9608 panic(todo("", p.pos(n))) 9609 case n.Operand.Type().Kind() == cc.Array: 9610 panic(todo("", p.pos(n))) 9611 default: 9612 if fld.IsBitField() { 9613 p.err(&n.Token2, "internal error, wrong function for accessing a bit field: %s", n.Token2.Value) 9614 } 9615 pe := n.PostfixExpression.Operand.Type() 9616 defer p.w("%s", p.convert(n, n.Operand, t, flags)) 9617 p.w("(*%s)(unsafe.Pointer(", p.typ(n, n.Operand.Type())) 9618 p.postfixExpression(f, n.PostfixExpression, pe, exprAddrOf, flags) 9619 p.w("))") 9620 } 9621 } 9622 9623 func (p *project) postfixExpressionSelectIndex(f *function, n *cc.PostfixExpression, t cc.Type, mode exprMode, flags flags) { 9624 // PostfixExpression '[' Expression ']' 9625 switch k := p.opKind(f, n.PostfixExpression, n.PostfixExpression.Operand.Type()); k { 9626 case opArray: 9627 p.postfixExpressionSelectIndexArray(f, n, t, mode, flags) 9628 case opNormal: 9629 p.postfixExpressionSelectIndexNormal(f, n, t, mode, flags) 9630 case opArrayParameter: 9631 p.postfixExpressionSelectIndexArrayParamater(f, n, t, mode, flags) 9632 default: 9633 panic(todo("", n.Position(), k)) 9634 } 9635 } 9636 9637 func (p *project) postfixExpressionSelectIndexArrayParamater(f *function, n *cc.PostfixExpression, t cc.Type, mode exprMode, flags flags) { 9638 pe := n.PostfixExpression.Operand.Type() 9639 // PostfixExpression '[' Expression ']' 9640 switch { 9641 case n.Operand.Type().IsBitFieldType(): 9642 panic(todo("", p.pos(n))) 9643 case n.Operand.Type().Kind() == cc.Array: 9644 panic(todo("", p.pos(n))) 9645 default: 9646 p.w("(*%s)(unsafe.Pointer(", p.typ(n, pe.Elem())) 9647 p.postfixExpression(f, n.PostfixExpression, pe, exprValue, flags) 9648 if !n.Expression.Operand.IsZero() { 9649 p.nzUintptr(n, func() { p.expression(f, n.Expression, n.Expression.Operand.Type(), exprValue, flags) }, n.Expression.Operand) 9650 if sz := pe.Decay().Elem().Size(); sz != 1 { 9651 p.w("*%d", sz) 9652 } 9653 } 9654 p.w("))") 9655 } 9656 } 9657 9658 func (p *project) postfixExpressionSelectIndexNormal(f *function, n *cc.PostfixExpression, t cc.Type, mode exprMode, flags flags) { 9659 pe := n.PostfixExpression.Operand.Type() 9660 // PostfixExpression '[' Expression ']' 9661 switch { 9662 case n.Operand.Type().IsBitFieldType(): 9663 panic(todo("", p.pos(n))) 9664 case n.Operand.Type().Kind() == cc.Array: 9665 panic(todo("", p.pos(n))) 9666 case pe.Kind() != cc.Ptr: 9667 p.w("(*%s)(unsafe.Pointer(", p.typ(n, pe.Elem())) 9668 p.postfixExpression(f, n.PostfixExpression, pe, exprAddrOf, flags) 9669 if !n.Expression.Operand.IsZero() { 9670 p.nzUintptr(n, func() { p.expression(f, n.Expression, n.Expression.Operand.Type(), exprValue, flags) }, n.Expression.Operand) 9671 if sz := pe.Decay().Elem().Size(); sz != 1 { 9672 p.w("*%d", sz) 9673 } 9674 } 9675 p.w("))") 9676 default: 9677 p.w("(*%s)(unsafe.Pointer(", p.typ(n, pe.Elem())) 9678 p.postfixExpression(f, n.PostfixExpression, pe, exprValue, flags) 9679 if !n.Expression.Operand.IsZero() { 9680 p.nzUintptr(n, func() { p.expression(f, n.Expression, n.Expression.Operand.Type(), exprValue, flags) }, n.Expression.Operand) 9681 if sz := pe.Decay().Elem().Size(); sz != 1 { 9682 p.w("*%d", sz) 9683 } 9684 } 9685 p.w("))") 9686 } 9687 } 9688 9689 func (p *project) postfixExpressionSelectIndexArray(f *function, n *cc.PostfixExpression, t cc.Type, mode exprMode, flags flags) { 9690 // PostfixExpression '[' Expression ']' 9691 switch { 9692 case n.Operand.Type().IsBitFieldType(): 9693 panic(todo("", p.pos(n))) 9694 case n.Operand.Type().Kind() == cc.Array: 9695 panic(todo("", p.pos(n))) 9696 default: 9697 pe := n.PostfixExpression.Operand.Type() 9698 p.postfixExpression(f, n.PostfixExpression, pe, mode, flags) 9699 p.w("[") 9700 p.expression(f, n.Expression, n.Expression.Operand.Type(), exprValue, flags) 9701 p.w("]") 9702 } 9703 } 9704 9705 func (p *project) postfixExpressionAddrOf(f *function, n *cc.PostfixExpression, t cc.Type, mode exprMode, flags flags) { 9706 switch n.Case { 9707 case cc.PostfixExpressionPrimary: // PrimaryExpression 9708 p.primaryExpression(f, n.PrimaryExpression, t, mode, flags) 9709 case cc.PostfixExpressionIndex: // PostfixExpression '[' Expression ']' 9710 p.postfixExpressionAddrOfIndex(f, n, t, mode, flags) 9711 case cc.PostfixExpressionCall: // PostfixExpression '(' ArgumentExpressionList ')' 9712 ot := n.Operand.Type() 9713 switch ot.Kind() { 9714 case cc.Struct, cc.Union: 9715 // ok 9716 default: 9717 p.err(n, "cannot take address of value of type %v", n.Operand.Type()) 9718 return 9719 } 9720 9721 if p.pass1 { 9722 off := roundup(f.off, uintptr(ot.Align())) 9723 f.complits[n] = off 9724 f.off += ot.Size() 9725 return 9726 } 9727 9728 off := f.complits[n] 9729 p.w("func() uintptr { *(*%s)(unsafe.Pointer(%s%s)) = ", p.typ(n, ot), f.bpName, nonZeroUintptr(off)) 9730 p.postfixExpressionValue(f, n, ot, exprValue, flags) 9731 p.w("; return %s%s }()", f.bpName, nonZeroUintptr(off)) 9732 case cc.PostfixExpressionSelect: // PostfixExpression '.' IDENTIFIER 9733 p.postfixExpressionAddrOfSelect(f, n, t, mode, flags) 9734 case cc.PostfixExpressionPSelect: // PostfixExpression "->" IDENTIFIER 9735 p.postfixExpressionAddrOfPSelect(f, n, t, mode, flags) 9736 case cc.PostfixExpressionInc: // PostfixExpression "++" 9737 p.postfixExpressionIncDec(f, n, "++", "+=", t, exprLValue, flags) 9738 case cc.PostfixExpressionDec: // PostfixExpression "--" 9739 panic(todo("", p.pos(n))) 9740 case cc.PostfixExpressionComplit: // '(' TypeName ')' '{' InitializerList ',' '}' 9741 tn := n.TypeName.Type() 9742 switch tn.Decay().Kind() { 9743 case cc.Ptr: 9744 switch tn.Kind() { 9745 case cc.Array: 9746 switch { 9747 case p.pass1: 9748 off := roundup(f.off, uintptr(tn.Elem().Align())) 9749 f.complits[n] = off 9750 f.off += tn.Size() 9751 default: 9752 off := f.complits[n] 9753 p.w(" func() uintptr { *(*%s)(unsafe.Pointer(%s%s)) = ", p.typ(n, tn), f.bpName, nonZeroUintptr(off)) 9754 p.initializer(f, &cc.Initializer{Case: cc.InitializerInitList, InitializerList: n.InitializerList}, tn, cc.Automatic, nil) 9755 p.w("; return %s%s }()", f.bpName, nonZeroUintptr(off)) 9756 } 9757 default: 9758 panic(todo("%v: %v", n.Position(), tn)) 9759 } 9760 default: 9761 switch { 9762 case p.pass1: 9763 off := roundup(f.off, uintptr(tn.Align())) 9764 f.complits[n] = off 9765 f.off += tn.Size() 9766 default: 9767 off := f.complits[n] 9768 p.w(" func() uintptr { *(*%s)(unsafe.Pointer(%s%s)) = ", p.typ(n, tn), f.bpName, nonZeroUintptr(off)) 9769 p.initializer(f, &cc.Initializer{Case: cc.InitializerInitList, InitializerList: n.InitializerList}, tn, cc.Automatic, nil) 9770 p.w("; return %s%s }()", f.bpName, nonZeroUintptr(off)) 9771 } 9772 } 9773 case cc.PostfixExpressionTypeCmp: // "__builtin_types_compatible_p" '(' TypeName ',' TypeName ')' 9774 panic(todo("", p.pos(n))) 9775 case cc.PostfixExpressionChooseExpr: 9776 panic(todo("", p.pos(n))) 9777 default: 9778 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 9779 } 9780 } 9781 9782 func (p *project) postfixExpressionAddrOfPSelect(f *function, n *cc.PostfixExpression, t cc.Type, mode exprMode, flags flags) { 9783 // PostfixExpression "->" IDENTIFIER 9784 p.w("(") 9785 defer p.w(")") 9786 pe := n.PostfixExpression.Operand.Type() 9787 switch { 9788 case n.Operand.Type().IsBitFieldType(): 9789 p.postfixExpression(f, n.PostfixExpression, pe, exprValue, flags) 9790 p.bitFldOff(pe.Elem(), n.Token2) 9791 case pe.Kind() == cc.Array: 9792 p.postfixExpression(f, n.PostfixExpression, pe, exprDecay, flags) 9793 p.fldOff(pe.Elem(), n.Token2) 9794 default: 9795 p.postfixExpression(f, n.PostfixExpression, pe, exprValue, flags) 9796 p.fldOff(pe.Elem(), n.Token2) 9797 } 9798 } 9799 9800 func (p *project) postfixExpressionAddrOfIndex(f *function, n *cc.PostfixExpression, t cc.Type, mode exprMode, flags flags) { 9801 // PostfixExpression '[' Expression ']' 9802 p.w("(") 9803 defer p.w(")") 9804 switch { 9805 case n.Operand.Type().Kind() == cc.Array: 9806 fallthrough 9807 default: 9808 pe := n.PostfixExpression.Operand.Type() 9809 d := n.PostfixExpression.Declarator() 9810 switch { 9811 case pe.Kind() == cc.Ptr: 9812 p.postfixExpression(f, n.PostfixExpression, pe, exprValue, flags) 9813 case pe.Kind() == cc.Array && d != nil && d.IsParameter: 9814 p.postfixExpression(f, n.PostfixExpression, pe, exprValue, flags) 9815 default: 9816 p.postfixExpression(f, n.PostfixExpression, pe, mode, flags) 9817 } 9818 if !n.Expression.Operand.IsZero() { 9819 p.nzUintptr(n, func() { p.expression(f, n.Expression, n.Expression.Operand.Type(), exprValue, flags) }, n.Expression.Operand) 9820 if sz := pe.Decay().Elem().Size(); sz != 1 { 9821 p.w("*%d", sz) 9822 } 9823 } 9824 } 9825 } 9826 9827 func (p *project) postfixExpressionAddrOfSelect(f *function, n *cc.PostfixExpression, t cc.Type, mode exprMode, flags flags) { 9828 // PostfixExpression '.' IDENTIFIER 9829 p.w("(") 9830 defer p.w(")") 9831 switch { 9832 case n.Operand.Type().IsBitFieldType(): 9833 pe := n.PostfixExpression.Operand.Type() 9834 p.postfixExpression(f, n.PostfixExpression, nil, mode, flags) 9835 p.bitFldOff(pe, n.Token2) 9836 case n.Operand.Type().Kind() == cc.Array: 9837 fallthrough 9838 default: 9839 pe := n.PostfixExpression.Operand.Type() 9840 p.postfixExpression(f, n.PostfixExpression, nil, mode, flags) 9841 p.fldOff(pe, n.Token2) 9842 } 9843 } 9844 9845 func (p *project) postfixExpressionFunc(f *function, n *cc.PostfixExpression, t cc.Type, mode exprMode, flags flags) { 9846 switch n.Case { 9847 case cc.PostfixExpressionPrimary: // PrimaryExpression 9848 p.primaryExpression(f, n.PrimaryExpression, t, mode, flags) 9849 case cc.PostfixExpressionIndex: // PostfixExpression '[' Expression ']' 9850 switch n.Operand.Type().Kind() { 9851 case cc.Ptr: 9852 switch et := n.Operand.Type().Elem(); et.Kind() { 9853 case cc.Function: 9854 p.fnVal(n, f, func() { 9855 p.postfixExpression(f, n, n.Operand.Type(), exprValue, flags) 9856 }, nil, n.Operand.Type(), 0, mode, flags) 9857 default: 9858 panic(todo("", p.pos(n), et, et.Kind())) 9859 } 9860 default: 9861 panic(todo("", n.Position(), n.Operand.Type())) 9862 } 9863 case cc.PostfixExpressionCall: // PostfixExpression '(' ArgumentExpressionList ')' 9864 switch n.Operand.Type().Kind() { 9865 case cc.Ptr: 9866 switch et := n.Operand.Type().Elem(); et.Kind() { 9867 case cc.Function: 9868 p.fnVal(n, f, func() { 9869 p.postfixExpressionCall(f, n, t, exprValue, flags) 9870 }, nil, n.Operand.Type(), 0, mode, flags) 9871 default: 9872 panic(todo("", p.pos(n), et, et.Kind())) 9873 } 9874 default: 9875 panic(todo("", n.Position(), n.Operand.Type())) 9876 } 9877 case cc.PostfixExpressionSelect: // PostfixExpression '.' IDENTIFIER 9878 switch n.Operand.Type().Kind() { 9879 case cc.Ptr: 9880 switch n.Operand.Type().Kind() { 9881 case cc.Ptr: 9882 switch et := n.Operand.Type().Elem(); et.Kind() { 9883 case cc.Function: 9884 p.fnVal(n, f, func() { p.postfixExpression(f, n, p.ptrType, exprValue, flags) }, nil, n.Operand.Type(), 0, mode, flags) 9885 default: 9886 panic(todo("", p.pos(n), et, et.Kind())) 9887 } 9888 default: 9889 panic(todo("", p.pos(n), n.Operand.Type(), n.Operand.Type().Kind())) 9890 } 9891 default: 9892 panic(todo("", n.Position(), n.Operand.Type())) 9893 } 9894 case cc.PostfixExpressionPSelect: // PostfixExpression "->" IDENTIFIER 9895 p.fnVal(n, f, func() { p.postfixExpression(f, n, p.ptrType, exprValue, flags) }, nil, n.Operand.Type(), 0, mode, flags) 9896 case cc.PostfixExpressionInc: // PostfixExpression "++" 9897 panic(todo("", p.pos(n))) 9898 case cc.PostfixExpressionDec: // PostfixExpression "--" 9899 panic(todo("", p.pos(n))) 9900 case cc.PostfixExpressionComplit: // '(' TypeName ')' '{' InitializerList ',' '}' 9901 panic(todo("", p.pos(n))) 9902 case cc.PostfixExpressionTypeCmp: // "__builtin_types_compatible_p" '(' TypeName ',' TypeName ')' 9903 panic(todo("", p.pos(n))) 9904 case cc.PostfixExpressionChooseExpr: 9905 panic(todo("", p.pos(n))) 9906 default: 9907 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 9908 } 9909 } 9910 9911 func (p *project) postfixExpressionVoid(f *function, n *cc.PostfixExpression, t cc.Type, mode exprMode, flags flags) { 9912 switch n.Case { 9913 case cc.PostfixExpressionPrimary: // PrimaryExpression 9914 p.primaryExpression(f, n.PrimaryExpression, t, mode, flags) 9915 case cc.PostfixExpressionIndex: // PostfixExpression '[' Expression ']' 9916 p.w("_ = ") 9917 p.postfixExpression(f, n, n.Operand.Type(), exprValue, flags) 9918 case cc.PostfixExpressionCall: // PostfixExpression '(' ArgumentExpressionList ')' 9919 p.postfixExpressionCall(f, n, n.Operand.Type(), mode, flags) 9920 case cc.PostfixExpressionSelect: // PostfixExpression '.' IDENTIFIER 9921 p.w("_ = ") 9922 p.postfixExpression(f, n, n.Operand.Type(), exprValue, flags) 9923 case cc.PostfixExpressionPSelect: // PostfixExpression "->" IDENTIFIER 9924 p.w("_ = ") 9925 p.postfixExpression(f, n, n.Operand.Type(), exprValue, flags) 9926 case cc.PostfixExpressionInc: // PostfixExpression "++" 9927 p.postfixExpressionIncDec(f, n, "++", "+=", t, mode, flags) 9928 case cc.PostfixExpressionDec: // PostfixExpression "--" 9929 p.postfixExpressionIncDec(f, n, "--", "-=", t, mode, flags) 9930 case cc.PostfixExpressionComplit: // '(' TypeName ')' '{' InitializerList ',' '}' 9931 tn := n.TypeName.Type() 9932 switch tn.Decay().Kind() { 9933 case cc.Ptr: 9934 switch tn.Kind() { 9935 case cc.Array: 9936 switch { 9937 case p.pass1: 9938 off := roundup(f.off, uintptr(tn.Elem().Align())) 9939 f.complits[n] = off 9940 f.off += tn.Size() 9941 default: 9942 off := f.complits[n] 9943 p.w("*(*%s)(unsafe.Pointer(%s%s)) = ", p.typ(n, tn), f.bpName, nonZeroUintptr(off)) 9944 p.initializer(f, &cc.Initializer{Case: cc.InitializerInitList, InitializerList: n.InitializerList}, tn, cc.Automatic, nil) 9945 } 9946 return 9947 default: 9948 panic(todo("%v: %v", n.Position(), tn)) 9949 } 9950 } 9951 9952 defer p.w("%s", p.convertType(n, tn, t, flags)) 9953 p.w("_ = ") 9954 p.initializer(f, &cc.Initializer{Case: cc.InitializerInitList, InitializerList: n.InitializerList}, tn, cc.Automatic, nil) 9955 case cc.PostfixExpressionTypeCmp: // "__builtin_types_compatible_p" '(' TypeName ',' TypeName ')' 9956 panic(todo("", p.pos(n))) 9957 case cc.PostfixExpressionChooseExpr: 9958 panic(todo("", p.pos(n))) 9959 default: 9960 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 9961 } 9962 } 9963 9964 func (p *project) postfixExpressionValue(f *function, n *cc.PostfixExpression, t cc.Type, mode exprMode, flags flags) { 9965 switch n.Case { 9966 case cc.PostfixExpressionPrimary: // PrimaryExpression 9967 if p.isArray(f, n.PrimaryExpression, n.Operand.Type()) && t.Kind() == cc.Ptr { 9968 mode = exprDecay 9969 } 9970 p.primaryExpression(f, n.PrimaryExpression, t, mode, flags) 9971 case cc.PostfixExpressionIndex: // PostfixExpression '[' Expression ']' 9972 p.postfixExpressionValueIndex(f, n, t, mode, flags) 9973 case cc.PostfixExpressionCall: // PostfixExpression '(' ArgumentExpressionList ')' 9974 p.postfixExpressionCall(f, n, t, mode, flags) 9975 case cc.PostfixExpressionSelect: // PostfixExpression '.' IDENTIFIER 9976 p.postfixExpressionValueSelect(f, n, t, mode, flags) 9977 case cc.PostfixExpressionPSelect: // PostfixExpression "->" IDENTIFIER 9978 p.postfixExpressionValuePSelect(f, n, t, mode, flags) 9979 case cc.PostfixExpressionInc: // PostfixExpression "++" 9980 p.postfixExpressionIncDec(f, n, "++", "+=", t, mode, flags) 9981 case cc.PostfixExpressionDec: // PostfixExpression "--" 9982 p.postfixExpressionIncDec(f, n, "--", "-=", t, mode, flags) 9983 case cc.PostfixExpressionComplit: // '(' TypeName ')' '{' InitializerList ',' '}' 9984 tn := n.TypeName.Type() 9985 switch tn.Decay().Kind() { 9986 case cc.Ptr: 9987 switch tn.Kind() { 9988 case cc.Array: 9989 switch { 9990 case p.pass1: 9991 off := roundup(f.off, uintptr(tn.Elem().Align())) 9992 f.complits[n] = off 9993 f.off += tn.Size() 9994 default: 9995 off := f.complits[n] 9996 p.w(" func() uintptr { *(*%s)(unsafe.Pointer(%s%s)) = ", p.typ(n, tn), f.bpName, nonZeroUintptr(off)) 9997 p.initializer(f, &cc.Initializer{Case: cc.InitializerInitList, InitializerList: n.InitializerList}, tn, cc.Automatic, nil) 9998 p.w("; return %s%s }()", f.bpName, nonZeroUintptr(off)) 9999 } 10000 return 10001 default: 10002 panic(todo("%v: %v", n.Position(), tn)) 10003 } 10004 } 10005 10006 defer p.w("%s", p.convertType(n, tn, t, flags)) 10007 p.initializer(f, &cc.Initializer{Case: cc.InitializerInitList, InitializerList: n.InitializerList}, tn, cc.Automatic, nil) 10008 case cc.PostfixExpressionTypeCmp: // "__builtin_types_compatible_p" '(' TypeName ',' TypeName ')' 10009 // Built-in Function: int __builtin_types_compatible_p (type1, type2) You can 10010 // use the built-in function __builtin_types_compatible_p to determine whether 10011 // two types are the same. 10012 // 10013 // This built-in function returns 1 if the unqualified versions of the types 10014 // type1 and type2 (which are types, not expressions) are compatible, 0 10015 // otherwise. The result of this built-in function can be used in integer 10016 // constant expressions. 10017 // 10018 // This built-in function ignores top level qualifiers (e.g., const, volatile). 10019 // For example, int is equivalent to const int. 10020 // 10021 // The type int[] and int[5] are compatible. On the other hand, int and char * 10022 // are not compatible, even if the size of their types, on the particular 10023 // architecture are the same. Also, the amount of pointer indirection is taken 10024 // into account when determining similarity. Consequently, short * is not 10025 // similar to short **. Furthermore, two types that are typedefed are 10026 // considered compatible if their underlying types are compatible. 10027 // 10028 // An enum type is not considered to be compatible with another enum type even 10029 // if both are compatible with the same integer type; this is what the C 10030 // standard specifies. For example, enum {foo, bar} is not similar to enum 10031 // {hot, dog}. 10032 // 10033 // You typically use this function in code whose execution varies depending on 10034 // the arguments’ types. For example: 10035 // 10036 // #define foo(x) \ 10037 // ({ \ 10038 // typeof (x) tmp = (x); \ 10039 // if (__builtin_types_compatible_p (typeof (x), long double)) \ 10040 // tmp = foo_long_double (tmp); \ 10041 // else if (__builtin_types_compatible_p (typeof (x), double)) \ 10042 // tmp = foo_double (tmp); \ 10043 // else if (__builtin_types_compatible_p (typeof (x), float)) \ 10044 // tmp = foo_float (tmp); \ 10045 // else \ 10046 // abort (); \ 10047 // tmp; \ 10048 // }) 10049 // 10050 // Note: This construct is only available for C. 10051 p.w(" %d ", n.Operand.Value()) 10052 case cc.PostfixExpressionChooseExpr: // "__builtin_choose_expr" '(' AssignmentExpression ',' AssignmentExpression ',' AssignmentExpression ')' 10053 // You can use the built-in function __builtin_choose_expr to evaluate code 10054 // depending on the value of a constant expression. This built-in function 10055 // returns exp1 if const_exp, which is an integer constant expression, is 10056 // nonzero. Otherwise it returns exp2. 10057 // 10058 // This built-in function is analogous to the ‘? :’ operator in C, except that 10059 // the expression returned has its type unaltered by promotion rules. Also, the 10060 // built-in function does not evaluate the expression that is not chosen. For 10061 // example, if const_exp evaluates to true, exp2 is not evaluated even if it 10062 // has side effects. 10063 // 10064 // This built-in function can return an lvalue if the chosen argument is an 10065 // lvalue. 10066 // 10067 // If exp1 is returned, the return type is the same as exp1’s type. Similarly, 10068 // if exp2 is returned, its return type is the same as exp2. 10069 // 10070 // Example: 10071 // 10072 // #define foo(x) \ 10073 // __builtin_choose_expr ( \ 10074 // __builtin_types_compatible_p (typeof (x), double), \ 10075 // foo_double (x), \ 10076 // __builtin_choose_expr ( \ 10077 // __builtin_types_compatible_p (typeof (x), float), \ 10078 // foo_float (x), \ 10079 // /* The void expression results in a compile-time error \ 10080 // when assigning the result to something. */ \ 10081 // (void)0)) 10082 // 10083 // Note: This construct is only available for C. Furthermore, the unused 10084 // expression (exp1 or exp2 depending on the value of const_exp) may still 10085 // generate syntax errors. This may change in future revisions. 10086 switch op := n.AssignmentExpression.Operand; { 10087 case op.IsNonZero(): 10088 p.assignmentExpression(f, n.AssignmentExpression2, t, mode, flags) 10089 case op.IsZero(): 10090 p.assignmentExpression(f, n.AssignmentExpression3, t, mode, flags) 10091 default: 10092 panic(todo("")) 10093 } 10094 default: 10095 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 10096 } 10097 } 10098 10099 func (p *project) postfixExpressionValuePSelect(f *function, n *cc.PostfixExpression, t cc.Type, mode exprMode, flags flags) { 10100 // PostfixExpression "->" IDENTIFIER 10101 switch k := p.opKind(f, n.PostfixExpression, n.PostfixExpression.Operand.Type().Elem()); k { 10102 case opStruct: 10103 p.postfixExpressionValuePSelectStruct(f, n, t, mode, flags) 10104 case opUnion: 10105 p.postfixExpressionValuePSelectUnion(f, n, t, mode, flags) 10106 default: 10107 panic(todo("", n.Position(), k)) 10108 } 10109 } 10110 10111 func (p *project) postfixExpressionValuePSelectUnion(f *function, n *cc.PostfixExpression, t cc.Type, mode exprMode, flags flags) { 10112 // PostfixExpression "->" IDENTIFIER 10113 fld := n.Field 10114 if fld.Offset() != 0 { 10115 p.err(&n.Token2, "internal error, union field with non-zero offset: %s %v", n.Token2.Value, fld.Offset()) 10116 } 10117 pe := n.PostfixExpression.Operand.Type() 10118 switch { 10119 case n.Operand.Type().IsBitFieldType(): 10120 panic(todo("", p.pos(n))) 10121 case n.Operand.Type().Kind() == cc.Array: 10122 panic(todo("", p.pos(n))) 10123 default: 10124 if fld.IsBitField() { 10125 p.err(&n.Token2, "internal error, wrong function for accessing a bit field: %s", n.Token2.Value) 10126 } 10127 defer p.w("%s", p.convert(n, n.Operand, t, flags)) 10128 p.w("*(*%s)(unsafe.Pointer(", p.typ(n, n.Operand.Type())) 10129 p.postfixExpression(f, n.PostfixExpression, pe, exprValue, flags) 10130 p.w("/* .%s */", p.fieldName(n, n.Token2.Value)) 10131 p.w("))") 10132 } 10133 } 10134 10135 func (p *project) postfixExpressionValuePSelectStruct(f *function, n *cc.PostfixExpression, t cc.Type, mode exprMode, flags flags) { 10136 // PostfixExpression "->" IDENTIFIER 10137 fld := n.Field 10138 pe := n.PostfixExpression.Operand.Type() 10139 k := p.opKind(f, n.PostfixExpression, n.PostfixExpression.Operand.Type()) 10140 switch { 10141 case n.Operand.Type().IsBitFieldType(): 10142 p.w("(") 10143 defer p.w(")") 10144 fld := n.Field 10145 defer p.w("%s", p.convertType(n, fld.Promote(), t, flags)) 10146 switch pe.Kind() { 10147 case cc.Array: 10148 x := p.convertType(n, nil, fld.Promote(), flags) 10149 p.w("*(*uint%d)(unsafe.Pointer(", fld.BitFieldBlockWidth()) 10150 p.postfixExpression(f, n.PostfixExpression, pe, exprDecay, flags) 10151 p.bitFldOff(pe.Elem(), n.Token2) 10152 p.w("))") 10153 p.w("&%#x>>%d%s", fld.Mask(), fld.BitFieldOffset(), x) 10154 if fld.Type().IsSignedType() { 10155 panic(todo("")) 10156 p.w("<<%d>>%[1]d", int(fld.Promote().Size()*8)-fld.BitFieldWidth()) 10157 } 10158 default: 10159 x := p.convertType(n, nil, fld.Promote(), flags) 10160 p.w("*(*uint%d)(unsafe.Pointer(", fld.BitFieldBlockWidth()) 10161 p.postfixExpression(f, n.PostfixExpression, pe, exprValue, flags) 10162 p.bitFldOff(pe.Elem(), n.Token2) 10163 p.w("))&%#x>>%d%s", fld.Mask(), fld.BitFieldOffset(), x) 10164 if fld.Type().IsSignedType() { 10165 p.w("<<%d>>%[1]d", int(fld.Promote().Size()*8)-fld.BitFieldWidth()) 10166 } 10167 } 10168 case n.Operand.Type().Kind() == cc.Array: 10169 defer p.w("%s", p.convertType(n, n.Operand.Type().Decay(), t.Decay(), flags)) 10170 p.postfixExpression(f, n.PostfixExpression, pe, exprValue, flags) 10171 p.fldOff(n.PostfixExpression.Operand.Type().Elem(), n.Token2) 10172 case k == opArray: 10173 defer p.w("%s", p.convert(n, n.Operand, t, flags)) 10174 p.postfixExpression(f, n.PostfixExpression, pe, exprValue, flags) 10175 p.w("[0].%s", p.fieldName(n, n.Token2.Value)) 10176 default: 10177 if fld.IsBitField() { 10178 p.err(&n.Token2, "internal error, wrong function for accessing a bit field: %s", n.Token2.Value) 10179 } 10180 defer p.w("%s", p.convert(n, n.Operand, t, flags)) 10181 et := pe.Elem() 10182 fld, path, ok := et.FieldByName2(n.Token2.Value) 10183 switch { 10184 case !ok: 10185 panic(todo("")) 10186 case fld.InUnion(): 10187 p.w("*(*%s)(unsafe.Pointer(", p.typ(n, n.Operand.Type())) 10188 p.postfixExpression(f, n.PostfixExpression, pe, exprValue, flags) 10189 p.w("%s))", nonZeroUintptr(pathOff(et, path))) 10190 case len(path) != 1: 10191 panic(todo("")) 10192 default: 10193 p.w("(*%s)(unsafe.Pointer(", p.typ(n, pe.Elem())) 10194 p.postfixExpression(f, n.PostfixExpression, pe, exprValue, flags) 10195 p.w(")).%s", p.fieldName(n, n.Token2.Value)) 10196 } 10197 } 10198 } 10199 10200 func pathOff(t cc.Type, path []int) (r uintptr) { 10201 for len(path) != 0 { 10202 f := t.FieldByIndex(path[:1]) 10203 r += f.Offset() 10204 path = path[1:] 10205 t = f.Type() 10206 } 10207 return r 10208 } 10209 10210 func (p *project) postfixExpressionValueIndex(f *function, n *cc.PostfixExpression, t cc.Type, mode exprMode, flags flags) { 10211 // PostfixExpression '[' Expression ']' 10212 switch k := p.opKind(f, n.PostfixExpression, n.PostfixExpression.Operand.Type()); k { 10213 case opArray: 10214 p.postfixExpressionValueIndexArray(f, n, t, mode, flags) 10215 case opNormal: 10216 p.postfixExpressionValueIndexNormal(f, n, t, mode, flags) 10217 case opArrayParameter: 10218 p.postfixExpressionValueIndexArrayParameter(f, n, t, mode, flags) 10219 default: 10220 panic(todo("", n.Position(), k)) 10221 } 10222 } 10223 func (p *project) postfixExpressionValueIndexArrayParameter(f *function, n *cc.PostfixExpression, t cc.Type, mode exprMode, flags flags) { 10224 // PostfixExpression '[' Expression ']' 10225 pe := n.PostfixExpression.Operand.Type() 10226 switch { 10227 case n.Operand.Type().Kind() == cc.Array: 10228 defer p.w("%s", p.convert(n, n.Operand, t, flags)) 10229 p.w("(") 10230 defer p.w(")") 10231 p.postfixExpression(f, n.PostfixExpression, pe, exprValue, flags) 10232 if !n.Expression.Operand.IsZero() { 10233 p.nzUintptr(n, func() { p.expression(f, n.Expression, n.Expression.Operand.Type(), exprValue, flags) }, n.Expression.Operand) 10234 if sz := pe.Elem().Size(); sz != 1 { 10235 p.w("*%d", sz) 10236 } 10237 } 10238 default: 10239 defer p.w("%s", p.convert(n, n.Operand, t, flags)) 10240 p.w("*(*%s)(unsafe.Pointer(", p.typ(n, pe.Elem())) 10241 p.postfixExpression(f, n.PostfixExpression, pe, exprValue, flags) 10242 if !n.Expression.Operand.IsZero() { 10243 p.nzUintptr(n, func() { p.expression(f, n.Expression, n.Expression.Operand.Type(), exprValue, flags) }, n.Expression.Operand) 10244 if sz := pe.Elem().Size(); sz != 1 { 10245 p.w("*%d", sz) 10246 } 10247 } 10248 p.w("))") 10249 } 10250 } 10251 10252 func (p *project) postfixExpressionValueIndexNormal(f *function, n *cc.PostfixExpression, t cc.Type, mode exprMode, flags flags) { 10253 // PostfixExpression '[' Expression ']' 10254 switch { 10255 case n.Operand.Type().Kind() == cc.Array: 10256 p.w("(") 10257 defer p.w(")") 10258 pe := n.PostfixExpression.Operand.Type() 10259 defer p.w("%s", p.convert(n, n.Operand, t, flags)) 10260 p.postfixExpression(f, n.PostfixExpression, pe, exprValue, flags) 10261 if !n.Expression.Operand.IsZero() { 10262 p.nzUintptr(n, func() { p.expression(f, n.Expression, n.Expression.Operand.Type(), exprValue, flags) }, n.Expression.Operand) 10263 if sz := pe.Elem().Size(); sz != 1 { 10264 p.w("*%d", sz) 10265 } 10266 } 10267 default: 10268 switch pe := n.PostfixExpression.Operand.Type(); pe.Kind() { 10269 case cc.Ptr: 10270 defer p.w("%s", p.convert(n, n.Operand, t, flags)) 10271 p.w("*(*%s)(unsafe.Pointer(", p.typ(n, pe.Elem())) 10272 p.postfixExpression(f, n.PostfixExpression, pe, exprValue, flags) 10273 if !n.Expression.Operand.IsZero() { 10274 p.nzUintptr(n, func() { p.expression(f, n.Expression, n.Expression.Operand.Type(), exprValue, flags) }, n.Expression.Operand) 10275 if sz := pe.Elem().Size(); sz != 1 { 10276 p.w("*%d", sz) 10277 } 10278 } 10279 p.w("))") 10280 case cc.Array: 10281 defer p.w("%s", p.convert(n, n.Operand, t, flags)) 10282 p.w("*(*%s)(unsafe.Pointer(", p.typ(n, pe.Elem())) 10283 p.postfixExpression(f, n.PostfixExpression, pe, exprDecay, flags) 10284 if !n.Expression.Operand.IsZero() { 10285 p.nzUintptr(n, func() { p.expression(f, n.Expression, n.Expression.Operand.Type(), exprValue, flags) }, n.Expression.Operand) 10286 if sz := pe.Elem().Size(); sz != 1 { 10287 p.w("*%d", sz) 10288 } 10289 } 10290 p.w("))") 10291 default: 10292 panic(todo("", p.pos(n), pe, pe.Kind())) 10293 } 10294 } 10295 } 10296 10297 func (p *project) postfixExpressionValueIndexArray(f *function, n *cc.PostfixExpression, t cc.Type, mode exprMode, flags flags) { 10298 // PostfixExpression '[' Expression ']' 10299 pe := n.PostfixExpression.Operand.Type() 10300 switch n.Operand.Type().Kind() { 10301 case cc.Array: 10302 defer p.w("%s", p.convert(n, n.Operand, t, flags)) 10303 p.w("(") 10304 defer p.w(")") 10305 p.postfixExpression(f, n.PostfixExpression, pe, exprDecay, flags) 10306 if !n.Expression.Operand.IsZero() { 10307 p.nzUintptr(n, func() { p.expression(f, n.Expression, n.Expression.Operand.Type(), exprValue, flags) }, n.Expression.Operand) 10308 if sz := pe.Elem().Size(); sz != 1 { 10309 p.w("*%d", sz) 10310 } 10311 } 10312 default: 10313 defer p.w("%s", p.convert(n, n.Operand, t, flags)) 10314 p.postfixExpression(f, n.PostfixExpression, pe, mode, flags) 10315 p.w("[") 10316 p.expression(f, n.Expression, n.Expression.Operand.Type(), exprValue, flags) 10317 p.w("]") 10318 } 10319 } 10320 10321 func (p *project) postfixExpressionValueSelect(f *function, n *cc.PostfixExpression, t cc.Type, mode exprMode, flags flags) { 10322 // PostfixExpression '.' IDENTIFIER 10323 switch k := p.opKind(f, n.PostfixExpression, n.PostfixExpression.Operand.Type()); k { 10324 case opStruct: 10325 p.postfixExpressionValueSelectStruct(f, n, t, mode, flags) 10326 case opUnion: 10327 p.postfixExpressionValueSelectUnion(f, n, t, mode, flags) 10328 default: 10329 panic(todo("", n.Position(), k)) 10330 } 10331 } 10332 10333 func (p *project) postfixExpressionValueSelectUnion(f *function, n *cc.PostfixExpression, t cc.Type, mode exprMode, flags flags) { 10334 // PostfixExpression '.' IDENTIFIER 10335 pe := n.PostfixExpression.Operand.Type() 10336 fld := n.Field 10337 switch { 10338 case n.Operand.Type().IsBitFieldType(): 10339 p.w("(") 10340 defer p.w("%s)", p.convertType(n, fld.Promote(), t, flags)) 10341 x := p.convertType(n, nil, fld.Promote(), flags) 10342 p.w("*(*uint%d)(unsafe.Pointer(", fld.BitFieldBlockWidth()) 10343 p.postfixExpression(f, n.PostfixExpression, pe, exprAddrOf, flags) 10344 p.bitFldOff(pe, n.Token2) 10345 p.w("))&%#x>>%d%s", fld.Mask(), fld.BitFieldOffset(), x) 10346 if fld.Type().IsSignedType() { 10347 p.w("<<%d>>%[1]d", int(fld.Promote().Size()*8)-fld.BitFieldWidth()) 10348 } 10349 case n.Operand.Type().Kind() == cc.Array: 10350 p.postfixExpression(f, n.PostfixExpression, pe, exprAddrOf, flags) 10351 default: 10352 if fld.IsBitField() { 10353 p.err(&n.Token2, "internal error, wrong function for accessing a bit field: %s", n.Token2.Value) 10354 } 10355 defer p.w("%s", p.convert(n, n.Operand, t, flags)) 10356 p.w("*(*%s)(unsafe.Pointer(", p.typ(n, n.Operand.Type())) 10357 p.postfixExpression(f, n.PostfixExpression, pe, exprAddrOf, flags) 10358 p.w("))") 10359 } 10360 } 10361 10362 func (p *project) postfixExpressionValueSelectStruct(f *function, n *cc.PostfixExpression, t cc.Type, mode exprMode, flags flags) { 10363 // PostfixExpression '.' IDENTIFIER 10364 pe := n.PostfixExpression.Operand.Type() 10365 fld := n.Field 10366 switch { 10367 case n.Operand.Type().IsBitFieldType(): 10368 p.w("(") 10369 defer p.w("%s)", p.convertType(n, fld.Promote(), t, flags)) 10370 x := p.convertType(n, nil, fld.Promote(), flags) 10371 p.w("*(*uint%d)(unsafe.Pointer(", fld.BitFieldBlockWidth()) 10372 p.postfixExpression(f, n.PostfixExpression, pe, exprAddrOf, flags) 10373 p.bitFldOff(pe, n.Token2) 10374 p.w("))&%#x>>%d%s", fld.Mask(), fld.BitFieldOffset(), x) 10375 if fld.Type().IsSignedType() { 10376 p.w("<<%d>>%[1]d", int(fld.Promote().Size()*8)-fld.BitFieldWidth()) 10377 } 10378 case n.Operand.Type().Kind() == cc.Array: 10379 p.postfixExpression(f, n, t, exprDecay, flags) 10380 case fld.InUnion(): 10381 defer p.w("%s", p.convert(n, n.Operand, t, flags)) 10382 p.w("*(*%s)(unsafe.Pointer(", p.typ(n, fld.Type())) 10383 p.postfixExpression(f, n.PostfixExpression, pe, exprAddrOf, flags) 10384 p.fldOff(pe, n.Token2) 10385 p.w("))") 10386 default: 10387 if fld.IsBitField() { 10388 p.err(&n.Token2, "internal error, wrong function for accessing a bit field: %s", n.Token2.Value) 10389 } 10390 defer p.w("%s", p.convert(n, n.Operand, t, flags)) 10391 p.postfixExpression(f, n.PostfixExpression, pe, exprSelect, flags) 10392 p.w(".%s", p.fieldName(n, n.Token2.Value)) 10393 } 10394 } 10395 10396 func (p *project) postfixExpressionLValue(f *function, n *cc.PostfixExpression, t cc.Type, mode exprMode, flags flags) { 10397 switch n.Case { 10398 case cc.PostfixExpressionPrimary: // PrimaryExpression 10399 p.primaryExpression(f, n.PrimaryExpression, t, mode, flags) 10400 case cc.PostfixExpressionIndex: // PostfixExpression '[' Expression ']' 10401 p.postfixExpressionLValueIndex(f, n, t, mode, flags) 10402 case cc.PostfixExpressionCall: // PostfixExpression '(' ArgumentExpressionList ')' 10403 panic(todo("", p.pos(n))) 10404 case cc.PostfixExpressionSelect: // PostfixExpression '.' IDENTIFIER 10405 p.postfixExpressionLValueSelect(f, n, t, mode, flags) 10406 case cc.PostfixExpressionPSelect: // PostfixExpression "->" IDENTIFIER 10407 p.postfixExpressionLValuePSelect(f, n, t, mode, flags) 10408 case cc.PostfixExpressionInc: // PostfixExpression "++" 10409 p.postfixExpressionIncDec(f, n, "++", "+=", t, mode, flags) 10410 case cc.PostfixExpressionDec: // PostfixExpression "--" 10411 p.postfixExpressionIncDec(f, n, "--", "-=", t, mode, flags) 10412 case cc.PostfixExpressionComplit: // '(' TypeName ')' '{' InitializerList ',' '}' 10413 panic(todo("", p.pos(n))) 10414 case cc.PostfixExpressionTypeCmp: // "__builtin_types_compatible_p" '(' TypeName ',' TypeName ')' 10415 panic(todo("", p.pos(n))) 10416 case cc.PostfixExpressionChooseExpr: 10417 panic(todo("", p.pos(n))) 10418 default: 10419 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 10420 } 10421 } 10422 10423 func (p *project) postfixExpressionLValuePSelect(f *function, n *cc.PostfixExpression, t cc.Type, mode exprMode, flags flags) { 10424 // PostfixExpression "->" IDENTIFIER 10425 pe := n.PostfixExpression 10426 switch k := p.opKind(f, n.PostfixExpression, n.PostfixExpression.Operand.Type().Elem()); k { 10427 case opStruct: 10428 if !p.inUnion(n, pe.Operand.Type().Elem(), n.Token2.Value) { 10429 p.postfixExpressionLValuePSelectStruct(f, n, t, mode, flags) 10430 break 10431 } 10432 10433 p.w("*(*%s)(unsafe.Pointer(", p.typ(n, n.Operand.Type())) 10434 p.postfixExpression(f, pe, pe.Operand.Type(), exprValue, flags) 10435 p.fldOff(pe.Operand.Type().Elem(), n.Token2) 10436 p.w("))") 10437 case opUnion: 10438 p.postfixExpressionLValuePSelectUnion(f, n, t, mode, flags) 10439 default: 10440 panic(todo("", n.Position(), k)) 10441 } 10442 } 10443 10444 func (p *project) postfixExpressionLValuePSelectUnion(f *function, n *cc.PostfixExpression, t cc.Type, mode exprMode, flags flags) { 10445 // PostfixExpression "->" IDENTIFIER 10446 fld := n.Field 10447 if fld.Offset() != 0 { 10448 p.err(&n.Token2, "internal error, union field with non-zero offset: %s %v", n.Token2.Value, fld.Offset()) 10449 } 10450 switch { 10451 case n.Operand.Type().IsBitFieldType(): 10452 panic(todo("", p.pos(n))) 10453 default: 10454 if fld.IsBitField() { 10455 p.err(&n.Token2, "internal error, wrong function for accessing a bit field: %s", n.Token2.Value) 10456 } 10457 pe := n.PostfixExpression.Operand.Type() 10458 defer p.w("%s", p.convert(n, n.Operand, t, flags)) 10459 p.w("(*(*%s)(unsafe.Pointer(", p.typ(n, n.Operand.Type())) 10460 p.postfixExpression(f, n.PostfixExpression, pe, exprValue, flags) 10461 p.w("/* .%s */", p.fieldName(n, n.Token2.Value)) 10462 p.w(")))") 10463 } 10464 } 10465 10466 func (p *project) postfixExpressionLValuePSelectStruct(f *function, n *cc.PostfixExpression, t cc.Type, mode exprMode, flags flags) { 10467 // PostfixExpression "->" IDENTIFIER 10468 fld := n.Field 10469 pe := n.PostfixExpression.Operand.Type() 10470 k := p.opKind(f, n.PostfixExpression, n.PostfixExpression.Operand.Type()) 10471 switch { 10472 case n.Operand.Type().IsBitFieldType(): 10473 panic(todo("", p.pos(n))) 10474 case k == opArray: 10475 defer p.w("%s", p.convert(n, n.Operand, t, flags)) 10476 p.postfixExpression(f, n.PostfixExpression, pe, exprValue, flags) 10477 p.w("[0].%s", p.fieldName(n, n.Token2.Value)) 10478 default: 10479 if fld.IsBitField() { 10480 p.err(&n.Token2, "internal error, wrong function for accessing a bit field: %s", n.Token2.Value) 10481 } 10482 defer p.w("%s", p.convert(n, n.Operand, t, flags)) 10483 p.w("(*%s)(unsafe.Pointer(", p.typ(n, pe.Elem())) 10484 p.postfixExpression(f, n.PostfixExpression, pe, exprValue, flags) 10485 p.w(")).%s", p.fieldName(n, n.Token2.Value)) 10486 } 10487 } 10488 10489 func (p *project) postfixExpressionLValueIndex(f *function, n *cc.PostfixExpression, t cc.Type, mode exprMode, flags flags) { 10490 // PostfixExpression '[' Expression ']' 10491 switch k := p.opKind(f, n.PostfixExpression, n.PostfixExpression.Operand.Type()); k { 10492 case opArray: 10493 p.postfixExpressionLValueIndexArray(f, n, t, mode, flags) 10494 case opNormal: 10495 p.postfixExpressionLValueIndexNormal(f, n, t, mode, flags) 10496 case opArrayParameter: 10497 p.postfixExpressionLValueIndexArrayParameter(f, n, t, mode, flags) 10498 default: 10499 panic(todo("", n.Position(), k)) 10500 } 10501 } 10502 10503 func (p *project) postfixExpressionLValueIndexArrayParameter(f *function, n *cc.PostfixExpression, t cc.Type, mode exprMode, flags flags) { 10504 // PostfixExpression '[' Expression ']' 10505 defer p.w("%s", p.convert(n, n.Operand, t, flags)) 10506 pe := n.PostfixExpression.Operand.Type() 10507 p.w("*(*%s)(unsafe.Pointer(", p.typ(n, pe.Elem())) 10508 p.postfixExpression(f, n.PostfixExpression, pe, exprValue, flags) 10509 if !n.Expression.Operand.IsZero() { 10510 p.nzUintptr(n, func() { p.expression(f, n.Expression, n.Expression.Operand.Type(), exprValue, flags) }, n.Expression.Operand) 10511 if sz := pe.Elem().Size(); sz != 1 { 10512 p.w("*%d", sz) 10513 } 10514 } 10515 p.w("))") 10516 } 10517 10518 func (p *project) postfixExpressionLValueIndexNormal(f *function, n *cc.PostfixExpression, t cc.Type, mode exprMode, flags flags) { 10519 // PostfixExpression '[' Expression ']' 10520 switch { 10521 case n.Operand.Type().Kind() == cc.Array: 10522 panic(todo("", p.pos(n))) 10523 default: 10524 switch pe := n.PostfixExpression.Operand.Type(); pe.Kind() { 10525 case cc.Ptr: 10526 defer p.w("%s", p.convert(n, n.Operand, t, flags)) 10527 p.w("*(*%s)(unsafe.Pointer(", p.typ(n, pe.Elem())) 10528 p.postfixExpression(f, n.PostfixExpression, pe, exprValue, flags) 10529 if !n.Expression.Operand.IsZero() { 10530 p.nzUintptr(n, func() { p.expression(f, n.Expression, n.Expression.Operand.Type(), exprValue, flags) }, n.Expression.Operand) 10531 if sz := pe.Elem().Size(); sz != 1 { 10532 p.w("*%d", sz) 10533 } 10534 } 10535 p.w("))") 10536 case cc.Array: 10537 defer p.w("%s", p.convert(n, n.Operand, t, flags)) 10538 p.w("*(*%s)(unsafe.Pointer(", p.typ(n, pe.Elem())) 10539 p.postfixExpression(f, n.PostfixExpression, pe, exprDecay, flags) 10540 if !n.Expression.Operand.IsZero() { 10541 p.nzUintptr(n, func() { p.expression(f, n.Expression, n.Expression.Operand.Type(), exprValue, flags) }, n.Expression.Operand) 10542 if sz := pe.Elem().Size(); sz != 1 { 10543 p.w("*%d", sz) 10544 } 10545 } 10546 p.w("))") 10547 default: 10548 panic(todo("", p.pos(n), pe)) 10549 } 10550 } 10551 } 10552 10553 func (p *project) postfixExpressionLValueIndexArray(f *function, n *cc.PostfixExpression, t cc.Type, mode exprMode, flags flags) { 10554 // PostfixExpression '[' Expression ']' 10555 pe := n.PostfixExpression.Operand.Type() 10556 p.postfixExpression(f, n.PostfixExpression, pe, mode, flags) 10557 p.w("[") 10558 p.expression(f, n.Expression, n.Expression.Operand.Type(), exprValue, flags) 10559 p.w("]") 10560 } 10561 10562 func (p *project) postfixExpressionLValueSelect(f *function, n *cc.PostfixExpression, t cc.Type, mode exprMode, flags flags) { 10563 // PostfixExpression '.' IDENTIFIER 10564 pe := n.PostfixExpression 10565 switch k := p.opKind(f, pe, pe.Operand.Type()); k { 10566 case opStruct: 10567 if !p.inUnion(n, pe.Operand.Type(), n.Token2.Value) { 10568 p.postfixExpressionLValueSelectStruct(f, n, t, mode, flags) 10569 break 10570 } 10571 10572 p.w("*(*%s)(unsafe.Pointer(", p.typ(n, n.Operand.Type())) 10573 p.postfixExpression(f, pe, pe.Operand.Type(), exprAddrOf, flags) 10574 p.fldOff(pe.Operand.Type(), n.Token2) 10575 p.w("))") 10576 case opUnion: 10577 p.postfixExpressionLValueSelectUnion(f, n, t, mode, flags) 10578 default: 10579 panic(todo("", n.Position(), k)) 10580 } 10581 } 10582 10583 func (p *project) inUnion(n cc.Node, t cc.Type, fname cc.StringID) bool { 10584 f, ok := t.FieldByName(fname) 10585 if !ok { 10586 p.err(n, "unknown field: %s", fname) 10587 return false 10588 } 10589 10590 return f.InUnion() 10591 } 10592 10593 func (p *project) postfixExpressionLValueSelectUnion(f *function, n *cc.PostfixExpression, t cc.Type, mode exprMode, flags flags) { 10594 fld := n.Field 10595 pe := n.PostfixExpression.Operand.Type() 10596 switch { 10597 case pe.Kind() == cc.Array: 10598 panic(todo("", p.pos(n))) 10599 case n.Operand.Type().IsBitFieldType(): 10600 panic(todo("", p.pos(n))) 10601 default: 10602 if fld.IsBitField() { 10603 p.err(&n.Token2, "internal error, wrong function for accessing a bit field: %s", n.Token2.Value) 10604 } 10605 p.w("*(*%s)(unsafe.Pointer(", p.typ(n, n.Operand.Type())) 10606 p.postfixExpression(f, n.PostfixExpression, pe, exprAddrOf, flags) 10607 nonZeroUintptr(fld.Offset()) 10608 p.w("))") 10609 } 10610 } 10611 10612 func (p *project) postfixExpressionLValueSelectStruct(f *function, n *cc.PostfixExpression, t cc.Type, mode exprMode, flags flags) { 10613 // PostfixExpression '.' IDENTIFIER 10614 fld := n.Field 10615 switch { 10616 case n.Operand.Type().IsBitFieldType(): 10617 panic(todo("", p.pos(n))) 10618 default: 10619 if fld.IsBitField() { 10620 p.err(&n.Token2, "internal error, wrong function for accessing a bit field: %s", n.Token2.Value) 10621 } 10622 pe := n.PostfixExpression.Operand.Type() 10623 p.postfixExpression(f, n.PostfixExpression, pe, exprSelect, flags) 10624 p.w(".%s", p.fieldName(n, n.Token2.Value)) 10625 } 10626 } 10627 10628 func (p *project) postfixExpressionIncDec(f *function, n *cc.PostfixExpression, oper, oper2 string, t cc.Type, mode exprMode, flags flags) { 10629 switch mode { 10630 case exprVoid: 10631 p.postfixExpressionIncDecVoid(f, n, oper, oper2, t, mode, flags) 10632 case exprLValue: 10633 p.postfixExpressionIncDecLValue(f, n, oper, oper2, t, mode, flags) 10634 case exprValue: 10635 p.postfixExpressionIncDecValue(f, n, oper, oper2, t, mode, flags) 10636 default: 10637 panic(todo("", mode)) 10638 } 10639 } 10640 10641 func (p *project) postfixExpressionIncDecValue(f *function, n *cc.PostfixExpression, oper, oper2 string, t cc.Type, mode exprMode, flags flags) { 10642 // PostfixExpression "++" 10643 pe := n.PostfixExpression.Operand.Type() 10644 switch k := p.opKind(f, n.PostfixExpression, pe); k { 10645 case opNormal: 10646 p.postfixExpressionIncDecValueNormal(f, n, oper, oper2, t, mode, flags) 10647 case opBitfield: 10648 p.postfixExpressionIncDecValueBitfield(f, n, oper, oper2, t, mode, flags) 10649 case opArrayParameter: 10650 p.postfixExpressionIncDecValueArrayParameter(f, n, oper, oper2, t, mode, flags) 10651 default: 10652 panic(todo("", n.Position(), pe, pe.Kind(), k)) 10653 } 10654 } 10655 10656 func (p *project) postfixExpressionIncDecValueArrayParameter(f *function, n *cc.PostfixExpression, oper, oper2 string, t cc.Type, mode exprMode, flags flags) { 10657 // PostfixExpression "++" 10658 pe := n.PostfixExpression.Operand.Type() 10659 defer p.w("%s", p.convert(n, n.PostfixExpression.Operand, t, flags)) 10660 x := "Dec" 10661 if oper == "++" { 10662 x = "Inc" 10663 } 10664 p.w("%sPost%s%s(&", p.task.crt, x, p.helperType(n, pe.Decay())) 10665 p.postfixExpression(f, n.PostfixExpression, pe, exprLValue, flags) 10666 p.w(", %d)", p.incDelta(n.PostfixExpression, pe)) 10667 } 10668 10669 func (p *project) postfixExpressionIncDecValueBitfield(f *function, n *cc.PostfixExpression, oper, oper2 string, t cc.Type, mode exprMode, flags flags) { 10670 // PostfixExpression "++" 10671 pe := n.PostfixExpression.Operand.Type() 10672 defer p.w("%s", p.convert(n, n.PostfixExpression.Operand, t, flags)) 10673 x := "Dec" 10674 if oper == "++" { 10675 x = "Inc" 10676 } 10677 bf := pe.BitField() 10678 p.w("%sPost%sBitFieldPtr%d%s(", p.task.crt, x, bf.BitFieldBlockWidth(), p.bfHelperType(pe)) 10679 p.postfixExpression(f, n.PostfixExpression, pe, exprAddrOf, flags) 10680 p.w(", %d, %d, %d, %#x)", p.incDelta(n.PostfixExpression, pe), bf.BitFieldBlockWidth(), bf.BitFieldOffset(), bf.Mask()) 10681 } 10682 10683 func (p *project) postfixExpressionIncDecValueNormal(f *function, n *cc.PostfixExpression, oper, oper2 string, t cc.Type, mode exprMode, flags flags) { 10684 // PostfixExpression "++" 10685 pe := n.PostfixExpression.Operand.Type() 10686 defer p.w("%s", p.convert(n, n.PostfixExpression.Operand, t, flags)) 10687 x := "Dec" 10688 if oper == "++" { 10689 x = "Inc" 10690 } 10691 if d := n.PostfixExpression.Declarator(); d != nil && p.isVolatileOrAtomic(d) { 10692 p.w("%sPost%sAtomic%s(&", p.task.crt, x, p.helperType(n, pe)) 10693 var local *local 10694 var tld *tld 10695 if f != nil { 10696 local = f.locals[d] 10697 } 10698 if local == nil { 10699 tld = p.tlds[d] 10700 } 10701 switch { 10702 case local != nil: 10703 p.w("%s", local.name) 10704 case tld != nil: 10705 p.w("%s", tld.name) 10706 default: 10707 panic(todo("")) 10708 } 10709 p.w(", %d)", p.incDelta(n.PostfixExpression, pe)) 10710 return 10711 } 10712 10713 p.w("%sPost%s%s(&", p.task.crt, x, p.helperType(n, pe)) 10714 p.postfixExpression(f, n.PostfixExpression, pe, exprLValue, flags) 10715 p.w(", %d)", p.incDelta(n.PostfixExpression, pe)) 10716 } 10717 10718 func (p *project) postfixExpressionIncDecLValue(f *function, n *cc.PostfixExpression, oper, oper2 string, t cc.Type, mode exprMode, flags flags) { 10719 switch k := p.opKind(f, n, n.Operand.Type()); k { 10720 case opNormal: 10721 p.postfixExpressionIncDecLValueNormal(f, n, oper, oper2, t, mode, flags) 10722 default: 10723 panic(todo("", n.Position(), k)) 10724 } 10725 } 10726 10727 func (p *project) postfixExpressionIncDecLValueNormal(f *function, n *cc.PostfixExpression, oper, oper2 string, t cc.Type, mode exprMode, flags flags) { 10728 pe := n.PostfixExpression.Operand.Type() 10729 defer p.w("%s", p.convert(n, n.PostfixExpression.Operand, t, flags)) 10730 x := "Dec" 10731 if oper == "++" { 10732 x = "Inc" 10733 } 10734 p.w("%sPost%s%s(&", p.task.crt, x, p.helperType(n, pe)) 10735 p.postfixExpression(f, n.PostfixExpression, pe, exprLValue, flags) 10736 p.w(", %d)", p.incDelta(n.PostfixExpression, pe)) 10737 } 10738 10739 func (p *project) postfixExpressionIncDecVoid(f *function, n *cc.PostfixExpression, oper, oper2 string, t cc.Type, mode exprMode, flags flags) { 10740 switch k := p.opKind(f, n, n.Operand.Type()); k { 10741 case opNormal: 10742 p.postfixExpressionIncDecVoidNormal(f, n, oper, oper2, t, mode, flags) 10743 case opBitfield: 10744 p.postfixExpressionIncDec(f, n, oper, oper2, t, exprValue, flags) 10745 default: 10746 panic(todo("", n.Position(), k)) 10747 } 10748 } 10749 10750 func (p *project) postfixExpressionIncDecVoidNormal(f *function, n *cc.PostfixExpression, oper, oper2 string, t cc.Type, mode exprMode, flags flags) { 10751 if d := n.PostfixExpression.Declarator(); d != nil && p.isVolatileOrAtomic(d) { 10752 switch d.Type().Size() { 10753 case 4, 8: 10754 if !d.Type().IsIntegerType() { 10755 p.err(n, "unsupported volatile declarator type: %v", d.Type()) 10756 return 10757 } 10758 10759 if f != nil { 10760 if local := f.locals[d]; local != nil { 10761 if local.isPinned { 10762 panic(todo("")) 10763 } 10764 10765 p.w("atomic.Add%s(&%s, ", p.helperType(n, d.Type()), local.name) 10766 switch oper { 10767 case "++": 10768 // ok 10769 case "--": 10770 p.w("-") 10771 default: 10772 p.err(n, "unsupported volatile declarator operation: %v", oper) 10773 } 10774 p.w("%d)", p.incDelta(n, d.Type())) 10775 return 10776 } 10777 } 10778 10779 if tld := p.tlds[d]; tld != nil { 10780 p.w("atomic.Add%s(&%s, ", p.helperType(n, d.Type()), tld.name) 10781 switch oper { 10782 case "++": 10783 // ok 10784 case "--": 10785 p.w("-") 10786 default: 10787 p.err(n, "unsupported volatile declarator operation: %v", oper) 10788 } 10789 p.w("%d)", p.incDelta(n, d.Type())) 10790 return 10791 } 10792 10793 panic(todo("", n.Position(), d.Position())) 10794 default: 10795 p.err(n, "unsupported volatile declarator size: %v", d.Type().Size()) 10796 return 10797 } 10798 } 10799 10800 pe := n.PostfixExpression.Operand.Type().Decay() 10801 p.postfixExpression(f, n.PostfixExpression, pe, exprLValue, flags) 10802 if pe.IsIntegerType() || pe.Kind() == cc.Ptr && p.incDelta(n, pe) == 1 { 10803 p.w("%s", oper) 10804 return 10805 } 10806 10807 switch pe.Kind() { 10808 case cc.Ptr, cc.Float, cc.Double: 10809 p.w("%s %d", oper2, p.incDelta(n, pe)) 10810 return 10811 } 10812 10813 panic(todo("", n.Position(), pe, pe.Kind())) 10814 } 10815 10816 func (p *project) incDelta(n cc.Node, t cc.Type) uintptr { 10817 if t.IsArithmeticType() { 10818 return 1 10819 } 10820 10821 if t.Kind() == cc.Ptr || t.Kind() == cc.Array { 10822 return t.Elem().Size() 10823 } 10824 10825 panic(todo("", n.Position(), t.Kind())) 10826 } 10827 10828 func (p *project) bitFldOff(t cc.Type, tok cc.Token) { 10829 var off uintptr 10830 fld, ok := t.FieldByName(tok.Value) 10831 switch { 10832 case ok && !fld.IsBitField(): 10833 panic(todo("%v: internal error: bitFdlOff must not be used with non bit fields", origin(2))) 10834 case !ok: 10835 p.err(&tok, "uknown field: %s", tok.Value) 10836 default: 10837 off = fld.BitFieldBlockFirst().Offset() 10838 } 10839 if off != 0 { 10840 p.w("+%d", off) 10841 } 10842 p.w("/* &.%s */", tok.Value) 10843 } 10844 10845 func (p *project) fldOff(t cc.Type, tok cc.Token) { 10846 if t.Kind() == cc.Ptr { 10847 t = t.Elem() 10848 } 10849 var off uintptr 10850 fld, ok := t.FieldByName(tok.Value) 10851 switch { 10852 case ok && fld.IsBitField(): 10853 panic(todo("%v: internal error: fdlOff must not be used with bit fields", origin(2))) 10854 case !ok: 10855 p.err(&tok, "uknown field: %s", tok.Value) 10856 default: 10857 off = fld.Offset() 10858 } 10859 if off != 0 { 10860 p.w("+%d", off) 10861 } 10862 p.w("/* &.%s */", tok.Value) 10863 } 10864 10865 func (p *project) postfixExpressionCall(f *function, n *cc.PostfixExpression, t cc.Type, mode exprMode, flags flags) { 10866 // PostfixExpression '(' ArgumentExpressionList ')' 10867 switch mode { 10868 case exprVoid: 10869 p.postfixExpressionCallVoid(f, n, t, mode, flags) 10870 case exprValue: 10871 p.postfixExpressionCallValue(f, n, t, mode, flags) 10872 case exprBool: 10873 p.postfixExpressionCallBool(f, n, t, mode, flags) 10874 default: 10875 panic(todo("", mode)) 10876 } 10877 } 10878 10879 func (p *project) postfixExpressionCallBool(f *function, n *cc.PostfixExpression, t cc.Type, mode exprMode, flags flags) { 10880 // PostfixExpression '(' ArgumentExpressionList ')' 10881 p.w("(") 10882 defer p.w(")") 10883 defer p.w(" != 0") 10884 if d := n.PostfixExpression.Declarator(); d != nil { 10885 switch d.Name() { 10886 case idVaArg: 10887 if !f.vaType.IsScalarType() { 10888 panic(todo("", f.vaType)) 10889 } 10890 10891 lhs := n.ArgumentExpressionList.AssignmentExpression 10892 p.w("%sVa%s(&", p.task.crt, p.helperType(n, f.vaType)) 10893 p.assignmentExpression(f, lhs, lhs.Operand.Type(), exprLValue, flags) 10894 p.w(")") 10895 return 10896 case idAtomicLoadN: 10897 p.atomicLoadN(f, n, t, mode, flags) 10898 return 10899 case idBuiltinConstantPImpl: 10900 p.w("%v", n.Operand.Value()) 10901 return 10902 } 10903 } 10904 10905 var va uintptr 10906 if f != nil { 10907 va = f.vaLists[n] 10908 } 10909 p.postfixExpression(f, n.PostfixExpression, n.PostfixExpression.Operand.Type(), exprFunc, flags) 10910 p.argumentExpressionList(f, n.PostfixExpression, n.ArgumentExpressionList, va) 10911 } 10912 10913 func (p *project) postfixExpressionCallValue(f *function, n *cc.PostfixExpression, t cc.Type, mode exprMode, flags flags) { 10914 // PostfixExpression '(' ArgumentExpressionList ')' 10915 defer p.w("%s", p.convert(n, n.Operand, t, flags)) 10916 if d := n.PostfixExpression.Declarator(); d != nil { 10917 switch d.Name() { 10918 case idVaEnd: 10919 p.w("_ = ") 10920 arg := n.ArgumentExpressionList.AssignmentExpression 10921 p.assignmentExpression(f, arg, arg.Operand.Type(), exprValue, flags) 10922 return 10923 case idVaStart: 10924 lhs := n.ArgumentExpressionList.AssignmentExpression 10925 p.assignmentExpression(f, lhs, lhs.Operand.Type(), exprLValue, flags) 10926 p.w(" = %s", f.vaName) 10927 return 10928 case idVaArg: 10929 if !f.vaType.IsScalarType() { 10930 panic(todo("", f.vaType)) 10931 } 10932 10933 lhs := n.ArgumentExpressionList.AssignmentExpression 10934 p.w("%sVa%s(&", p.task.crt, p.helperType(n, f.vaType)) 10935 p.assignmentExpression(f, lhs, lhs.Operand.Type(), exprLValue, flags) 10936 p.w(")") 10937 return 10938 case idAtomicLoadN: 10939 p.atomicLoadN(f, n, t, mode, flags) 10940 return 10941 case idAddOverflow: 10942 p.addOverflow(f, n, t, mode, flags) 10943 return 10944 case idSubOverflow: 10945 p.subOverflow(f, n, t, mode, flags) 10946 return 10947 case idMulOverflow: 10948 p.mulOverflow(f, n, t, mode, flags) 10949 return 10950 case idBuiltinConstantPImpl: 10951 p.w("%v", n.Operand.Value()) 10952 return 10953 } 10954 } 10955 var va uintptr 10956 if f != nil { 10957 va = f.vaLists[n] 10958 } 10959 p.postfixExpression(f, n.PostfixExpression, n.PostfixExpression.Operand.Type(), exprFunc, flags) 10960 p.argumentExpressionList(f, n.PostfixExpression, n.ArgumentExpressionList, va) 10961 } 10962 10963 // bool __builtin_mul_overflow (type1 a, type2 b, type3 *res) 10964 func (p *project) mulOverflow(f *function, n *cc.PostfixExpression, t cc.Type, mode exprMode, flags flags) { 10965 args := p.argList(n.ArgumentExpressionList) 10966 if len(args) != 3 { 10967 p.err(n, "expected 3 arguments in call to __builtin_mul_overflow") 10968 return 10969 } 10970 10971 pt := args[2].Operand.Type() 10972 if pt.Kind() != cc.Ptr { 10973 p.err(n, "invalid argument of __builtin_mul_overflow (expected pointer): %s", pt) 10974 return 10975 } 10976 10977 vt := pt.Elem() 10978 switch { 10979 case vt.IsIntegerType(): 10980 switch vt.Size() { 10981 case 1, 2, 4, 8, 16: 10982 p.w("%sX__builtin_mul_overflow%s", p.task.crt, p.helperType(n, vt)) 10983 default: 10984 p.err(n, "invalid argument of __builtin_mul_overflow: %v, elem kind %v", pt, vt.Kind()) 10985 return 10986 } 10987 p.w("(%s", f.tlsName) 10988 types := []cc.Type{vt, vt, pt} 10989 for i, v := range args[:3] { 10990 p.w(", ") 10991 p.assignmentExpression(f, v, types[i], exprValue, flags) 10992 } 10993 p.w(")") 10994 return 10995 } 10996 10997 p.err(n, "invalid arguments of __builtin_mul_overflow: (%v, %v, %v)", args[0].Operand.Type(), args[1].Operand.Type(), args[2].Operand.Type()) 10998 } 10999 11000 // bool __builtin_sub_overflow (type1 a, type2 b, type3 *res) 11001 func (p *project) subOverflow(f *function, n *cc.PostfixExpression, t cc.Type, mode exprMode, flags flags) { 11002 args := p.argList(n.ArgumentExpressionList) 11003 if len(args) != 3 { 11004 p.err(n, "expected 3 arguments in call to __builtin_sub_overflow") 11005 return 11006 } 11007 11008 pt := args[2].Operand.Type() 11009 if pt.Kind() != cc.Ptr { 11010 p.err(n, "invalid argument of __builtin_sub_overflow (expected pointer): %s", pt) 11011 return 11012 } 11013 11014 vt := pt.Elem() 11015 switch { 11016 case vt.IsIntegerType(): 11017 switch vt.Size() { 11018 case 1, 2, 4, 8: 11019 p.w("%sX__builtin_sub_overflow%s", p.task.crt, p.helperType(n, vt)) 11020 default: 11021 p.err(n, "invalid argument of __builtin_sub_overflow: %v, elem kind %v", pt, vt.Kind()) 11022 return 11023 } 11024 p.w("(%s", f.tlsName) 11025 types := []cc.Type{vt, vt, pt} 11026 for i, v := range args[:3] { 11027 p.w(", ") 11028 p.assignmentExpression(f, v, types[i], exprValue, flags) 11029 } 11030 p.w(")") 11031 return 11032 } 11033 11034 p.err(n, "invalid arguments of __builtin_sub_overflow: (%v, %v, %v)", args[0].Operand.Type(), args[1].Operand.Type(), args[2].Operand.Type()) 11035 } 11036 11037 // bool __builtin_add_overflow (type1 a, type2 b, type3 *res) 11038 func (p *project) addOverflow(f *function, n *cc.PostfixExpression, t cc.Type, mode exprMode, flags flags) { 11039 args := p.argList(n.ArgumentExpressionList) 11040 if len(args) != 3 { 11041 p.err(n, "expected 3 arguments in call to __builtin_add_overflow") 11042 return 11043 } 11044 11045 pt := args[2].Operand.Type() 11046 if pt.Kind() != cc.Ptr { 11047 p.err(n, "invalid argument of __builtin_add_overflow (expected pointer): %s", pt) 11048 return 11049 } 11050 11051 vt := pt.Elem() 11052 switch { 11053 case vt.IsIntegerType(): 11054 switch vt.Size() { 11055 case 1, 2, 4, 8: 11056 p.w("%sX__builtin_add_overflow%s", p.task.crt, p.helperType(n, vt)) 11057 default: 11058 p.err(n, "invalid argument of __builtin_add_overflow: %v, elem kind %v", pt, vt.Kind()) 11059 return 11060 } 11061 p.w("(%s", f.tlsName) 11062 types := []cc.Type{vt, vt, pt} 11063 for i, v := range args[:3] { 11064 p.w(", ") 11065 p.assignmentExpression(f, v, types[i], exprValue, flags) 11066 } 11067 p.w(")") 11068 return 11069 } 11070 11071 p.err(n, "invalid arguments of __builtin_add_overflow: (%v, %v, %v)", args[0].Operand.Type(), args[1].Operand.Type(), args[2].Operand.Type()) 11072 } 11073 11074 // type __atomic_load_n (type *ptr, int memorder) 11075 func (p *project) atomicLoadN(f *function, n *cc.PostfixExpression, t cc.Type, mode exprMode, flags flags) { 11076 args := p.argList(n.ArgumentExpressionList) 11077 if len(args) != 2 { 11078 p.err(n, "expected 2 arguments in call to __atomic_load_n") 11079 return 11080 } 11081 11082 pt := args[0].Operand.Type() 11083 if pt.Kind() != cc.Ptr { 11084 p.err(n, "invalid argument of __atomic_load_n (expected pointer): %s", pt) 11085 return 11086 } 11087 11088 vt := pt.Elem() 11089 switch { 11090 case vt.IsIntegerType(): 11091 var s string 11092 switch { 11093 case vt.IsSignedType(): 11094 s = "Int" 11095 default: 11096 s = "Uint" 11097 } 11098 switch vt.Size() { 11099 case 2, 4, 8: 11100 p.w("%sAtomicLoadN%s%d", p.task.crt, s, 8*vt.Size()) 11101 default: 11102 p.err(n, "invalid argument of __atomic_load_n: %v, elem kind %v", pt, vt.Kind()) 11103 return 11104 } 11105 types := []cc.Type{pt, p.intType} 11106 p.w("(") 11107 for i, v := range args[:2] { 11108 if i != 0 { 11109 p.w(", ") 11110 } 11111 p.assignmentExpression(f, v, types[i], exprValue, flags) 11112 } 11113 p.w(")") 11114 return 11115 case vt.Kind() == cc.Ptr: 11116 panic(todo("", pt, vt)) 11117 } 11118 11119 p.err(n, "invalid first argument of __atomic_load_n: %v, elem kind %v", pt, vt.Kind()) 11120 } 11121 11122 func (p *project) postfixExpressionCallVoid(f *function, n *cc.PostfixExpression, t cc.Type, mode exprMode, flags flags) { 11123 // PostfixExpression '(' ArgumentExpressionList ')' 11124 if d := n.PostfixExpression.Declarator(); d != nil { 11125 switch d.Name() { 11126 case idVaEnd: 11127 p.w("_ = ") 11128 arg := n.ArgumentExpressionList.AssignmentExpression 11129 p.assignmentExpression(f, arg, arg.Operand.Type(), exprValue, flags) 11130 return 11131 case idVaStart: 11132 lhs := n.ArgumentExpressionList.AssignmentExpression 11133 p.assignmentExpression(f, lhs, lhs.Operand.Type(), exprLValue, flags) 11134 p.w(" = %s", f.vaName) 11135 return 11136 case idVaArg: 11137 if !f.vaType.IsScalarType() { 11138 panic(todo("", f.vaType)) 11139 } 11140 11141 lhs := n.ArgumentExpressionList.AssignmentExpression 11142 p.w("%sVa%s(&", p.task.crt, p.helperType(n, f.vaType)) 11143 p.assignmentExpression(f, lhs, lhs.Operand.Type(), exprLValue, flags) 11144 p.w(")") 11145 return 11146 case idAtomicStoreN: 11147 p.atomicStoreN(f, n, t, mode, flags) 11148 return 11149 case idMulOverflow: 11150 p.mulOverflow(f, n, t, mode, flags) 11151 return 11152 } 11153 } 11154 var va uintptr 11155 if f != nil { 11156 va = f.vaLists[n] 11157 } 11158 p.postfixExpression(f, n.PostfixExpression, n.PostfixExpression.Operand.Type(), exprFunc, flags) 11159 p.argumentExpressionList(f, n.PostfixExpression, n.ArgumentExpressionList, va) 11160 } 11161 11162 // void __atomic_store_n (type *ptr, type val, int memorder) 11163 func (p *project) atomicStoreN(f *function, n *cc.PostfixExpression, t cc.Type, mode exprMode, flags flags) { 11164 args := p.argList(n.ArgumentExpressionList) 11165 if len(args) != 3 { 11166 p.err(n, "expected 3 arguments in call to __atomic_store_n") 11167 return 11168 } 11169 11170 pt := args[0].Operand.Type() 11171 if pt.Kind() != cc.Ptr { 11172 p.err(n, "invalid first argument of __atomic_store_n (expected pointer): %s", pt) 11173 return 11174 } 11175 11176 vt := args[1].Operand.Type() 11177 switch { 11178 case vt.IsIntegerType(): 11179 var s string 11180 switch { 11181 case vt.IsSignedType(): 11182 s = "Int" 11183 default: 11184 s = "Uint" 11185 } 11186 switch vt.Size() { 11187 case 2, 4, 8: 11188 p.w("%sAtomicStoreN%s%d", p.task.crt, s, 8*vt.Size()) 11189 default: 11190 p.err(n, "invalid arguments of __atomic_store_n: (%v, %v), element kind %v", pt, vt, vt.Kind()) 11191 return 11192 } 11193 p.w("(") 11194 types := []cc.Type{pt, vt, p.intType} 11195 for i, v := range args[:3] { 11196 if i != 0 { 11197 p.w(", ") 11198 } 11199 if i == 1 { 11200 p.w("%s(", strings.ToLower(p.helperType(n, vt))) 11201 } 11202 p.assignmentExpression(f, v, types[i], exprValue, flags) 11203 if i == 1 { 11204 p.w(")") 11205 } 11206 } 11207 p.w(")") 11208 return 11209 case vt.Kind() == cc.Ptr: 11210 panic(todo("", pt, vt)) 11211 } 11212 11213 p.err(n, "invalid arguments of __atomic_store_n: (%v, %v), element kind %v", pt, vt, vt.Kind()) 11214 } 11215 11216 func (p *project) argList(n *cc.ArgumentExpressionList) (r []*cc.AssignmentExpression) { 11217 for ; n != nil; n = n.ArgumentExpressionList { 11218 r = append(r, n.AssignmentExpression) 11219 } 11220 return r 11221 } 11222 11223 func (p *project) argumentExpressionList(f *function, pe *cc.PostfixExpression, n *cc.ArgumentExpressionList, bpOff uintptr) { 11224 switch { 11225 case f == nil: 11226 p.w("(nil") 11227 default: 11228 p.w("(%s", f.tlsName) 11229 } 11230 ft := funcType(pe.Operand.Type()) 11231 isVariadic := ft.IsVariadic() 11232 params := ft.Parameters() 11233 if len(params) == 1 && params[0].Type().Kind() == cc.Void { 11234 params = nil 11235 } 11236 var args []*cc.AssignmentExpression 11237 for ; n != nil; n = n.ArgumentExpressionList { 11238 args = append(args, n.AssignmentExpression) 11239 } 11240 if len(args) < len(params) { 11241 panic(todo("", p.pos(n))) 11242 } 11243 11244 va := true 11245 if len(args) > len(params) && !isVariadic { 11246 var a []string 11247 for _, v := range args { 11248 a = append(a, v.Operand.Type().String()) 11249 } 11250 sargs := strings.Join(a, ",") 11251 switch d := pe.Declarator(); { 11252 case d == nil: 11253 p.err(pe, "too many arguments (%s) in call to %s", sargs, ft) 11254 default: 11255 p.err(pe, "too many arguments (%s) in call to %s of type %s", sargs, d.Name(), ft) 11256 } 11257 va = false 11258 } 11259 11260 paren := "" 11261 for i, arg := range args { 11262 p.w(",%s", tidyComment(" ", arg)) 11263 mode := exprValue 11264 if at := arg.Operand.Type(); at.Kind() == cc.Array { 11265 mode = exprDecay 11266 } 11267 switch { 11268 case i < len(params): 11269 switch pt := params[i].Type(); { 11270 case isTransparentUnion(params[i].Type()): 11271 p.callArgTransparentUnion(f, arg, pt) 11272 default: 11273 p.assignmentExpression(f, arg, arg.Promote(), mode, 0) 11274 } 11275 case va && i == len(params): 11276 p.w("%sVaList(%s%s, ", p.task.crt, f.bpName, nonZeroUintptr(bpOff)) 11277 paren = ")" 11278 fallthrough 11279 default: 11280 var flags flags 11281 if arg.Promote().IsIntegerType() { 11282 switch x := arg.Operand.Value().(type) { 11283 case cc.Int64Value: 11284 if x < mathutil.MinInt || x > mathutil.MaxInt { 11285 flags |= fForceConv 11286 } 11287 case cc.Uint64Value: 11288 if x > mathutil.MaxInt { 11289 flags |= fForceConv 11290 } 11291 } 11292 } 11293 p.assignmentExpression(f, arg, arg.Promote(), mode, flags) 11294 } 11295 } 11296 if isVariadic && len(args) == len(params) { 11297 p.w(", 0") 11298 } 11299 p.w("%s)", paren) 11300 } 11301 11302 // https://gcc.gnu.org/onlinedocs/gcc-3.3/gcc/Type-Attributes.html 11303 // 11304 // transparent_union 11305 // 11306 // This attribute, attached to a union type definition, indicates that any 11307 // function parameter having that union type causes calls to that function to 11308 // be treated in a special way. 11309 // 11310 // First, the argument corresponding to a transparent union type can be of any 11311 // type in the union; no cast is required. Also, if the union contains a 11312 // pointer type, the corresponding argument can be a null pointer constant or a 11313 // void pointer expression; and if the union contains a void pointer type, the 11314 // corresponding argument can be any pointer expression. If the union member 11315 // type is a pointer, qualifiers like const on the referenced type must be 11316 // respected, just as with normal pointer conversions. 11317 // 11318 // Second, the argument is passed to the function using the calling conventions 11319 // of first member of the transparent union, not the calling conventions of the 11320 // union itself. All members of the union must have the same machine 11321 // representation; this is necessary for this argument passing to work 11322 // properly. 11323 // 11324 // Transparent unions are designed for library functions that have multiple 11325 // interfaces for compatibility reasons. For example, suppose the wait function 11326 // must accept either a value of type int * to comply with Posix, or a value of 11327 // type union wait * to comply with the 4.1BSD interface. If wait's parameter 11328 // were void *, wait would accept both kinds of arguments, but it would also 11329 // accept any other pointer type and this would make argument type checking 11330 // less useful. Instead, <sys/wait.h> might define the interface as follows: 11331 // 11332 // typedef union 11333 // { 11334 // int *__ip; 11335 // union wait *__up; 11336 // } wait_status_ptr_t __attribute__ ((__transparent_union__)); 11337 // 11338 // pid_t wait (wait_status_ptr_t); 11339 // 11340 // This interface allows either int * or union wait * arguments to be passed, 11341 // using the int * calling convention. The program can call wait with arguments 11342 // of either type: 11343 // 11344 // int w1 () { int w; return wait (&w); } 11345 // int w2 () { union wait w; return wait (&w); } 11346 // 11347 // With this interface, wait's implementation might look like this: 11348 // 11349 // pid_t wait (wait_status_ptr_t p) 11350 // { 11351 // return waitpid (-1, p.__ip, 0); 11352 // } 11353 func (p *project) callArgTransparentUnion(f *function, n *cc.AssignmentExpression, pt cc.Type) { 11354 if pt.Kind() != cc.Union { 11355 panic(todo("internal error")) 11356 } 11357 11358 ot := n.Operand.Type() 11359 switch k := pt.UnionCommon(); k { 11360 case cc.Ptr: 11361 if ot.Kind() != k { 11362 panic(todo("", n.Position(), k, pt)) 11363 } 11364 11365 p.assignmentExpression(f, n, ot, exprValue, 0) 11366 default: 11367 panic(todo("", n.Position(), k, pt)) 11368 } 11369 } 11370 11371 func isTransparentUnion(t cc.Type) (r bool) { 11372 for _, v := range attrs(t) { 11373 cc.Inspect(v, func(n cc.Node, _ bool) bool { 11374 if x, ok := n.(*cc.AttributeValue); ok && x.Token.Value == idTransparentUnion { 11375 r = true 11376 return false 11377 } 11378 11379 return true 11380 }) 11381 } 11382 return r 11383 } 11384 11385 func attrs(t cc.Type) []*cc.AttributeSpecifier { 11386 if a := t.Attributes(); len(a) != 0 { 11387 return a 11388 } 11389 11390 if t.IsAliasType() { 11391 if a := t.Alias().Attributes(); len(a) != 0 { 11392 return a 11393 } 11394 11395 return t.AliasDeclarator().Type().Attributes() 11396 } 11397 11398 return nil 11399 } 11400 11401 func (p *project) nzUintptr(n cc.Node, f func(), op cc.Operand) { 11402 if op.Type().IsIntegerType() { 11403 switch { 11404 case op.IsZero(): 11405 return 11406 case op.Value() != nil: 11407 switch x := op.Value().(type) { 11408 case cc.Int64Value: 11409 if x > 0 && uint64(x) <= 1<<(8*p.ptrSize)-1 { 11410 p.w("+%d", x) 11411 return 11412 } 11413 case cc.Uint64Value: 11414 if uint64(x) <= 1<<(8*p.ptrSize)-1 { 11415 p.w("+%d", x) 11416 return 11417 } 11418 } 11419 11420 p.w(" +%sUintptrFrom%s(", p.task.crt, p.helperType(n, op.Type())) 11421 default: 11422 p.w(" +uintptr(") 11423 } 11424 11425 f() 11426 p.w(")") 11427 return 11428 } 11429 11430 panic(todo("", p.pos(n))) 11431 } 11432 11433 func (p *project) primaryExpression(f *function, n *cc.PrimaryExpression, t cc.Type, mode exprMode, flags flags) { 11434 switch mode { 11435 case exprLValue: 11436 p.primaryExpressionLValue(f, n, t, mode, flags) 11437 case exprValue: 11438 p.primaryExpressionValue(f, n, t, mode, flags) 11439 case exprFunc: 11440 p.primaryExpressionFunc(f, n, t, mode, flags) 11441 case exprAddrOf: 11442 p.primaryExpressionAddrOf(f, n, t, mode, flags) 11443 case exprSelect: 11444 p.primaryExpressionSelect(f, n, t, mode, flags) 11445 case exprPSelect: 11446 p.primaryExpressionPSelect(f, n, t, mode, flags) 11447 case exprBool: 11448 p.primaryExpressionBool(f, n, t, mode, flags) 11449 case exprVoid: 11450 p.primaryExpressionVoid(f, n, t, mode, flags) 11451 case exprDecay: 11452 p.primaryExpressionDecay(f, n, t, mode, flags) 11453 default: 11454 panic(todo("", n.Position(), mode)) 11455 } 11456 } 11457 11458 func (p *project) primaryExpressionDecay(f *function, n *cc.PrimaryExpression, t cc.Type, mode exprMode, flags flags) { 11459 switch n.Case { 11460 case cc.PrimaryExpressionIdent: // IDENTIFIER 11461 switch d := n.Declarator(); { 11462 case d != nil: 11463 p.declarator(n, f, d, t, mode, flags) 11464 default: 11465 panic(todo("", p.pos(n))) 11466 } 11467 case cc.PrimaryExpressionInt: // INTCONST 11468 p.intConst(n, n.Token.Src.String(), n.Operand, t, flags) 11469 case cc.PrimaryExpressionFloat: // FLOATCONST 11470 panic(todo("", p.pos(n))) 11471 case cc.PrimaryExpressionEnum: // ENUMCONST 11472 panic(todo("", p.pos(n))) 11473 case cc.PrimaryExpressionChar: // CHARCONST 11474 panic(todo("", p.pos(n))) 11475 case cc.PrimaryExpressionLChar: // LONGCHARCONST 11476 panic(todo("", p.pos(n))) 11477 case cc.PrimaryExpressionString: // STRINGLITERAL 11478 p.w("%s", p.stringLiteral(n.Operand.Value())) 11479 case cc.PrimaryExpressionLString: // LONGSTRINGLITERAL 11480 p.w("%s", p.wideStringLiteral(n.Operand.Value(), 0)) 11481 case cc.PrimaryExpressionExpr: // '(' Expression ')' 11482 p.expression(f, n.Expression, t, mode, flags) 11483 case cc.PrimaryExpressionStmt: // '(' CompoundStatement ')' 11484 p.err(n, "statement expressions not supported") 11485 default: 11486 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 11487 } 11488 } 11489 11490 func (p *project) primaryExpressionVoid(f *function, n *cc.PrimaryExpression, t cc.Type, mode exprMode, flags flags) { 11491 11492 switch n.Case { 11493 case cc.PrimaryExpressionIdent: // IDENTIFIER 11494 p.w("_ = ") 11495 p.primaryExpression(f, n, n.Operand.Type(), exprValue, flags) 11496 case cc.PrimaryExpressionInt, // INTCONST 11497 cc.PrimaryExpressionFloat, // FLOATCONST 11498 cc.PrimaryExpressionEnum, // ENUMCONST 11499 cc.PrimaryExpressionChar, // CHARCONST 11500 cc.PrimaryExpressionLChar, // LONGCHARCONST 11501 cc.PrimaryExpressionString, // STRINGLITERAL 11502 cc.PrimaryExpressionLString: // LONGSTRINGLITERAL 11503 11504 // nop 11505 case cc.PrimaryExpressionExpr: // '(' Expression ')' 11506 p.expression(f, n.Expression, n.Expression.Operand.Type(), mode, flags) 11507 case cc.PrimaryExpressionStmt: // '(' CompoundStatement ')' 11508 p.compoundStatement(f, n.CompoundStatement, "", true, false, 0) 11509 default: 11510 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 11511 } 11512 } 11513 11514 func (p *project) primaryExpressionBool(f *function, n *cc.PrimaryExpression, t cc.Type, mode exprMode, flags flags) { 11515 if n.Case != cc.PrimaryExpressionExpr { 11516 p.w("(") 11517 defer p.w(")") 11518 } 11519 11520 if n.Case != cc.PrimaryExpressionExpr { 11521 defer p.w(" != 0") 11522 } 11523 switch n.Case { 11524 case cc.PrimaryExpressionIdent: // IDENTIFIER 11525 switch d := n.Declarator(); { 11526 case d != nil: 11527 p.declarator(n, f, d, d.Type(), exprValue, 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, n.Operand.Type(), 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 p.charConst(n, n.Token.Src.String(), n.Operand, t, flags) 11541 case cc.PrimaryExpressionString: // STRINGLITERAL 11542 p.w(" 1 ") 11543 case cc.PrimaryExpressionLString: // LONGSTRINGLITERAL 11544 panic(todo("", p.pos(n))) 11545 case cc.PrimaryExpressionExpr: // '(' Expression ')' 11546 p.w("(") 11547 defer p.w(")") 11548 p.expression(f, n.Expression, t, mode, flags) 11549 case cc.PrimaryExpressionStmt: // '(' CompoundStatement ')' 11550 p.w("func() %v {", p.typ(n, n.CompoundStatement.Operand.Type())) 11551 p.compoundStatement(f, n.CompoundStatement, "", true, false, exprValue) 11552 p.w("}()") 11553 default: 11554 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 11555 } 11556 } 11557 11558 func (p *project) primaryExpressionPSelect(f *function, n *cc.PrimaryExpression, t cc.Type, mode exprMode, flags flags) { 11559 switch n.Case { 11560 case cc.PrimaryExpressionIdent: // IDENTIFIER 11561 switch d := n.Declarator(); { 11562 case d != nil: 11563 switch k := p.declaratorKind(d); k { 11564 case opArray: 11565 panic(todo("", p.pos(n))) 11566 p.primaryExpression(f, n, t, exprDecay, flags) 11567 default: 11568 p.declarator(n, f, d, t, mode, flags) 11569 } 11570 default: 11571 panic(todo("", p.pos(n))) 11572 } 11573 case cc.PrimaryExpressionInt: // INTCONST 11574 panic(todo("", p.pos(n))) 11575 case cc.PrimaryExpressionFloat: // FLOATCONST 11576 panic(todo("", p.pos(n))) 11577 case cc.PrimaryExpressionEnum: // ENUMCONST 11578 panic(todo("", p.pos(n))) 11579 case cc.PrimaryExpressionChar: // CHARCONST 11580 panic(todo("", p.pos(n))) 11581 case cc.PrimaryExpressionLChar: // LONGCHARCONST 11582 panic(todo("", p.pos(n))) 11583 case cc.PrimaryExpressionString: // STRINGLITERAL 11584 panic(todo("", p.pos(n))) 11585 case cc.PrimaryExpressionLString: // LONGSTRINGLITERAL 11586 panic(todo("", p.pos(n))) 11587 case cc.PrimaryExpressionExpr: // '(' Expression ')' 11588 p.expression(f, n.Expression, t, mode, flags) 11589 case cc.PrimaryExpressionStmt: // '(' CompoundStatement ')' 11590 p.err(n, "statement expressions not supported") 11591 default: 11592 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 11593 } 11594 } 11595 11596 func (p *project) primaryExpressionSelect(f *function, n *cc.PrimaryExpression, t cc.Type, mode exprMode, flags flags) { 11597 switch n.Case { 11598 case cc.PrimaryExpressionIdent: // IDENTIFIER 11599 switch d := n.Declarator(); { 11600 case d != nil: 11601 p.declarator(n, f, d, t, mode, flags) 11602 default: 11603 panic(todo("", p.pos(n))) 11604 } 11605 case cc.PrimaryExpressionInt: // INTCONST 11606 panic(todo("", p.pos(n))) 11607 case cc.PrimaryExpressionFloat: // FLOATCONST 11608 panic(todo("", p.pos(n))) 11609 case cc.PrimaryExpressionEnum: // ENUMCONST 11610 panic(todo("", p.pos(n))) 11611 case cc.PrimaryExpressionChar: // CHARCONST 11612 panic(todo("", p.pos(n))) 11613 case cc.PrimaryExpressionLChar: // LONGCHARCONST 11614 panic(todo("", p.pos(n))) 11615 case cc.PrimaryExpressionString: // STRINGLITERAL 11616 panic(todo("", p.pos(n))) 11617 case cc.PrimaryExpressionLString: // LONGSTRINGLITERAL 11618 panic(todo("", p.pos(n))) 11619 case cc.PrimaryExpressionExpr: // '(' Expression ')' 11620 p.expression(f, n.Expression, t, mode, flags) 11621 case cc.PrimaryExpressionStmt: // '(' CompoundStatement ')' 11622 p.err(n, "statement expressions not supported") 11623 default: 11624 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 11625 } 11626 } 11627 11628 func (p *project) primaryExpressionAddrOf(f *function, n *cc.PrimaryExpression, t cc.Type, mode exprMode, flags flags) { 11629 switch n.Case { 11630 case cc.PrimaryExpressionIdent: // IDENTIFIER 11631 switch d := n.Declarator(); { 11632 case d != nil: 11633 p.declarator(n, f, d, t, mode, flags) 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 p.w("%s", p.stringLiteral(n.Operand.Value())) 11649 case cc.PrimaryExpressionLString: // LONGSTRINGLITERAL 11650 p.w("%s", p.wideStringLiteral(n.Operand.Value(), 0)) 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) primaryExpressionFunc(f *function, n *cc.PrimaryExpression, t cc.Type, mode exprMode, flags flags) { 11661 switch n.Case { 11662 case cc.PrimaryExpressionIdent: // IDENTIFIER 11663 p.fnVal(n, f, func() { p.primaryExpression(f, n, n.Operand.Type(), exprValue, flags) }, n.Declarator(), n.Operand.Type(), 0, mode, flags) 11664 case cc.PrimaryExpressionInt: // INTCONST 11665 panic(todo("", p.pos(n))) 11666 case cc.PrimaryExpressionFloat: // FLOATCONST 11667 panic(todo("", p.pos(n))) 11668 case cc.PrimaryExpressionEnum: // ENUMCONST 11669 panic(todo("", p.pos(n))) 11670 case cc.PrimaryExpressionChar: // CHARCONST 11671 panic(todo("", p.pos(n))) 11672 case cc.PrimaryExpressionLChar: // LONGCHARCONST 11673 panic(todo("", p.pos(n))) 11674 case cc.PrimaryExpressionString: // STRINGLITERAL 11675 panic(todo("", p.pos(n))) 11676 case cc.PrimaryExpressionLString: // LONGSTRINGLITERAL 11677 panic(todo("", p.pos(n))) 11678 case cc.PrimaryExpressionExpr: // '(' Expression ')' 11679 p.expression(f, n.Expression, t, mode, flags) 11680 case cc.PrimaryExpressionStmt: // '(' CompoundStatement ')' 11681 p.err(n, "statement expressions not supported") 11682 default: 11683 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 11684 } 11685 } 11686 11687 func cmpNormalizeValue(v cc.Value) cc.Value { 11688 switch x := v.(type) { 11689 case cc.Int64Value: 11690 if x >= 0 { 11691 return cc.Uint64Value(x) 11692 } 11693 } 11694 return v 11695 } 11696 11697 func (p *project) primaryExpressionValue(f *function, n *cc.PrimaryExpression, t cc.Type, mode exprMode, flags flags) { 11698 switch n.Case { 11699 case cc.PrimaryExpressionIdent: // IDENTIFIER 11700 switch d := n.Declarator(); { 11701 case d != nil: 11702 p.declarator(n, f, d, t, mode, flags) 11703 default: 11704 panic(todo("", p.pos(n))) 11705 } 11706 case cc.PrimaryExpressionInt: // INTCONST 11707 if m := n.Token.Macro(); m != 0 { 11708 if d := p.defines[m]; d.name != "" { 11709 if cmpNormalizeValue(n.Operand.Value()) == cmpNormalizeValue(d.value) { 11710 defer p.w("%s", p.convert(n, n.Operand, t, flags)) 11711 p.w(" %s ", d.name) 11712 break 11713 } 11714 11715 p.w("/* %s */", m) 11716 } 11717 } 11718 11719 p.intConst(n, n.Token.Src.String(), n.Operand, t, flags) 11720 case cc.PrimaryExpressionFloat: // FLOATCONST 11721 //TODO use #define 11722 p.floatConst(n, n.Token.Src.String(), n.Operand, t, flags) 11723 case cc.PrimaryExpressionEnum: // ENUMCONST 11724 en := n.ResolvedTo().(*cc.Enumerator) 11725 if n.ResolvedIn().Parent() == nil { 11726 if nm := p.enumConsts[en.Token.Value]; nm != "" { 11727 p.w(" %s ", nm) 11728 break 11729 } 11730 } 11731 11732 p.intConst(n, "", n.Operand, t, flags) 11733 p.w("/* %s */", en.Token.Value) 11734 case cc.PrimaryExpressionChar: // CHARCONST 11735 p.charConst(n, n.Token.Src.String(), n.Operand, t, flags) 11736 case cc.PrimaryExpressionLChar: // LONGCHARCONST 11737 p.charConst(n, n.Token.Src.String(), n.Operand, t, flags) 11738 case cc.PrimaryExpressionString: // STRINGLITERAL 11739 p.w("%s", p.stringLiteral(n.Operand.Value())) 11740 case cc.PrimaryExpressionLString: // LONGSTRINGLITERAL 11741 p.w("%s", p.wideStringLiteral(n.Operand.Value(), 0)) 11742 case cc.PrimaryExpressionExpr: // '(' Expression ')' 11743 p.w("(") 11744 defer p.w(")") 11745 p.expression(f, n.Expression, t, mode, flags) 11746 case cc.PrimaryExpressionStmt: // '(' CompoundStatement ')' 11747 p.statementExpression(f, n.CompoundStatement, t, mode, flags) 11748 default: 11749 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 11750 } 11751 } 11752 11753 func (p *project) statementExpression(f *function, n *cc.CompoundStatement, t cc.Type, mode exprMode, flags flags) { 11754 defer p.w("%s", p.convert(n, n.Operand, t, flags)) 11755 p.w(" func() %v {", p.typ(n, n.Operand.Type())) 11756 p.compoundStatement(f, n, "", true, false, mode) 11757 p.w("}()") 11758 } 11759 11760 func (p *project) primaryExpressionLValue(f *function, n *cc.PrimaryExpression, t cc.Type, mode exprMode, flags flags) { 11761 switch n.Case { 11762 case cc.PrimaryExpressionIdent: // IDENTIFIER 11763 switch d := n.Declarator(); { 11764 case d != nil: 11765 p.declarator(n, f, d, t, mode, flags) 11766 default: 11767 panic(todo("", p.pos(n))) 11768 } 11769 case cc.PrimaryExpressionInt: // INTCONST 11770 panic(todo("", p.pos(n))) 11771 case cc.PrimaryExpressionFloat: // FLOATCONST 11772 panic(todo("", p.pos(n))) 11773 case cc.PrimaryExpressionEnum: // ENUMCONST 11774 panic(todo("", p.pos(n))) 11775 case cc.PrimaryExpressionChar: // CHARCONST 11776 panic(todo("", p.pos(n))) 11777 case cc.PrimaryExpressionLChar: // LONGCHARCONST 11778 panic(todo("", p.pos(n))) 11779 case cc.PrimaryExpressionString: // STRINGLITERAL 11780 panic(todo("", p.pos(n))) 11781 case cc.PrimaryExpressionLString: // LONGSTRINGLITERAL 11782 panic(todo("", p.pos(n))) 11783 case cc.PrimaryExpressionExpr: // '(' Expression ')' 11784 p.w("(") 11785 defer p.w(")") 11786 p.expression(f, n.Expression, t, mode, flags) 11787 case cc.PrimaryExpressionStmt: // '(' CompoundStatement ')' 11788 p.err(n, "statement expressions not supported") 11789 default: 11790 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 11791 } 11792 } 11793 11794 func (p *project) stringLiteralString(s string) string { 11795 if p.pass1 { 11796 return "" 11797 } 11798 11799 id := cc.String(s) 11800 off, ok := p.tsOffs[id] 11801 if !ok { 11802 off = uintptr(p.ts.Len()) 11803 p.ts.WriteString(s) 11804 p.ts.WriteByte(0) 11805 p.tsOffs[id] = off 11806 } 11807 return fmt.Sprintf("(%s%s)%s", p.tsNameP, nonZeroUintptr(off), p.stringSnippet(s)) 11808 } 11809 11810 func (p *project) stringLiteral(v cc.Value) string { 11811 if p.pass1 { 11812 return "" 11813 } 11814 11815 switch x := v.(type) { 11816 case cc.StringValue: 11817 id := cc.StringID(x) 11818 off, ok := p.tsOffs[id] 11819 s := id.String() 11820 if !ok { 11821 off = uintptr(p.ts.Len()) 11822 p.ts.WriteString(s) 11823 p.ts.WriteByte(0) 11824 p.tsOffs[id] = off 11825 } 11826 return fmt.Sprintf("(%s%s)%s", p.tsNameP, nonZeroUintptr(off), p.stringSnippet(s)) 11827 default: 11828 panic(todo("%T", x)) 11829 } 11830 } 11831 11832 func (p *project) stringSnippet(s string) string { 11833 s = strings.ReplaceAll(s, "*/", "*\\/") 11834 const max = 16 11835 switch { 11836 case len(s) <= max: 11837 return fmt.Sprintf("/* %q */", s) 11838 default: 11839 return fmt.Sprintf("/* %q */", s[:16]+"...") 11840 } 11841 } 11842 11843 func (p *project) wideStringLiteral(v cc.Value, pad int) string { 11844 if p.pass1 { 11845 return "" 11846 } 11847 11848 switch x := v.(type) { 11849 case cc.WideStringValue: 11850 id := cc.StringID(x) 11851 off, ok := p.tsWOffs[id] 11852 if !ok { 11853 off = p.wcharSize * uintptr(len(p.tsW)) 11854 s := []rune(id.String()) 11855 if pad != 0 { 11856 s = append(s, make([]rune, pad)...) 11857 } 11858 p.tsW = append(p.tsW, s...) 11859 p.tsW = append(p.tsW, 0) 11860 p.tsWOffs[id] = off 11861 } 11862 return fmt.Sprintf("(%s%s)", p.tsWNameP, nonZeroUintptr(off)) 11863 default: 11864 panic(todo("%T", x)) 11865 } 11866 } 11867 11868 func (p *project) charConst(n cc.Node, src string, op cc.Operand, to cc.Type, flags flags) { 11869 switch { 11870 case to.IsArithmeticType(): 11871 defer p.w("%s", p.convert(n, op, to, flags)) 11872 case to.Kind() == cc.Ptr && op.IsZero(): 11873 p.w(" 0 ") 11874 return 11875 default: 11876 panic(todo("%v: t %v, to %v, to.Alias() %v", n.Position(), op.Type(), to, to.Alias())) 11877 } 11878 11879 r, mb, _, err := strconv.UnquoteChar(src[1:len(src)-1], '\'') 11880 rValid := !mb && err == nil 11881 var on uint64 11882 switch x := op.Value().(type) { 11883 case cc.Int64Value: 11884 on = uint64(x) 11885 case cc.Uint64Value: 11886 on = uint64(x) 11887 default: 11888 panic(todo("%T(%v)", x, x)) 11889 } 11890 var mask uint64 11891 switch { 11892 case !to.IsIntegerType(): 11893 // ok 11894 if rValid { // Prefer original form 11895 p.w("%s", src) 11896 return 11897 } 11898 11899 p.w("%d", on) 11900 return 11901 case to.IsSignedType(): 11902 var in int64 11903 var ok bool 11904 switch to.Size() { 11905 case 1: 11906 in = int64(int8(on)) 11907 ok = int8(on) >= 0 11908 case 2: 11909 in = int64(int16(on)) 11910 ok = int16(on) >= 0 11911 case 4: 11912 in = int64(int32(on)) 11913 ok = int32(on) >= 0 11914 case 8: 11915 in = int64(int64(on)) 11916 ok = in >= 0 11917 default: 11918 panic(todo("", op.Type().Size())) 11919 } 11920 if ok && rValid && uint64(in) == on { // Prefer original form 11921 p.w("%s", src) 11922 return 11923 } 11924 11925 p.w("%d", in) 11926 default: 11927 switch to.Size() { 11928 case 1: 11929 mask = 0xff 11930 case 2: 11931 mask = 0xffff 11932 case 4: 11933 mask = 0xffffffff 11934 case 8: 11935 mask = 0xffffffffffffffff 11936 default: 11937 panic(todo("", op.Type().Size())) 11938 } 11939 if rValid && uint64(r)&mask == on { // Prefer original form 11940 p.w("%s", src) 11941 return 11942 } 11943 11944 p.w("%d", on&mask) 11945 } 11946 } 11947 11948 func (p *project) floatConst(n cc.Node, src string, op cc.Operand, to cc.Type, flags flags) { 11949 if flags&fForceRuntimeConv != 0 { 11950 p.w("%s(", p.helperType2(n, op.Type(), to)) 11951 defer p.w(")") 11952 } 11953 11954 bits := 64 11955 switch to.Kind() { 11956 case cc.Float: 11957 bits = 32 11958 } 11959 src = strings.TrimRight(src, "flFL") 11960 sn, err := strconv.ParseFloat(src, bits) 11961 snValid := err == nil 11962 switch x := op.Value().(type) { 11963 case cc.Float64Value: 11964 switch to.Kind() { 11965 case cc.Double: 11966 if snValid && sn == float64(x) { // Prefer original form. 11967 p.w("%s", src) 11968 return 11969 } 11970 11971 p.w("math.Float64frombits(%#x)", math.Float64bits(float64(x))) 11972 case cc.Float: 11973 if snValid && float32(sn) == float32(x) { // Prefer original form. 11974 p.w("%s", src) 11975 return 11976 } 11977 11978 p.w("math.Float32frombits(%#x)", math.Float32bits(float32(x))) 11979 default: 11980 defer p.w("%s", p.convert(n, op, to, 0)) 11981 if snValid && sn == float64(x) { // Prefer original form. 11982 p.w("%s", src) 11983 return 11984 } 11985 11986 p.w("math.Float64frombits(%#x)", math.Float64bits(float64(x))) 11987 } 11988 case cc.Float32Value: 11989 switch to.Kind() { 11990 case cc.Double: 11991 if snValid && float32(sn) == float32(x) { // Prefer original form. 11992 p.w("%s", src) 11993 return 11994 } 11995 11996 p.w("math.Float64frombits(%#x)", math.Float64bits(float64(x))) 11997 case cc.Float: 11998 if snValid && float32(sn) == float32(x) { // Prefer original form. 11999 p.w("%s", src) 12000 return 12001 } 12002 12003 p.w("math.Float32frombits(%#x)", math.Float32bits(float32(x))) 12004 default: 12005 if to.IsIntegerType() { 12006 if s := p.float2Int(n, x, to); s != "" { 12007 defer p.w("%s%s", s, p.convertType(n, op.Type(), to, 0)) 12008 break 12009 } 12010 } 12011 12012 defer p.w("%s", p.convert(n, op, to, 0)) 12013 if snValid && float32(sn) == float32(x) { // Prefer original form. 12014 p.w("%s", src) 12015 return 12016 } 12017 12018 p.w("math.Float32frombits(%#x)", math.Float32bits(float32(x))) 12019 } 12020 default: 12021 panic(todo("%T(%v)", x, x)) 12022 } 12023 } 12024 12025 func (p *project) float2Int(n cc.Node, x cc.Float32Value, to cc.Type) string { 12026 switch { 12027 case to.IsSignedType(): 12028 limits := &signedSaturationLimits[to.Size()] 12029 v := float64(x) 12030 switch { 12031 case math.IsNaN(v): 12032 panic(todo("", p.pos(n))) 12033 case math.IsInf(v, -1): 12034 panic(todo("", p.pos(n))) 12035 case math.IsInf(v, 1): 12036 panic(todo("", p.pos(n))) 12037 case v < limits.fmin: 12038 return fmt.Sprint(limits.min) 12039 case v > limits.fmax: 12040 return fmt.Sprint(limits.max) 12041 } 12042 default: 12043 limits := &unsignedSaturationLimits[to.Size()] 12044 v := float64(x) 12045 switch { 12046 case math.IsNaN(v): 12047 panic(todo("", p.pos(n))) 12048 case math.IsInf(v, -1): 12049 panic(todo("", p.pos(n))) 12050 case math.IsInf(v, 1): 12051 panic(todo("", p.pos(n))) 12052 case v < 0: 12053 return "0" 12054 case v > limits.fmax: 12055 return fmt.Sprint(limits.max) 12056 } 12057 } 12058 return "" 12059 } 12060 12061 type signedSaturationLimit struct { 12062 fmin, fmax float64 12063 min, max int64 12064 } 12065 12066 type unsignedSaturationLimit struct { 12067 fmax float64 12068 max uint64 12069 } 12070 12071 var ( 12072 signedSaturationLimits = [...]signedSaturationLimit{ 12073 1: {math.Nextafter(math.MinInt32, 0), math.Nextafter(math.MaxInt32, 0), math.MinInt32, math.MaxInt32}, 12074 2: {math.Nextafter(math.MinInt32, 0), math.Nextafter(math.MaxInt32, 0), math.MinInt32, math.MaxInt32}, 12075 4: {math.Nextafter(math.MinInt32, 0), math.Nextafter(math.MaxInt32, 0), math.MinInt32, math.MaxInt32}, 12076 8: {math.Nextafter(math.MinInt64, 0), math.Nextafter(math.MaxInt64, 0), math.MinInt64, math.MaxInt64}, 12077 } 12078 12079 unsignedSaturationLimits = [...]unsignedSaturationLimit{ 12080 1: {math.Nextafter(math.MaxUint32, 0), math.MaxUint32}, 12081 2: {math.Nextafter(math.MaxUint32, 0), math.MaxUint32}, 12082 4: {math.Nextafter(math.MaxUint32, 0), math.MaxUint32}, 12083 8: {math.Nextafter(math.MaxUint64, 0), math.MaxUint64}, 12084 } 12085 ) 12086 12087 func (p *project) intConst(n cc.Node, src string, op cc.Operand, to cc.Type, flags flags) { 12088 ptr := to.Kind() == cc.Ptr 12089 switch { 12090 case to.IsArithmeticType(): 12091 // p.w("/*10568 %T(%#[1]x) %v -> %v */", op.Value(), op.Type(), to) //TODO- 12092 if flags&fForceNoConv != 0 { 12093 break 12094 } 12095 12096 if !op.Type().IsSignedType() && op.Type().Size() == 8 && op.Value().(cc.Uint64Value) > math.MaxInt64 { 12097 flags |= fForceRuntimeConv 12098 } 12099 defer p.w("%s", p.convert(n, op, to, flags)) 12100 case ptr: 12101 p.w(" uintptr(") 12102 defer p.w(")") 12103 // ok 12104 default: 12105 panic(todo("%v: %v -> %v", p.pos(n), op.Type(), to)) 12106 } 12107 12108 src = strings.TrimRight(src, "luLU") 12109 sn, err := strconv.ParseUint(src, 0, 64) 12110 snValid := err == nil 12111 var on uint64 12112 switch x := op.Value().(type) { 12113 case cc.Int64Value: 12114 if x < 0 { 12115 sn, err := strconv.ParseInt(src, 0, 64) 12116 snValid := err == nil 12117 if snValid && sn == int64(x) { // Prefer original form 12118 p.w("%s", src) 12119 return 12120 } 12121 12122 p.w("%d", x) 12123 return 12124 } 12125 12126 on = uint64(x) 12127 case cc.Uint64Value: 12128 on = uint64(x) 12129 default: 12130 panic(todo("%T(%v)", x, x)) 12131 } 12132 12133 if snValid && sn == on { // Prefer original form 12134 p.w("%s", src) 12135 return 12136 } 12137 12138 p.w("%d", on) 12139 } 12140 12141 func (p *project) assignShiftOp(f *function, n *cc.AssignmentExpression, t cc.Type, mode exprMode, oper, oper2 string, flags flags) { 12142 // UnaryExpression "<<=" AssignmentExpression etc. 12143 switch mode { 12144 case exprVoid: 12145 p.assignShiftOpVoid(f, n, t, mode, oper, oper2, flags) 12146 default: 12147 panic(todo("", mode)) 12148 } 12149 } 12150 12151 func (p *project) assignShiftOpVoid(f *function, n *cc.AssignmentExpression, t cc.Type, mode exprMode, oper, oper2 string, flags flags) { 12152 // UnaryExpression "<<=" AssignmentExpression etc. 12153 switch k := p.opKind(f, n.UnaryExpression, n.UnaryExpression.Operand.Type()); k { 12154 case opNormal: 12155 p.assignShiftOpVoidNormal(f, n, t, mode, oper, oper2, flags) 12156 default: 12157 panic(todo("", n.Position(), k)) 12158 } 12159 } 12160 12161 func (p *project) assignShiftOpVoidNormal(f *function, n *cc.AssignmentExpression, t cc.Type, mode exprMode, oper, oper2 string, flags flags) { 12162 switch { 12163 case n.Operand.Type().IsBitFieldType(): 12164 panic(todo("", p.pos(n))) 12165 default: 12166 if d := n.UnaryExpression.Declarator(); d != nil { 12167 switch d.Type().Kind() { 12168 case cc.Int128, cc.UInt128: 12169 p.declarator(n, f, d, d.Type(), exprLValue, flags) 12170 p.w(".LValue%s(", oper2) 12171 p.assignmentExpression(f, n.AssignmentExpression, p.intType, exprValue, flags) 12172 p.w(")") 12173 return 12174 default: 12175 p.declarator(n, f, d, d.Type(), exprLValue, flags) 12176 p.w(" %s= ", oper) 12177 p.assignmentExpression(f, n.AssignmentExpression, n.Promote(), exprValue, flags) 12178 return 12179 } 12180 } 12181 12182 lhs := n.UnaryExpression 12183 switch { 12184 case lhs.Operand.Type().IsArithmeticType(): 12185 p.w("%sAssign%sPtr%s(", p.task.crt, oper2, p.helperType(n, lhs.Operand.Type())) 12186 p.unaryExpression(f, lhs, lhs.Operand.Type(), exprAddrOf, flags) 12187 p.w(", int(") 12188 p.assignmentExpression(f, n.AssignmentExpression, n.Promote(), exprValue, flags) 12189 p.w("))") 12190 default: 12191 panic(todo("", p.pos(n), lhs.Operand.Type())) 12192 } 12193 } 12194 } 12195 12196 func (p *project) assignOp(f *function, n *cc.AssignmentExpression, t cc.Type, mode exprMode, oper, oper2 string, flags flags) { 12197 // UnaryExpression "*=" AssignmentExpression etc. 12198 switch mode { 12199 case exprVoid: 12200 p.assignOpVoid(f, n, t, mode, oper, oper2, flags) 12201 case exprValue, exprCondReturn: 12202 p.assignOpValue(f, n, t, mode, oper, oper2, flags) 12203 default: 12204 panic(todo("", n.Position(), mode)) 12205 } 12206 } 12207 12208 func (p *project) assignOpValue(f *function, n *cc.AssignmentExpression, t cc.Type, mode exprMode, oper, oper2 string, flags flags) { 12209 // UnaryExpression "*=" AssignmentExpression etc. 12210 switch k := p.opKind(f, n.UnaryExpression, n.UnaryExpression.Operand.Type()); k { 12211 case opNormal: 12212 p.assignOpValueNormal(f, n, t, oper, oper2, mode, flags) 12213 case opBitfield: 12214 p.assignOpValueBitfield(f, n, t, oper, oper2, mode, flags) 12215 default: 12216 panic(todo("", n.Position(), k)) 12217 } 12218 } 12219 12220 func (p *project) assignOpValueBitfield(f *function, n *cc.AssignmentExpression, t cc.Type, oper, oper2 string, mode exprMode, flags flags) { 12221 // UnaryExpression "*=" AssignmentExpression etc. 12222 12223 asInt := oper2 == "Shl" || oper2 == "Shr" 12224 if asInt { 12225 panic(todo("")) 12226 } 12227 12228 ot := n.Operand.Type() 12229 lhs := n.UnaryExpression 12230 bf := lhs.Operand.Type().BitField() 12231 defer p.w("%s", p.convertType(n, ot, t, flags)) 12232 p.w(" func() %v {", p.typ(n, ot)) 12233 switch lhs.Case { 12234 case cc.UnaryExpressionPostfix: // PostfixExpression 12235 pe := n.UnaryExpression.PostfixExpression 12236 switch pe.Case { 12237 case cc.PostfixExpressionSelect: // PostfixExpression '.' IDENTIFIER 12238 p.w("__p := ") 12239 p.postfixExpression(f, pe, pe.Operand.Type(), exprAddrOf, flags) 12240 p.w("; __v := ") 12241 p.readBitfield(lhs, "__p", bf, ot) 12242 p.w(" %s (", oper) 12243 p.assignmentExpression(f, n.AssignmentExpression, ot, exprValue, flags) 12244 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()) 12245 case cc.PostfixExpressionPSelect: // PostfixExpression "->" IDENTIFIER 12246 panic(todo("", p.pos(n))) 12247 default: 12248 panic(todo("", n.Position(), pe.Case)) 12249 } 12250 default: 12251 panic(todo("", n.Position(), lhs.Case)) 12252 } 12253 p.w("}()") 12254 } 12255 12256 func (p *project) readBitfield(n cc.Node, ptr string, bf cc.Field, promote cc.Type) { 12257 bw := bf.BitFieldBlockWidth() 12258 m := bf.Mask() 12259 o := bf.BitFieldOffset() 12260 w := bf.BitFieldWidth() 12261 p.w("(%s(*(*uint%d)(unsafe.Pointer(%s))&%#x)", p.typ(n, promote), bw, ptr, m) 12262 switch { 12263 case bf.Type().IsSignedType(): 12264 bits := int(promote.Size()) * 8 12265 p.w("<<%d>>%d)", bits-w-o, bits-w) 12266 default: 12267 p.w(">>%d)", o) 12268 } 12269 } 12270 12271 func (p *project) assignOpValueNormal(f *function, n *cc.AssignmentExpression, t cc.Type, oper, oper2 string, mode exprMode, flags flags) { 12272 if mode == exprCondReturn { 12273 p.w("return ") 12274 } 12275 asInt := oper2 == "Shl" || oper2 == "Shr" 12276 lhs := n.UnaryExpression 12277 // UnaryExpression "*=" AssignmentExpression etc. 12278 if d := lhs.Declarator(); d != nil { 12279 if local := f.locals[d]; local != nil && local.isPinned { 12280 switch { 12281 case lhs.Operand.Type().IsArithmeticType(): 12282 defer p.w("%s", p.convertType(n, lhs.Operand.Type(), t, flags)) 12283 p.w("%sAssign%sPtr%s(", p.task.crt, oper2, p.helperType(n, lhs.Operand.Type())) 12284 p.unaryExpression(f, lhs, lhs.Operand.Type(), exprAddrOf, flags) 12285 p.w(", ") 12286 if asInt { 12287 p.w("int(") 12288 } 12289 p.assignmentExpression(f, n.AssignmentExpression, lhs.Operand.Type(), exprValue, flags) 12290 if asInt { 12291 p.w(")") 12292 } 12293 p.w(")") 12294 default: 12295 panic(todo("", lhs.Operand.Type())) 12296 } 12297 return 12298 } 12299 12300 switch { 12301 case d.Type().Kind() == cc.Ptr: 12302 defer p.w("%s", p.convertType(n, d.Type(), t, flags)) 12303 p.w("%sAssign%s%s(&", p.task.crt, oper2, p.helperType(n, d.Type())) 12304 p.declarator(n, f, d, d.Type(), exprLValue, flags) 12305 p.w(", ") 12306 if dd := p.incDelta(d, d.Type()); dd != 1 { 12307 p.w("%d*(", dd) 12308 defer p.w(")") 12309 } 12310 p.assignmentExpression(f, n.AssignmentExpression, d.Type(), exprValue, flags) 12311 p.w(")") 12312 case d.Type().IsArithmeticType(): 12313 defer p.w("%s", p.convertType(n, d.Type(), t, flags)) 12314 p.w("%sAssign%s%s(&", p.task.crt, oper2, p.helperType(n, d.Type())) 12315 p.declarator(n, f, d, d.Type(), exprLValue, flags) 12316 p.w(", ") 12317 if asInt { 12318 p.w("int(") 12319 } 12320 p.assignmentExpression(f, n.AssignmentExpression, d.Type(), exprValue, flags) 12321 p.w(")") 12322 if asInt { 12323 p.w(")") 12324 } 12325 default: 12326 panic(todo("", p.pos(n), p.pos(d), d.Name())) 12327 } 12328 return 12329 } 12330 12331 switch { 12332 case lhs.Operand.Type().IsArithmeticType(): 12333 defer p.w("%s", p.convertType(n, lhs.Operand.Type(), t, flags)) 12334 p.w("%sAssign%sPtr%s(", p.task.crt, oper2, p.helperType(n, lhs.Operand.Type())) 12335 p.unaryExpression(f, lhs, lhs.Operand.Type(), exprAddrOf, flags) 12336 p.w(", ") 12337 if asInt { 12338 p.w("int(") 12339 } 12340 p.assignmentExpression(f, n.AssignmentExpression, lhs.Operand.Type(), exprValue, flags) 12341 if asInt { 12342 p.w(")") 12343 } 12344 p.w(")") 12345 default: 12346 panic(todo("", lhs.Operand.Type())) 12347 } 12348 } 12349 12350 func (p *project) assignOpVoid(f *function, n *cc.AssignmentExpression, t cc.Type, mode exprMode, oper, oper2 string, flags flags) { 12351 // UnaryExpression "*=" AssignmentExpression etc. 12352 switch k := p.opKind(f, n.UnaryExpression, n.UnaryExpression.Operand.Type()); k { 12353 case opNormal: 12354 p.assignOpVoidNormal(f, n, t, oper, oper2, mode, flags) 12355 case opBitfield: 12356 p.assignOpVoidBitfield(f, n, t, oper, oper2, mode, flags) 12357 case opArrayParameter: 12358 p.assignOpVoidArrayParameter(f, n, t, oper, oper2, mode, flags) 12359 default: 12360 panic(todo("", n.Position(), k)) 12361 } 12362 } 12363 12364 func (p *project) assignOpVoidArrayParameter(f *function, n *cc.AssignmentExpression, t cc.Type, oper, oper2 string, mode exprMode, flags flags) { 12365 // UnaryExpression "*=" AssignmentExpression etc. 12366 if oper != "+" && oper != "-" { 12367 panic(todo("", p.pos(n))) 12368 } 12369 12370 d := n.UnaryExpression.Declarator() 12371 switch local := f.locals[d]; { 12372 case local != nil && local.isPinned: 12373 p.w("*(*uintptr)(unsafe.Pointer(%s%s))", f.bpName, nonZeroUintptr(local.off)) 12374 default: 12375 p.declarator(n, f, d, d.Type(), exprLValue, flags) 12376 } 12377 12378 p.w(" %s= ", oper) 12379 if dd := p.incDelta(d, d.Type()); dd != 1 { 12380 p.w("%d*", dd) 12381 } 12382 p.w("uintptr(") 12383 p.assignmentExpression(f, n.AssignmentExpression, n.AssignmentExpression.Operand.Type(), exprValue, flags) 12384 p.w(")") 12385 } 12386 12387 func (p *project) assignOpVoidBitfield(f *function, n *cc.AssignmentExpression, t cc.Type, oper, oper2 string, mode exprMode, flags flags) { 12388 // UnaryExpression "*=" AssignmentExpression etc. 12389 lhs := n.UnaryExpression 12390 lt := lhs.Operand.Type() 12391 switch lhs.Case { 12392 case cc.UnaryExpressionPostfix: // PostfixExpression 12393 pe := n.UnaryExpression.PostfixExpression 12394 switch pe.Case { 12395 case cc.PostfixExpressionSelect: // PostfixExpression '.' IDENTIFIER 12396 bf := lt.BitField() 12397 p.w("%sSetBitFieldPtr%d%s(", p.task.crt, bf.BitFieldBlockWidth(), p.bfHelperType(n.Promote())) 12398 p.unaryExpression(f, lhs, lt, exprAddrOf, flags) 12399 p.w(", (") 12400 s := p.convertType(n, lt, n.Promote(), flags) 12401 p.unaryExpression(f, lhs, lt, exprValue, flags) 12402 p.w(")%s %s ", s, oper) 12403 s = p.convertType(n, lt, n.Promote(), flags) 12404 p.assignmentExpression(f, n.AssignmentExpression, n.Promote(), exprValue, flags) 12405 p.w("%s", s) 12406 p.w(", %d, %#x)", bf.BitFieldOffset(), bf.Mask()) 12407 case cc.PostfixExpressionPSelect: // PostfixExpression "->" IDENTIFIER 12408 switch d := pe.PostfixExpression.Declarator(); { 12409 case d != nil: 12410 panic(todo("", p.pos(n))) 12411 default: 12412 panic(todo("", p.pos(n))) 12413 } 12414 default: 12415 panic(todo("", n.Position(), pe.Case)) 12416 } 12417 default: 12418 panic(todo("", n.Position(), lhs.Case)) 12419 } 12420 } 12421 12422 func (p *project) assignOpVoidNormal(f *function, n *cc.AssignmentExpression, t cc.Type, oper, oper2 string, mode exprMode, flags flags) { 12423 // UnaryExpression "*=" AssignmentExpression etc. 12424 rop := n.AssignmentExpression.Operand 12425 if d := n.UnaryExpression.Declarator(); d != nil { 12426 if local := f.locals[d]; local != nil && local.isPinned { 12427 if p.isVolatileOrAtomic(d) { 12428 panic(todo("")) 12429 } 12430 12431 p.declarator(n, f, d, d.Type(), exprLValue, flags) 12432 switch { 12433 case d.Type().Kind() == cc.Ptr: 12434 p.w(" %s= ", oper) 12435 if dd := p.incDelta(d, d.Type()); dd != 1 { 12436 p.w("%d*(", dd) 12437 defer p.w(")") 12438 } 12439 defer p.w("%s", p.convert(n, rop.ConvertTo(n.Promote()), d.Type(), flags)) 12440 p.assignmentExpression(f, n.AssignmentExpression, n.Promote(), exprValue, flags) 12441 case d.Type().IsArithmeticType(): 12442 p.w(" %s= ", oper) 12443 defer p.w("%s", p.convert(n, rop.ConvertTo(n.Promote()), d.Type(), flags)) 12444 p.assignmentExpression(f, n.AssignmentExpression, n.Promote(), exprValue, flags) 12445 default: 12446 panic(todo("", n.Position(), d.Type().Kind())) 12447 } 12448 return 12449 } 12450 12451 if p.isVolatileOrAtomic(d) { 12452 var local *local 12453 var tld *tld 12454 var nm string 12455 if f != nil { 12456 if local = f.locals[d]; local != nil { 12457 nm = local.name 12458 } 12459 } 12460 12461 if local == nil { 12462 if tld = p.tlds[d]; tld == nil { 12463 p.err(n, "%v: internal error (%v: %v)", n.Position(), d.Position(), d.Name()) 12464 return 12465 } 12466 12467 nm = tld.name 12468 } 12469 var sign string 12470 switch oper { 12471 case "-": 12472 sign = oper 12473 fallthrough 12474 case "+": 12475 sz := d.Type().Size() 12476 var ht string 12477 switch sz { 12478 case 4, 8: 12479 if !d.Type().IsScalarType() { 12480 p.err(n, "unsupported volatile declarator type: %v", d.Type()) 12481 break 12482 } 12483 12484 ht = p.helperType(n, d.Type()) 12485 default: 12486 p.err(n, "unsupported volatile declarator size: %v", sz) 12487 return 12488 } 12489 12490 if local != nil { 12491 if local.isPinned { 12492 panic(todo("")) 12493 } 12494 } 12495 12496 p.w("%sAtomicAdd%s(&%s, %s%s(", p.task.crt, ht, nm, sign, p.typ(n, d.Type())) 12497 p.assignmentExpression(f, n.AssignmentExpression, n.Promote(), exprValue, flags) 12498 p.w("))") 12499 return 12500 default: 12501 p.warn(n, "unsupported volatile declarator operation: %v", oper) 12502 p.w("%s = ", nm) 12503 defer p.w("%s", p.convert(n, rop.ConvertTo(n.Promote()), d.Type(), flags)) 12504 p.declarator(n, f, d, n.Promote(), exprValue, flags) 12505 p.w(" %s (", oper) 12506 p.assignmentExpression(f, n.AssignmentExpression, n.Promote(), exprValue, flags) 12507 p.w(")") 12508 return 12509 } 12510 } 12511 12512 p.declarator(n, f, d, d.Type(), exprLValue, flags) 12513 switch d.Type().Kind() { 12514 case cc.Ptr: 12515 if oper != "+" && oper != "-" { 12516 panic(todo("", p.pos(n))) 12517 } 12518 12519 p.w(" %s= ", oper) 12520 if dd := p.incDelta(d, d.Type()); dd != 1 { 12521 p.w("%d*(", dd) 12522 defer p.w(")") 12523 } 12524 defer p.w("%s", p.convert(n, rop.ConvertTo(n.Promote()), d.Type(), flags)) 12525 p.assignmentExpression(f, n.AssignmentExpression, n.Promote(), exprValue, flags) 12526 case cc.Int128, cc.UInt128: 12527 p.w(" = ") 12528 p.declarator(n, f, d, n.Promote(), exprValue, flags) 12529 p.w(".%s(", oper2) 12530 p.assignmentExpression(f, n.AssignmentExpression, n.Promote(), exprValue, flags) 12531 p.w(")") 12532 default: 12533 p.w(" = ") 12534 defer p.w("%s", p.convert(n, rop.ConvertTo(n.Promote()), d.Type(), flags)) 12535 p.declarator(n, f, d, n.Promote(), exprValue, flags) 12536 p.w(" %s (", oper) 12537 p.assignmentExpression(f, n.AssignmentExpression, n.Promote(), exprValue, flags) 12538 p.w(")") 12539 } 12540 return 12541 } 12542 12543 lhs := n.UnaryExpression 12544 switch { 12545 case lhs.Operand.Type().IsArithmeticType(): 12546 p.w("*(*%s)(unsafe.Pointer(", p.typ(n, lhs.Operand.Type())) 12547 p.unaryExpression(f, lhs, lhs.Operand.Type(), exprAddrOf, flags) 12548 p.w(")) %s= ", oper) 12549 defer p.w("%s", p.convert(n, rop.ConvertTo(n.Promote()), lhs.Operand.Type(), flags)) 12550 p.w("(") 12551 p.assignmentExpression(f, n.AssignmentExpression, n.Promote(), exprValue, flags) 12552 p.w(")") 12553 case lhs.Operand.Type().Kind() == cc.Ptr: 12554 p.w("*(*%s)(unsafe.Pointer(", p.typ(n, lhs.Operand.Type())) 12555 p.unaryExpression(f, lhs, lhs.Operand.Type(), exprAddrOf, flags) 12556 p.w(")) %s= (", oper) 12557 p.assignmentExpression(f, n.AssignmentExpression, lhs.Operand.Type(), exprValue, flags) 12558 p.w(")") 12559 if dd := p.incDelta(n, lhs.Operand.Type()); dd != 1 { 12560 p.w("*%d", dd) 12561 } 12562 default: 12563 panic(todo("", lhs.Operand.Type())) 12564 } 12565 } 12566 12567 func (p *project) warn(n cc.Node, s string, args ...interface{}) { 12568 s = fmt.Sprintf(s, args...) 12569 s = strings.TrimRight(s, "\t\n\r") 12570 fmt.Fprintf(os.Stderr, "%v: warning: %s\n", n.Position(), s) 12571 } 12572 12573 func (p *project) iterationStatement(f *function, n *cc.IterationStatement) { 12574 sv := f.switchCtx 12575 sv2 := f.continueCtx 12576 sv3 := f.breakCtx 12577 f.switchCtx = 0 12578 f.continueCtx = 0 12579 f.breakCtx = 0 12580 defer func() { 12581 f.breakCtx = sv3 12582 f.continueCtx = sv2 12583 f.switchCtx = sv 12584 }() 12585 p.w("%s", tidyComment("\n", n)) 12586 switch n.Case { 12587 case cc.IterationStatementWhile: // "while" '(' Expression ')' Statement 12588 if f.hasJumps { 12589 // a: if !expr goto b 12590 // stmt 12591 // goto a 12592 // b: 12593 a := f.flatLabel() 12594 b := f.flatLabel() 12595 f.continueCtx = a 12596 f.breakCtx = b 12597 p.w("__%d: if !(", a) 12598 p.expression(f, n.Expression, n.Expression.Operand.Type(), exprBool, 0) 12599 p.w(") { goto __%d };", b) 12600 p.statement(f, n.Statement, false, false, false, 0) 12601 p.w("; goto __%d; __%d:", a, b) 12602 break 12603 } 12604 12605 p.w("for ") 12606 p.expression(f, n.Expression, n.Expression.Operand.Type(), exprBool, 0) 12607 p.statement(f, n.Statement, true, false, false, 0) 12608 case cc.IterationStatementDo: // "do" Statement "while" '(' Expression ')' ';' 12609 if f.hasJumps { 12610 // a: stmt 12611 // b: if expr goto a // b is the continue label 12612 // c: 12613 a := f.flatLabel() 12614 b := f.flatLabel() 12615 c := f.flatLabel() 12616 f.continueCtx = b 12617 f.breakCtx = c 12618 p.w("__%d:", a) 12619 p.statement(f, n.Statement, false, false, false, 0) 12620 p.w(";goto __%d; __%[1]d: if ", b) 12621 p.expression(f, n.Expression, n.Expression.Operand.Type(), exprBool, 0) 12622 p.w("{goto __%d};goto __%d;__%[2]d:", a, c) 12623 break 12624 } 12625 12626 v := "__ccgo" 12627 if !p.pass1 { 12628 v = f.scope.take(cc.String(v)) 12629 } 12630 p.w("for %v := true; %[1]v; %[1]v = ", v) 12631 p.expression(f, n.Expression, n.Expression.Operand.Type(), exprBool, 0) 12632 p.statement(f, n.Statement, true, false, false, 0) 12633 case cc.IterationStatementFor: // "for" '(' Expression ';' Expression ';' Expression ')' Statement 12634 if f.hasJumps || n.Expression3 != nil && n.Expression3.Case == cc.ExpressionComma { 12635 // expr 12636 // a: if !expr2 goto c 12637 // stmt 12638 // b: expr3 // label for continue 12639 // goto a 12640 // c: 12641 a := f.flatLabel() 12642 b := f.flatLabel() 12643 f.continueCtx = b 12644 c := f.flatLabel() 12645 f.breakCtx = c 12646 if n.Expression != nil { 12647 p.expression(f, n.Expression, n.Expression.Operand.Type(), exprVoid, fNoCondAssignment) 12648 } 12649 semi := "" 12650 if n.Expression != nil || n.Expression2 != nil || n.Expression3 != nil { 12651 semi = ";" 12652 } 12653 p.w("%s__%d:", semi, a) 12654 if n.Expression2 != nil { 12655 p.w("if !(") 12656 p.expression(f, n.Expression2, n.Expression2.Operand.Type(), exprBool, 0) 12657 p.w(") { goto __%d }", c) 12658 } 12659 p.w("%s", semi) 12660 p.statement(f, n.Statement, false, false, false, 0) 12661 p.w(";goto __%d; __%[1]d:", b) 12662 if n.Expression3 != nil { 12663 p.expression(f, n.Expression3, n.Expression3.Operand.Type(), exprVoid, fNoCondAssignment) 12664 } 12665 p.w("%sgoto __%d; goto __%d;__%[3]d:", semi, a, c) 12666 break 12667 } 12668 12669 expr := true 12670 if n.Expression != nil && n.Expression.Case == cc.ExpressionComma { 12671 p.expression(f, n.Expression, n.Expression.Operand.Type(), exprVoid, 0) 12672 p.w(";") 12673 expr = false 12674 } 12675 p.w("for ") 12676 if expr && n.Expression != nil { 12677 p.expression(f, n.Expression, n.Expression.Operand.Type(), exprVoid, fNoCondAssignment) 12678 } 12679 p.w("; ") 12680 if n.Expression2 != nil { 12681 p.expression(f, n.Expression2, n.Expression2.Operand.Type(), exprBool, 0) 12682 } 12683 p.w("; ") 12684 if n.Expression3 != nil { 12685 p.expression(f, n.Expression3, n.Expression3.Operand.Type(), exprVoid, fNoCondAssignment) 12686 } 12687 p.statement(f, n.Statement, true, false, false, 0) 12688 case cc.IterationStatementForDecl: // "for" '(' Declaration Expression ';' Expression ')' Statement 12689 if !(f.hasJumps || n.Expression2 != nil && n.Expression2.Case == cc.ExpressionComma) { 12690 p.w("{") 12691 p.declaration(f, n.Declaration, false) 12692 p.w("for ;") 12693 if n.Expression != nil { 12694 p.expression(f, n.Expression, n.Expression.Operand.Type(), exprBool, 0) 12695 } 12696 p.w(";") 12697 if n.Expression2 != nil { 12698 p.expression(f, n.Expression2, n.Expression2.Operand.Type(), exprVoid, fNoCondAssignment) 12699 } 12700 p.w("{") 12701 p.statement(f, n.Statement, false, true, false, 0) 12702 p.w("}};") 12703 break 12704 } 12705 12706 var ids []*cc.InitDeclarator 12707 for list := n.Declaration.InitDeclaratorList; list != nil; list = list.InitDeclaratorList { 12708 ids = append(ids, list.InitDeclarator) 12709 } 12710 12711 // declaration 12712 // a: if !expr goto c 12713 // stmt 12714 // b: expr2 // label for continue 12715 // goto a 12716 // c: 12717 a := f.flatLabel() 12718 b := f.flatLabel() 12719 f.continueCtx = b 12720 c := f.flatLabel() 12721 f.breakCtx = c 12722 p.w("{") 12723 p.declaration(f, n.Declaration, false) 12724 p.w(";") 12725 p.w("__%d:", a) 12726 if n.Expression != nil { 12727 p.w("if !(") 12728 p.expression(f, n.Expression, n.Expression.Operand.Type(), exprBool, 0) 12729 p.w(") { goto __%d }", c) 12730 } 12731 p.w(";") 12732 p.statement(f, n.Statement, false, false, false, 0) 12733 p.w(";goto __%d; __%[1]d:", b) 12734 if n.Expression2 != nil { 12735 p.expression(f, n.Expression2, n.Expression2.Operand.Type(), exprVoid, fNoCondAssignment) 12736 } 12737 p.w("; goto __%d; goto __%d;__%[2]d:\n}", a, c) 12738 default: 12739 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 12740 } 12741 } 12742 12743 func (p *project) selectionStatement(f *function, n *cc.SelectionStatement) { 12744 p.w("%s", tidyComment("\n", n)) 12745 switch n.Case { 12746 case cc.SelectionStatementIf: // "if" '(' Expression ')' Statement 12747 sv := f.ifCtx 12748 f.ifCtx = n 12749 defer func() { f.ifCtx = sv }() 12750 if f.hasJumps { 12751 // if !expr goto a 12752 // stmt 12753 // a: 12754 f.ifCtx = n 12755 a := f.flatLabel() 12756 p.w("if !(") 12757 p.expression(f, n.Expression, n.Expression.Operand.Type(), exprBool, 0) 12758 p.w(") { goto __%d };", a) 12759 p.statement(f, n.Statement, false, false, false, 0) 12760 p.w(";__%d: ", a) 12761 break 12762 } 12763 12764 p.w("if ") 12765 p.expression(f, n.Expression, n.Expression.Operand.Type(), exprBool, 0) 12766 p.statement(f, n.Statement, true, false, false, 0) 12767 case cc.SelectionStatementIfElse: // "if" '(' Expression ')' Statement "else" Statement 12768 sv := f.ifCtx 12769 f.ifCtx = n 12770 defer func() { f.ifCtx = sv }() 12771 if f.hasJumps { 12772 // if !expr goto a 12773 // stmt 12774 // goto b 12775 // a: 12776 // stmt2 12777 // b: 12778 a := f.flatLabel() 12779 b := f.flatLabel() 12780 p.w("if !(") 12781 p.expression(f, n.Expression, n.Expression.Operand.Type(), exprBool, 0) 12782 p.w(") { goto __%d };", a) 12783 p.statement(f, n.Statement, false, false, false, 0) 12784 p.w(";goto __%d; __%d:", b, a) 12785 p.statement(f, n.Statement2, false, false, false, 0) 12786 p.w(";__%d:", b) 12787 break 12788 } 12789 12790 p.w("if ") 12791 p.expression(f, n.Expression, n.Expression.Operand.Type(), exprBool, 0) 12792 p.statement(f, n.Statement, true, false, false, 0) 12793 p.w(" else ") 12794 switch { 12795 case p.isIfStmt(n.Statement2): 12796 p.statement(f, n.Statement2, false, true, false, 0) 12797 default: 12798 p.statement(f, n.Statement2, true, false, false, 0) 12799 } 12800 case cc.SelectionStatementSwitch: // "switch" '(' Expression ')' Statement 12801 // just dont generate in this case 12802 if f.switchCtx == inSwitchFirst { 12803 break 12804 } 12805 sv := f.switchCtx 12806 sb := f.block 12807 sc := p.pauseCodegen 12808 svBreakCtx := f.breakCtx 12809 f.breakCtx = 0 12810 f.block = f.blocks[n.Statement.CompoundStatement] 12811 12812 defer func() { 12813 f.block = sb 12814 f.switchCtx = sv 12815 f.breakCtx = svBreakCtx 12816 p.pauseCodegen = sc 12817 }() 12818 if f.hasJumps { 12819 f.switchCtx = inSwitchFlat 12820 p.flatSwitch(f, n) 12821 break 12822 } 12823 12824 f.switchCtx = inSwitchFirst 12825 // fmt.Println(f.block.decls) 12826 if len(f.block.decls) != 0 { 12827 f.block.topDecl = true 12828 // fmt.Printf("%p:%tf\n", f.block, f.block.topDecl) 12829 p.w("{") 12830 for _, v := range f.block.decls { 12831 // fmt.Printf("%p:%tf\n", f.block, f.block.topDecl) 12832 p.declaration(f, v, true) 12833 // fmt.Println("done!") 12834 } 12835 } 12836 12837 p.w("switch ") 12838 p.expression(f, n.Expression, n.Promote(), exprValue, 0) 12839 p.pauseCodegen = true 12840 p.statement(f, n.Statement, true, false, true, 0) 12841 p.pauseCodegen = false 12842 if len(f.block.decls) != 0 { 12843 p.w("}") 12844 } 12845 12846 default: 12847 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 12848 } 12849 } 12850 12851 func (p *project) isIfStmt(n *cc.Statement) bool { 12852 if n.Case != cc.StatementSelection { 12853 return false 12854 } 12855 12856 switch n.SelectionStatement.Case { 12857 case cc.SelectionStatementIf, cc.SelectionStatementIfElse: 12858 return true 12859 } 12860 12861 return false 12862 } 12863 12864 func (p *project) flatSwitch(f *function, n *cc.SelectionStatement) { 12865 if n.Statement.Case != cc.StatementCompound { 12866 panic(todo("", p.pos(n))) 12867 } 12868 12869 sv := f.block 12870 f.block = f.blocks[n.Statement.CompoundStatement] 12871 defer func() { f.block = sv }() 12872 // "switch" '(' Expression ')' Statement 12873 cases := n.Cases() 12874 labels := map[*cc.LabeledStatement]int{} 12875 svBreakCtx := f.breakCtx 12876 f.breakCtx = f.flatLabel() 12877 p.w("switch ") 12878 p.expression(f, n.Expression, n.Promote(), exprValue, 0) 12879 p.w("{") 12880 for _, ls := range cases { 12881 switch ls.Case { 12882 case cc.LabeledStatementLabel: // IDENTIFIER ':' AttributeSpecifierList Statement 12883 continue 12884 case cc.LabeledStatementCaseLabel: // "case" ConstantExpression ':' Statement 12885 p.w("%scase ", tidyComment("\n", ls)) 12886 p.constantExpression(f, ls.ConstantExpression, ls.ConstantExpression.Operand.Type(), exprValue, 0) 12887 p.w(":") 12888 case cc.LabeledStatementDefault: // "default" ':' Statement 12889 p.w("%sdefault:", tidyComment("\n", ls)) 12890 case cc.LabeledStatementRange: // "case" ConstantExpression "..." ConstantExpression ':' Statement 12891 panic(todo("", p.pos(n))) 12892 default: 12893 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 12894 } 12895 label := f.flatLabel() 12896 labels[ls] = label 12897 p.w("goto __%d;", label) 12898 } 12899 p.w("}; goto __%d;", f.breakCtx) 12900 svLabels := f.flatSwitchLabels 12901 f.flatSwitchLabels = labels 12902 p.statement(f, n.Statement, false, true, false, 0) 12903 f.flatSwitchLabels = svLabels 12904 p.w("__%d:", f.breakCtx) 12905 f.breakCtx = svBreakCtx 12906 } 12907 12908 func (p *project) expressionStatement(f *function, n *cc.ExpressionStatement) { 12909 p.w("%s", tidyComment("\n", n)) 12910 // Expression AttributeSpecifierList ';' 12911 if n.Expression == nil { 12912 return 12913 } 12914 12915 p.expression(f, n.Expression, n.Expression.Operand.Type(), exprVoid, 0) 12916 } 12917 12918 func (p *project) labeledStatement(f *function, n *cc.LabeledStatement) (r *cc.JumpStatement) { 12919 if f.hasJumps { //TODO merge with ...Flat below 12920 return p.labeledStatementFlat(f, n) 12921 } 12922 12923 switch n.Case { 12924 case cc.LabeledStatementLabel: // IDENTIFIER ':' AttributeSpecifierList Statement 12925 if _, ok := f.unusedLabels[n.Token.Value]; ok { 12926 p.w("goto %s;", f.labelNames[n.Token.Value]) 12927 } 12928 p.w("%s%s:", comment("\n", n), f.labelNames[n.Token.Value]) 12929 r = p.statement(f, n.Statement, false, false, false, 0) 12930 case 12931 cc.LabeledStatementCaseLabel, // "case" ConstantExpression ':' Statement 12932 cc.LabeledStatementDefault: // "default" ':' Statement 12933 12934 p.labeledStatementCase(f, n) 12935 case cc.LabeledStatementRange: // "case" ConstantExpression "..." ConstantExpression ':' Statement 12936 panic(todo("", n.Position(), n.Case)) 12937 default: 12938 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 12939 } 12940 return r 12941 } 12942 12943 func (p *project) labeledStatementFlat(f *function, n *cc.LabeledStatement) (r *cc.JumpStatement) { 12944 switch n.Case { 12945 case cc.LabeledStatementLabel: // IDENTIFIER ':' AttributeSpecifierList Statement 12946 if _, ok := f.unusedLabels[n.Token.Value]; ok { 12947 p.w("goto %s;", f.labelNames[n.Token.Value]) 12948 } 12949 p.w("%s%s:", tidyComment("\n", n), f.labelNames[n.Token.Value]) 12950 r = p.statement(f, n.Statement, false, false, false, 0) 12951 case 12952 cc.LabeledStatementCaseLabel, // "case" ConstantExpression ':' Statement 12953 cc.LabeledStatementDefault: // "default" ':' Statement 12954 12955 p.labeledStatementCase(f, n) 12956 case cc.LabeledStatementRange: // "case" ConstantExpression "..." ConstantExpression ':' Statement 12957 panic(todo("", n.Position(), n.Case)) 12958 default: 12959 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 12960 } 12961 return r 12962 } 12963 12964 func (p *project) labeledStatementCase(f *function, n *cc.LabeledStatement) { 12965 switch f.switchCtx { 12966 case inSwitchFirst: 12967 f.switchCtx = inSwitchCase 12968 p.pauseCodegen = false 12969 case inSwitchCase: 12970 p.w("\nfallthrough;") 12971 case inSwitchSeenBreak: 12972 f.switchCtx = inSwitchCase 12973 case inSwitchFlat: 12974 // ok 12975 default: 12976 panic(todo("", n.Position(), f.switchCtx)) 12977 } 12978 switch n.Case { 12979 case cc.LabeledStatementCaseLabel: // "case" ConstantExpression ':' Statement 12980 switch { 12981 case f.switchCtx == inSwitchFlat: 12982 p.w("%s__%d:", tidyComment("\n", n), f.flatSwitchLabels[n]) 12983 default: 12984 p.w("%scase ", tidyComment("\n", n)) 12985 p.constantExpression(f, n.ConstantExpression, n.ConstantExpression.Operand.Type(), exprValue, 0) 12986 p.w(":") 12987 } 12988 case cc.LabeledStatementDefault: // "default" ':' Statement 12989 switch { 12990 case f.switchCtx == inSwitchFlat: 12991 p.w("%s__%d:", tidyComment("\n", n), f.flatSwitchLabels[n]) 12992 default: 12993 p.w("%sdefault:", tidyComment("\n", n)) 12994 } 12995 default: 12996 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 12997 } 12998 p.statement(f, n.Statement, false, false, false, 0) 12999 } 13000 13001 func (p *project) constantExpression(f *function, n *cc.ConstantExpression, t cc.Type, mode exprMode, flags flags) { 13002 // ConditionalExpression 13003 p.conditionalExpression(f, n.ConditionalExpression, t, mode, flags) 13004 } 13005 13006 func (p *project) functionDefinitionSignature(n cc.Node, f *function, tld *tld) { 13007 switch { 13008 case f.mainSignatureForced: 13009 p.w("%sfunc %s(%s *%sTLS, _ int32, _ uintptr) int32", tidyComment("\n", f.fndef), tld.name, f.tlsName, p.task.crt) 13010 default: 13011 p.w("%s", tidyComment("\n", f.fndef)) 13012 p.functionSignature(n, f, f.fndef.Declarator.Type(), tld.name) 13013 } 13014 } 13015 13016 func (p *project) functionSignature2(n cc.Node, f *function, t cc.Type, nm string) { 13017 p.w("func %s", nm) 13018 p.w("(_ *%sTLS", p.task.crt) 13019 suffix := 1 13020 for _, v := range t.Parameters() { 13021 if v.Type().Kind() == cc.Void { 13022 break 13023 } 13024 13025 pn := "_" 13026 if d := v.Declarator(); d != nil { 13027 pn = d.Name().String() 13028 if _, ok := reservedNames[pn]; ok { 13029 pn += strconv.Itoa(suffix) 13030 suffix++ 13031 } 13032 } 13033 p.w(", %s %s", pn, p.paramTyp(v.Declarator(), v.Type())) 13034 } 13035 if t.IsVariadic() { 13036 p.w(", _ /* va_list */ uintptr") 13037 } 13038 p.w(")") 13039 if rt := t.Result(); rt != nil && rt.Kind() != cc.Void { 13040 p.w(" %s", p.typ(n, rt)) 13041 } 13042 } 13043 13044 func (p *project) functionSignature(n cc.Node, f *function, t cc.Type, nm string) { 13045 p.w("func") 13046 if nm != "" { 13047 p.w(" %s", nm) 13048 } 13049 switch { 13050 case f == nil || nm == "": 13051 p.w("(*%sTLS", p.task.crt) 13052 default: 13053 p.w("(%s *%sTLS", f.tlsName, p.task.crt) 13054 } 13055 for _, v := range t.Parameters() { 13056 if v.Type().Kind() == cc.Void { 13057 break 13058 } 13059 13060 var pn string 13061 if f != nil && nm != "" { 13062 pn = "_" 13063 if d := v.Declarator(); d != nil { 13064 if local := f.locals[d]; local != nil { 13065 pn = local.name 13066 } 13067 } 13068 } 13069 p.w(", %s %s", pn, p.paramTyp(v.Declarator(), v.Type())) 13070 } 13071 if t.IsVariadic() { 13072 switch { 13073 case f == nil || nm == "": 13074 p.w(", uintptr") 13075 default: 13076 p.w(", %s uintptr", f.vaName) 13077 } 13078 } 13079 p.w(")") 13080 if rt := t.Result(); rt != nil && rt.Kind() != cc.Void { 13081 p.w(" %s", p.typ(n, rt)) 13082 } 13083 } 13084 13085 func (p *project) paramTyp(n cc.Node, t cc.Type) string { 13086 if t.Kind() == cc.Array { 13087 return "uintptr" 13088 } 13089 13090 if isTransparentUnion(t) { 13091 switch k := t.UnionCommon(); k { 13092 case cc.Ptr: 13093 return "uintptr" 13094 default: 13095 panic(todo("%v: %v %k", n, t, k)) 13096 } 13097 } 13098 13099 return p.typ(n, t) 13100 } 13101 13102 func (p *project) dbg(a ...interface{}) { 13103 p.w("/*DBG.%v %v */", a, origin(2)) 13104 } 13105 13106 func (p *project) fnVal(n cc.Node, f *function, expr func(), exprDecl *cc.Declarator, exprType cc.Type, deref int, mode exprMode, flags flags) { 13107 // C type Go type 13108 // fn N/A: produce name from exprDecl 13109 // (*)() func() 13110 // (**)() *func() 13111 13112 if deref < 0 || deref > 1 { 13113 panic(todo("")) 13114 } 13115 13116 switch exprType.Kind() { 13117 case cc.Function: 13118 // C: fn 13119 switch deref { 13120 case 0: 13121 p.declarator(n, f, exprDecl, exprType, mode, flags) 13122 default: 13123 panic(todo("", n.Position())) 13124 } 13125 case cc.Ptr: 13126 switch et := exprType.Elem(); et.Kind() { 13127 case cc.Function: 13128 // C: (*)() 13129 switch deref { 13130 case 0: 13131 // (*struct{ f func()})(unsafe.Pointer(&struct{uintptr}{fprintfptr})).f() 13132 p.w("(*struct{ f ") 13133 p.functionSignature(n, f, et, "") 13134 p.w("})(unsafe.Pointer(&struct{uintptr}{") 13135 expr() 13136 p.w("})).f") 13137 default: 13138 p.declarator(n, f, exprDecl, et, mode, flags) 13139 } 13140 case cc.Ptr: 13141 switch et2 := et.Elem(); et2.Kind() { 13142 case cc.Function: 13143 // C: (**)() 13144 switch deref { 13145 case 0: 13146 panic(todo("", n.Position())) 13147 default: 13148 // (*struct{ f func()})(unsafe.Pointer(&struct{uintptr}{fprintfptr})).f() 13149 p.w("(*(**struct{ f ") 13150 p.functionSignature(n, f, et2, "") 13151 p.w("})(unsafe.Pointer(&struct{uintptr}{") 13152 expr() 13153 p.w("}))).f") 13154 } 13155 default: 13156 panic(todo("", n.Position(), et2.Kind(), deref)) 13157 } 13158 default: 13159 panic(todo("", n.Position(), et.Kind(), deref)) 13160 } 13161 default: 13162 panic(todo("", n.Position(), exprType.Kind(), deref)) 13163 } 13164 }