modernc.org/ccgo/v3@v3.16.14/lib/go.go (about) 1 // Copyright 2020 The CCGO Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package ccgo // import "modernc.org/ccgo/v3/lib" 6 7 import ( 8 "bytes" 9 "fmt" 10 "go/scanner" 11 "go/token" 12 "hash/maphash" 13 "io/ioutil" 14 "math" 15 "math/big" 16 "os" 17 "os/exec" 18 "path/filepath" 19 "runtime" 20 "sort" 21 "strconv" 22 "strings" 23 "sync" 24 "time" 25 26 "modernc.org/cc/v3" 27 "modernc.org/mathutil" 28 ) 29 30 var ( 31 idAddOverflow = cc.String("__builtin_add_overflow") // bool __builtin_add_overflow (type1 a, type2 b, type3 *res) 32 idAlias = cc.String("alias") 33 idAligned = cc.String("aligned") // int __attribute__ ((aligned (8))) foo; 34 idAtomicLoadN = cc.String("__atomic_load_n") // type __atomic_load_n (type *ptr, int memorder) 35 idAtomicStoreN = cc.String("__atomic_store_n") // void __atomic_store_n (type *ptr, type val, int memorder) 36 idBp = cc.String("bp") 37 idBuiltinConstantPImpl = cc.String("__builtin_constant_p_impl") 38 idCAPI = cc.String("CAPI") 39 idChooseExpr = cc.String("__builtin_choose_expr") 40 idEnviron = cc.String("environ") 41 idMain = cc.String("main") 42 idMulOverflow = cc.String("__builtin_mul_overflow") // bool __builtin_mul_overflow (type1 a, type2 b, type3 *res) 43 idPacked = cc.String("packed") // __attribute__((packed)) 44 idSubOverflow = cc.String("__builtin_sub_overflow") // bool __builtin_sub_overflow (type1 a, type2 b, type3 *res) 45 idTls = cc.String("tls") 46 idTransparentUnion = cc.String("__transparent_union__") 47 idTs = cc.String("ts") 48 idVa = cc.String("va") 49 idVaArg = cc.String("__ccgo_va_arg") 50 idVaEnd = cc.String("__ccgo_va_end") 51 idVaList = cc.String("va_list") 52 idVaStart = cc.String("__ccgo_va_start") 53 idWcharT = cc.String("wchar_t") 54 idWinWchar = cc.String("WCHAR") 55 idWtext = cc.String("wtext") 56 57 bytesBufferPool = sync.Pool{New: func() interface{} { return &bytes.Buffer{} }} 58 59 oTraceG bool 60 oTraceW bool 61 oTracePin bool 62 ) 63 64 type exprMode int 65 66 const ( 67 doNotExport = iota 68 doNotChange 69 exportCapitalize 70 exportPrefix 71 ) 72 73 const ( 74 _ exprMode = iota 75 exprAddrOf // &foo as uinptr (must be static/pinned) 76 exprBool // foo in foo != 0 77 exprCondInit // foo or bar in int i = x ? foo : bar; 78 exprCondReturn // foo or bar in return x ? foo : bar; 79 exprDecay // &foo[0] in foo for array foo. 80 exprFunc // foo in foo(bar) 81 exprLValue // foo in foo = bar 82 exprPSelect // foo in foo->bar 83 exprSelect // foo in foo.bar 84 exprValue // foo in bar = foo 85 exprVoid // 86 exprGoPtr 87 ) 88 89 const ( 90 tooManyErrors = "too many errors" 91 ) 92 93 type opKind int 94 95 const ( 96 opNormal opKind = iota 97 opArray 98 opArrayParameter 99 opFunction 100 opUnion 101 opBitfield 102 opStruct 103 ) 104 105 type flags byte 106 107 const ( 108 fForceConv flags = 1 << iota 109 fForceNoConv 110 fForceRuntimeConv 111 fNoCondAssignment 112 fAddrOfFuncPtrOk 113 fVolatileOk 114 ) 115 116 type imported struct { 117 path string // Eg. "example.com/user/foo". 118 name string // Eg. "foo" from "package foo". 119 qualifier string // Eg. "foo." or "foo2." if renamed due to name conflict. 120 exports map[string]struct{} // Eg. {"New": {}, "Close": {}, ...}. 121 122 used bool 123 } 124 125 type taggedStruct struct { 126 ctyp cc.Type 127 gotyp string 128 name string 129 node cc.Node 130 131 conflicts bool 132 emitted bool 133 } 134 135 func (s *taggedStruct) emit(p *project, ds *cc.DeclarationSpecifiers) { 136 if s == nil || s.emitted { 137 return 138 } 139 140 s.emitted = true 141 p.w("%stype %s = %s; /* %v */\n\n", tidyComment("\n", ds), s.name, s.gotyp, p.pos(s.node)) 142 } 143 144 // Return first non empty token separator within n or dflt otherwise. 145 func comment(dflt string, n cc.Node) string { 146 if s := tokenSeparator(n); s != "" { 147 return s 148 } 149 150 return dflt 151 } 152 153 // tidyComment is like comment but makes comment more Go-like. 154 func tidyComment(dflt string, n cc.Node) (r string) { return tidyCommentString(comment(dflt, n)) } 155 156 func tidyCommentString(s string) (r string) { 157 defer func() { 158 if !strings.Contains(r, "// <blockquote><pre>") { 159 return 160 } 161 162 a := strings.Split(r, "\n") 163 in := false 164 for i, v := range a { 165 switch { 166 case in: 167 if strings.HasPrefix(v, "// </pre></blockquote>") { 168 in = false 169 a[i] = "//" 170 break 171 } 172 173 a[i] = fmt.Sprintf("//\t%s", v[3:]) 174 default: 175 if strings.HasPrefix(v, "// <blockquote><pre>") { 176 a[i] = "//" 177 in = true 178 } 179 } 180 } 181 r = strings.Join(a, "\n") 182 }() 183 184 s = strings.ReplaceAll(s, "\f", "") 185 b := bytesBufferPool.Get().(*bytes.Buffer) 186 defer func() { b.Reset(); bytesBufferPool.Put(b) }() 187 for len(s) != 0 { 188 c := s[0] 189 s = s[1:] 190 if len(s) == 0 { 191 b.WriteByte(c) 192 break 193 } 194 195 if c != '/' { 196 b.WriteByte(c) 197 continue 198 } 199 200 c2 := s[0] 201 s = s[1:] 202 switch c2 { 203 case '/': // line comment start 204 b.WriteByte(c) 205 b.WriteByte(c2) 206 for { 207 c := s[0] 208 s = s[1:] 209 b.WriteByte(c) 210 if c == '\n' { 211 break 212 } 213 } 214 case '*': // block comment start 215 b2 := bytesBufferPool.Get().(*bytes.Buffer) 216 defer func() { b2.Reset(); bytesBufferPool.Put(b2) }() 217 for { 218 c := s[0] 219 s = s[1:] 220 if c != '*' { 221 b2.WriteByte(c) 222 continue 223 } 224 225 more: 226 c2 := s[0] 227 s = s[1:] 228 if c2 == '*' { 229 b2.WriteByte(c) 230 goto more 231 } 232 233 if c2 != '/' { 234 b2.WriteByte(c) 235 b2.WriteByte(c2) 236 continue 237 } 238 239 break 240 } 241 s2 := b2.String() // comment sans /* prefix and */ suffix 242 a := strings.Split(s2, "\n") 243 nl := len(s) != 0 && s[0] == '\n' 244 if len(a) == 1 { // /* foo */ form 245 if nl { 246 s = s[1:] 247 fmt.Fprintf(b, "//%s\n", s2) 248 break 249 } 250 251 fmt.Fprintf(b, "/*%s*/", s2) 252 break 253 } 254 255 if !nl { 256 fmt.Fprintf(b, "/*%s*/", s2) 257 break 258 } 259 260 // Block comment followed by a newline can be safely replaced by a sequence of 261 // line comments. Try to enhance the comment. 262 if commentForm1(b, a) || 263 commentForm2(b, a) || 264 commentForm3(b, a) { 265 break 266 } 267 268 // No enhancement posibilities detected, use the default form. 269 if a[len(a)-1] == "" { 270 a = a[:len(a)-1] 271 } 272 fmt.Fprintf(b, "//%s", a[0]) 273 for _, v := range a[1:] { 274 fmt.Fprintf(b, "\n// %s", v) 275 } 276 default: 277 b.WriteByte(c) 278 b.WriteByte(c2) 279 } 280 } 281 return b.String() 282 } 283 284 func commentForm1(b *bytes.Buffer, a []string) bool { 285 // Example 286 // 287 // /* 288 // ** Initialize this module. 289 // ** 290 // ** This Tcl module contains only a single new Tcl command named "sqlite". 291 // ** (Hence there is no namespace. There is no point in using a namespace 292 // ** if the extension only supplies one new name!) The "sqlite" command is 293 // ** used to open a new SQLite database. See the DbMain() routine above 294 // ** for additional information. 295 // ** 296 // ** The EXTERN macros are required by TCL in order to work on windows. 297 // */ 298 if strings.TrimSpace(a[0]) != "" { 299 return false 300 } 301 302 if strings.TrimSpace(a[len(a)-1]) != "" { 303 return false 304 } 305 306 a = a[1 : len(a)-1] 307 if len(a) == 0 { 308 return false 309 } 310 311 for i, v := range a { 312 v = strings.TrimSpace(v) 313 if !strings.HasPrefix(v, "*") { 314 return false 315 } 316 317 a[i] = strings.TrimLeft(v, "*") 318 } 319 320 fmt.Fprintf(b, "//%s", a[0]) 321 for _, v := range a[1:] { 322 fmt.Fprintf(b, "\n//%s", v) 323 } 324 return true 325 } 326 327 func commentForm2(b *bytes.Buffer, a []string) bool { 328 // Example 329 // 330 // /**************************** sqlite3_column_ ******************************* 331 // ** The following routines are used to access elements of the current row 332 // ** in the result set. 333 // */ 334 if strings.TrimSpace(a[len(a)-1]) != "" { 335 return false 336 } 337 338 a = a[:len(a)-1] 339 if len(a) == 0 { 340 return false 341 } 342 343 for i, v := range a[1:] { 344 v = strings.TrimSpace(v) 345 if !strings.HasPrefix(v, "*") { 346 return false 347 } 348 349 a[i+1] = strings.TrimLeft(v, "*") 350 } 351 352 fmt.Fprintf(b, "// %s", strings.TrimSpace(a[0])) 353 if strings.HasPrefix(a[0], "**") && strings.HasSuffix(a[0], "**") { 354 fmt.Fprintf(b, "\n//") 355 } 356 for _, v := range a[1:] { 357 fmt.Fprintf(b, "\n//%s", v) 358 } 359 return true 360 } 361 362 func commentForm3(b *bytes.Buffer, a []string) bool { 363 // Example 364 // 365 // /* Call sqlite3_shutdown() once before doing anything else. This is to 366 // ** test that sqlite3_shutdown() can be safely called by a process before 367 // ** sqlite3_initialize() is. */ 368 for i, v := range a[1:] { 369 v = strings.TrimSpace(v) 370 if !strings.HasPrefix(v, "*") { 371 return false 372 } 373 374 a[i+1] = strings.TrimLeft(v, "*") 375 } 376 377 fmt.Fprintf(b, "// %s", strings.TrimSpace(a[0])) 378 if strings.HasPrefix(a[0], "**") && strings.HasSuffix(a[0], "**") { 379 fmt.Fprintf(b, "\n//") 380 } 381 for _, v := range a[1:] { 382 fmt.Fprintf(b, "\n//%s", v) 383 } 384 return true 385 } 386 387 // Return the preceding white space, including any comments, of the first token 388 // of n. 389 func tokenSeparator(n cc.Node) (r string) { 390 if n == nil { 391 return "" 392 } 393 394 var tok cc.Token 395 cc.Inspect(n, func(n cc.Node, _ bool) bool { 396 if x, ok := n.(*cc.Token); ok { 397 if a, b := tok.Seq(), x.Seq(); a == 0 || a > x.Seq() && b != 0 { 398 tok = *x 399 } 400 } 401 return true 402 }) 403 return tok.Sep.String() 404 } 405 406 func source(n ...cc.Node) (r string) { 407 if len(n) == 0 { 408 return "<nil>" 409 } 410 411 var a []*cc.Token 412 for _, v := range n { 413 cc.Inspect(v, func(n cc.Node, _ bool) bool { 414 if x, ok := n.(*cc.Token); ok && x.Seq() != 0 { 415 a = append(a, x) 416 } 417 return true 418 }) 419 } 420 sort.Slice(a, func(i, j int) bool { 421 return a[i].Seq() < a[j].Seq() 422 }) 423 w := 0 424 seq := -1 425 for _, v := range a { 426 if n := v.Seq(); n != seq { 427 seq = n 428 a[w] = v 429 w++ 430 } 431 } 432 a = a[:w] 433 var b strings.Builder 434 for _, v := range a { 435 b.WriteString(v.Sep.String()) 436 b.WriteString(v.Src.String()) 437 } 438 return b.String() 439 } 440 441 type initPatch struct { 442 t cc.Type 443 init *cc.Initializer 444 fld cc.Field 445 } 446 447 type tld struct { 448 name string // Can differ from the original one. 449 patches []initPatch 450 } 451 452 type block struct { 453 block *cc.CompoundStatement 454 decls []*cc.Declaration // What to declare in this block. 455 params []*cc.Parameter 456 parent *block 457 scope scope 458 459 noDecl bool // Locals declared in one of the parent scopes. 460 topDecl bool // Declare locals at block start to avoid "jumps over declaration". 461 } 462 463 func newBlock(parent *block, n *cc.CompoundStatement, decls []*cc.Declaration, params []*cc.Parameter, scope scope, topDecl bool) *block { 464 return &block{ 465 block: n, 466 decls: decls, 467 params: params, 468 parent: parent, 469 scope: scope, 470 topDecl: topDecl, 471 } 472 } 473 474 type local struct { 475 name string 476 off uintptr // If isPinned: bp+off 477 478 forceRead bool // Possibly never read. 479 isPinned bool // Prevent this local from being placed in Go movable stack. 480 } 481 482 type switchState int 483 484 const ( 485 _ switchState = iota // Not in switch. 486 inSwitchFirst // Before seeing "case/default". 487 inSwitchCase // Seen "case/default". 488 inSwitchSeenBreak // In switch "case/default" and seen "break/return". 489 inSwitchFlat 490 ) 491 492 type function struct { 493 block *block 494 blocks map[*cc.CompoundStatement]*block 495 bpName string 496 breakCtx int //TODO merge with continueCtx 497 complits map[*cc.PostfixExpression]uintptr 498 condInitPrefix func() 499 continueCtx int 500 flatLabels int 501 flatSwitchLabels map[*cc.LabeledStatement]int 502 fndef *cc.FunctionDefinition 503 gen *project 504 ifCtx cc.Node 505 ignore map[*cc.Declarator]bool // Pseudo declarators 506 labelNames map[cc.StringID]string 507 labels scope 508 locals map[*cc.Declarator]*local 509 off uintptr // bp+off allocs 510 params []*cc.Parameter // May differ from what fndef says 511 project *project 512 rt cc.Type // May differ from what fndef says 513 scope scope 514 switchCtx switchState 515 tlsName string 516 top *block 517 unusedLabels map[cc.StringID]struct{} 518 vaLists map[*cc.PostfixExpression]uintptr 519 vaName string 520 vaType cc.Type 521 vlas map[*cc.Declarator]struct{} 522 523 hasJumps bool 524 mainSignatureForced bool 525 } 526 527 func newFunction(p *project, n *cc.FunctionDefinition) *function { 528 d := n.Declarator 529 t := d.Type() 530 rt := t.Result() 531 params := t.Parameters() 532 var mainSignatureForced bool 533 var ignore map[*cc.Declarator]bool 534 if d.Name() == idMain && d.Linkage == cc.External { 535 if rt.Kind() != cc.Int { 536 rt = p.task.cfg.ABI.Type(cc.Int) 537 } 538 if len(params) != 2 { 539 mainSignatureForced = true 540 d1 := newDeclarator("argc") 541 t1 := p.task.cfg.ABI.Type(cc.Int) 542 d2 := newDeclarator("argv") 543 t2 := p.task.cfg.ABI.Ptr(n, p.task.cfg.ABI.Type(cc.Void)) 544 params = []*cc.Parameter{ 545 cc.NewParameter(d1, t1), 546 cc.NewParameter(d2, t2), 547 } 548 ignore = map[*cc.Declarator]bool{d1: true, d2: true} 549 } 550 } 551 f := &function{ 552 blocks: map[*cc.CompoundStatement]*block{}, 553 complits: map[*cc.PostfixExpression]uintptr{}, 554 fndef: n, 555 gen: p, 556 hasJumps: n.CompoundStatement.IsJumpTarget(), 557 ignore: ignore, 558 locals: map[*cc.Declarator]*local{}, 559 mainSignatureForced: mainSignatureForced, 560 params: params, 561 project: p, 562 rt: rt, 563 scope: p.newScope(), 564 unusedLabels: map[cc.StringID]struct{}{}, 565 vaLists: map[*cc.PostfixExpression]uintptr{}, 566 vlas: map[*cc.Declarator]struct{}{}, 567 } 568 f.tlsName = f.scope.take(idTls) 569 if t.IsVariadic() { 570 f.vaName = f.scope.take(idVa) 571 } 572 f.layoutLocals(nil, n.CompoundStatement, params) 573 var extern []cc.StringID 574 for _, v := range n.CompoundStatements() { // testdata/gcc-9.1.0/gcc/testsuite/gcc.c-torture/execute/scope-1.c 575 for _, v := range v.Declarations() { 576 for list := v.InitDeclaratorList; list != nil; list = list.InitDeclaratorList { 577 if d := list.InitDeclarator.Declarator; d != nil && d.IsExtern() { 578 extern = append(extern, d.Name()) 579 } 580 } 581 } 582 } 583 for _, v := range n.CompoundStatements() { 584 block := f.blocks[v] 585 for _, v := range extern { 586 if tld := f.project.externs[v]; tld != nil { 587 block.scope.take(cc.String(tld.name)) 588 } 589 } 590 } 591 for _, v := range n.CompoundStatements() { 592 f.layoutBlocks(v) 593 } 594 f.renameLabels() 595 f.staticAllocsAndPinned(n.CompoundStatement) 596 return f 597 } 598 599 func (f *function) flatLabel() int { 600 if f.project.pass1 { 601 return 1 602 } 603 604 f.flatLabels++ 605 return f.flatLabels 606 } 607 608 func (f *function) renameLabels() { 609 var a []cc.StringID 610 for _, v := range f.fndef.Labels { 611 if v.Case != cc.LabeledStatementLabel { 612 continue 613 } 614 615 a = append(a, v.Token.Value) 616 f.unusedLabels[v.Token.Value] = struct{}{} 617 } 618 for _, v := range f.fndef.Gotos { 619 delete(f.unusedLabels, v.Token2.Value) 620 } 621 if len(a) == 0 { 622 return 623 } 624 sort.Slice(a, func(i, j int) bool { return a[i].String() < a[j].String() }) 625 f.labels = newScope() 626 f.labelNames = map[cc.StringID]string{} 627 for _, id := range a { 628 f.labelNames[id] = f.labels.take(id) 629 } 630 } 631 632 func (f *function) staticAllocsAndPinned(n *cc.CompoundStatement) { 633 for _, v := range f.params { 634 switch { 635 case v.Type().Kind() == cc.Array && v.Type().IsVLA(): 636 // trc("VLA") 637 f.project.err(f.fndef, "variable length arrays not supported") 638 } 639 } 640 641 //TODO use pass1 for this 642 cc.Inspect(n, func(n cc.Node, entry bool) bool { 643 if !entry { 644 return true 645 } 646 647 switch x := n.(type) { 648 case *cc.CastExpression: 649 switch x.Case { 650 case cc.CastExpressionCast: // '(' TypeName ')' CastExpression 651 if t := x.TypeName.Type(); t != nil && t.Kind() != cc.Void { 652 break 653 } 654 655 if d := x.CastExpression.Declarator(); d != nil { 656 if local := f.locals[d]; local != nil { 657 local.forceRead = true 658 } 659 } 660 } 661 } 662 663 x, ok := n.(*cc.PostfixExpression) 664 if !ok || x.Case != cc.PostfixExpressionCall { 665 return true 666 } 667 668 if x.PostfixExpression == nil || x.PostfixExpression.Operand == nil || x.PostfixExpression.Operand.Type() == nil { 669 return true 670 } 671 672 ft := funcType(x.PostfixExpression.Operand.Type()) 673 if ft.Kind() != cc.Function { 674 return true 675 } 676 677 if !ft.IsVariadic() { 678 return true 679 } 680 681 fixedParams := len(ft.Parameters()) 682 iArg := 0 683 var need uintptr 684 for list := x.ArgumentExpressionList; list != nil; list, iArg = list.ArgumentExpressionList, iArg+1 { 685 if iArg < fixedParams { 686 continue 687 } 688 689 t := list.AssignmentExpression.Operand.Type() 690 if t.IsIntegerType() { 691 need += 8 692 continue 693 } 694 695 switch t.Kind() { 696 case cc.Array, cc.Ptr, cc.Double, cc.Float, cc.Function: 697 need += 8 698 default: 699 panic(todo("", f.project.pos(x), t, t.Kind())) 700 } 701 } 702 if need != 0 { 703 //TODO- if f.project.task.mingw { 704 //TODO- need += 8 // On windows the va list is prefixed with its length 705 //TODO- } 706 va := roundup(f.off, 8) 707 f.vaLists[x] = va 708 f.off = va + need 709 } 710 return true 711 }) 712 } 713 714 func funcType(t cc.Type) cc.Type { 715 if t.Kind() == cc.Ptr { 716 t = t.Elem() 717 } 718 return t 719 } 720 721 type declarator interface { 722 Declarator() *cc.Declarator 723 cc.Node 724 } 725 726 func (p *project) isArrayParameterDeclarator(d *cc.Declarator) bool { 727 if d.Type().Kind() == cc.Array { 728 if d.Type().IsVLA() { 729 return false 730 } 731 732 return d.IsParameter 733 } 734 735 return false 736 } 737 738 func (p *project) isArrayDeclarator(d *cc.Declarator) bool { 739 if d.Type().Kind() == cc.Array { 740 if d.Type().IsVLA() { 741 return false 742 } 743 744 return !d.IsParameter 745 } 746 747 return false 748 } 749 750 func (p *project) isArrayParameter(n declarator, t cc.Type) bool { 751 if t.Kind() != cc.Array { 752 return false 753 } 754 755 if t.IsVLA() { 756 return false 757 } 758 759 if d := n.Declarator(); d != nil { 760 return d.IsParameter 761 } 762 763 return false 764 } 765 766 func (p *project) isArrayOrPinnedArray(f *function, n declarator, t cc.Type) (r bool) { 767 if t.Kind() != cc.Array { 768 return false 769 } 770 771 if t.IsVLA() { 772 return false 773 } 774 775 if d := n.Declarator(); d != nil { 776 return !d.IsParameter 777 } 778 779 return p.detectArray(f, n.(cc.Node), true, true, nil) 780 } 781 782 func (p *project) detectArray(f *function, n cc.Node, pinnedOk, recursiveOk bool, out **cc.Declarator) bool { 783 switch x := n.(type) { 784 case *cc.AssignmentExpression: 785 switch x.Case { 786 case cc.AssignmentExpressionCond: // ConditionalExpression 787 return p.detectArray(f, x.ConditionalExpression, pinnedOk, recursiveOk, out) 788 case cc.AssignmentExpressionAssign: // UnaryExpression '=' AssignmentExpression 789 return p.detectArray(f, x.UnaryExpression, pinnedOk, recursiveOk, out) 790 default: 791 return false 792 } 793 case *cc.ConditionalExpression: 794 switch x.Case { 795 case cc.ConditionalExpressionLOr: // LogicalOrExpression 796 return p.detectArray(f, x.LogicalOrExpression, pinnedOk, recursiveOk, out) 797 case cc.ConditionalExpressionCond: // LogicalOrExpression '?' Expression ':' ConditionalExpression 798 return p.detectArray(f, x.LogicalOrExpression, pinnedOk, recursiveOk, out) || 799 p.detectArray(f, x.Expression, pinnedOk, recursiveOk, out) || 800 p.detectArray(f, x.ConditionalExpression, pinnedOk, recursiveOk, out) 801 default: 802 panic(todo("", p.pos(x), x.Case)) 803 } 804 case *cc.LogicalOrExpression: 805 switch x.Case { 806 case cc.LogicalOrExpressionLAnd: // LogicalAndExpression 807 return p.detectArray(f, x.LogicalAndExpression, pinnedOk, recursiveOk, out) 808 default: 809 return false 810 } 811 case *cc.LogicalAndExpression: 812 switch x.Case { 813 case cc.LogicalAndExpressionOr: // InclusiveOrExpression 814 return p.detectArray(f, x.InclusiveOrExpression, pinnedOk, recursiveOk, out) 815 default: 816 return false 817 } 818 case *cc.InclusiveOrExpression: 819 switch x.Case { 820 case cc.InclusiveOrExpressionXor: // ExclusiveOrExpression 821 return p.detectArray(f, x.ExclusiveOrExpression, pinnedOk, recursiveOk, out) 822 default: 823 return false 824 } 825 case *cc.ExclusiveOrExpression: 826 switch x.Case { 827 case cc.ExclusiveOrExpressionAnd: // AndExpression 828 return p.detectArray(f, x.AndExpression, pinnedOk, recursiveOk, out) 829 default: 830 return false 831 } 832 case *cc.AndExpression: 833 switch x.Case { 834 case cc.AndExpressionEq: // EqualityExpression 835 return p.detectArray(f, x.EqualityExpression, pinnedOk, recursiveOk, out) 836 default: 837 return false 838 } 839 case *cc.EqualityExpression: 840 switch x.Case { 841 case cc.EqualityExpressionRel: // RelationalExpression 842 return p.detectArray(f, x.RelationalExpression, pinnedOk, recursiveOk, out) 843 default: 844 return false 845 } 846 case *cc.RelationalExpression: 847 switch x.Case { 848 case cc.RelationalExpressionShift: // ShiftExpression 849 return p.detectArray(f, x.ShiftExpression, pinnedOk, recursiveOk, out) 850 default: 851 return false 852 } 853 case *cc.ShiftExpression: 854 switch x.Case { 855 case cc.ShiftExpressionAdd: // AdditiveExpression 856 return p.detectArray(f, x.AdditiveExpression, pinnedOk, recursiveOk, out) 857 default: 858 return false 859 } 860 case *cc.AdditiveExpression: 861 switch x.Case { 862 case cc.AdditiveExpressionMul: // MultiplicativeExpression 863 return p.detectArray(f, x.MultiplicativeExpression, pinnedOk, recursiveOk, out) 864 case 865 cc.AdditiveExpressionSub, // AdditiveExpression '-' MultiplicativeExpression 866 cc.AdditiveExpressionAdd: // AdditiveExpression '+' MultiplicativeExpression 867 868 return p.detectArray(f, x.AdditiveExpression, pinnedOk, recursiveOk, out) || p.detectArray(f, x.MultiplicativeExpression, pinnedOk, recursiveOk, out) 869 default: 870 panic(todo("", p.pos(x), x.Case)) 871 } 872 case *cc.MultiplicativeExpression: 873 switch x.Case { 874 case cc.MultiplicativeExpressionCast: // CastExpression 875 return p.detectArray(f, x.CastExpression, pinnedOk, recursiveOk, out) 876 default: 877 return false 878 } 879 case *cc.CastExpression: 880 switch x.Case { 881 case cc.CastExpressionUnary: // UnaryExpression 882 return p.detectArray(f, x.UnaryExpression, pinnedOk, recursiveOk, out) 883 case cc.CastExpressionCast: // '(' TypeName ')' CastExpression 884 return p.detectArray(f, x.CastExpression, pinnedOk, recursiveOk, out) 885 default: 886 panic(todo("", p.pos(x), x.Case)) 887 } 888 case *cc.UnaryExpression: 889 switch x.Case { 890 case cc.UnaryExpressionPostfix: // PostfixExpression 891 return p.detectArray(f, x.PostfixExpression, pinnedOk, recursiveOk, out) 892 case 893 cc.UnaryExpressionDeref, // '*' CastExpression 894 cc.UnaryExpressionAddrof: // '&' CastExpression 895 896 return p.detectArray(f, x.CastExpression, pinnedOk, recursiveOk, out) 897 case 898 cc.UnaryExpressionSizeofExpr, // "sizeof" UnaryExpression 899 cc.UnaryExpressionSizeofType, // "sizeof" '(' TypeName ')' 900 cc.UnaryExpressionMinus, // '-' CastExpression 901 cc.UnaryExpressionCpl, // '~' CastExpression 902 cc.UnaryExpressionAlignofExpr, // "_Alignof" UnaryExpression 903 cc.UnaryExpressionAlignofType, // "_Alignof" '(' TypeName ')' 904 cc.UnaryExpressionNot, // '!' CastExpression 905 cc.UnaryExpressionInc, // "++" UnaryExpression 906 cc.UnaryExpressionDec, // "--" UnaryExpression 907 cc.UnaryExpressionPlus: // '+' CastExpression 908 909 return false 910 default: 911 panic(todo("", p.pos(x), x.Case)) 912 } 913 case *cc.PostfixExpression: 914 switch x.Case { 915 case cc.PostfixExpressionPrimary: // PrimaryExpression 916 return p.detectArray(f, x.PrimaryExpression, pinnedOk, recursiveOk, out) 917 case cc.PostfixExpressionIndex: // PostfixExpression '[' Expression ']' 918 return recursiveOk && p.detectArray(f, x.PostfixExpression, pinnedOk, recursiveOk, out) 919 case 920 cc.PostfixExpressionSelect, // PostfixExpression '.' IDENTIFIER 921 cc.PostfixExpressionDec, // PostfixExpression "--" 922 cc.PostfixExpressionInc, // PostfixExpression "++" 923 cc.PostfixExpressionCall, // PostfixExpression '(' ArgumentExpressionList ')' 924 cc.PostfixExpressionComplit, // '(' TypeName ')' '{' InitializerList ',' '}' 925 cc.PostfixExpressionPSelect: // PostfixExpression "->" IDENTIFIER 926 927 return false 928 default: 929 panic(todo("", p.pos(x), x.Case)) 930 } 931 case *cc.PrimaryExpression: 932 switch x.Case { 933 case 934 cc.PrimaryExpressionString, // STRINGLITERAL 935 cc.PrimaryExpressionEnum, // ENUMCONST 936 cc.PrimaryExpressionChar, // CHARCONST 937 cc.PrimaryExpressionLChar, // LONGCHARCONST 938 cc.PrimaryExpressionLString, // LONGSTRINGLITERAL 939 cc.PrimaryExpressionFloat, // FLOATCONST 940 cc.PrimaryExpressionInt: // INTCONST 941 942 return false 943 case cc.PrimaryExpressionIdent: // IDENTIFIER 944 d := x.Declarator() 945 if d == nil || d.IsParameter { 946 return false 947 } 948 949 if d.Type().Kind() != cc.Array { 950 return false 951 } 952 953 if d.Type().IsVLA() { 954 return false 955 } 956 957 if pinnedOk { 958 if out != nil { 959 *out = d 960 } 961 return true 962 } 963 964 local := f.locals[d] 965 if local == nil || local.isPinned { 966 return false 967 } 968 969 if out != nil { 970 *out = d 971 } 972 return true 973 case cc.PrimaryExpressionExpr: // '(' Expression ')' 974 return p.detectArray(f, x.Expression, pinnedOk, recursiveOk, out) 975 case cc.PrimaryExpressionStmt: // '(' CompoundStatement ')' 976 p.err(x, "statement expressions not supported") 977 return false 978 default: 979 panic(todo("", p.pos(x), x.Case)) 980 } 981 case *cc.Expression: 982 switch x.Case { 983 case cc.ExpressionAssign: // AssignmentExpression 984 return p.detectArray(f, x.AssignmentExpression, pinnedOk, recursiveOk, out) 985 case cc.ExpressionComma: // Expression ',' AssignmentExpression 986 return p.detectArray(f, x.Expression, pinnedOk, recursiveOk, out) || p.detectArray(f, x.AssignmentExpression, pinnedOk, recursiveOk, out) 987 default: 988 panic(todo("", p.pos(x), x.Case)) 989 } 990 default: 991 panic(todo("%T", x)) 992 } 993 } 994 995 func (p *project) isArray(f *function, n declarator, t cc.Type) (r bool) { 996 if t.Kind() != cc.Array { 997 return false 998 } 999 1000 if t.IsVLA() { 1001 return false 1002 } 1003 1004 if f == nil { 1005 return true 1006 } 1007 1008 if d := n.Declarator(); d != nil { 1009 local := f.locals[d] 1010 return !d.IsParameter && (local == nil || !local.isPinned) 1011 } 1012 1013 return p.detectArray(f, n.(cc.Node), false, true, nil) 1014 } 1015 1016 var home = os.Getenv("HOME") 1017 1018 // Return n's position with path reduced to baseName(path) unless 1019 // p.task.fullPathComments is true. 1020 func (p *project) pos(n cc.Node) (r token.Position) { 1021 if n == nil { 1022 return r 1023 } 1024 1025 if r = token.Position(n.Position()); r.IsValid() { 1026 switch { 1027 case p.task.fullPathComments: 1028 if strings.HasPrefix(r.Filename, home) { 1029 r.Filename = "$HOME" + r.Filename[len(home):] 1030 } 1031 default: 1032 r.Filename = filepath.Base(r.Filename) 1033 } 1034 } 1035 return r 1036 } 1037 1038 // Return n's position with path reduced to baseName(path). 1039 func pos(n cc.Node) (r token.Position) { 1040 if n == nil { 1041 return r 1042 } 1043 1044 r = token.Position(n.Position()) 1045 if r.IsValid() { 1046 r.Filename = filepath.Base(r.Filename) 1047 } 1048 return r 1049 } 1050 1051 func roundup(n, to uintptr) uintptr { 1052 if r := n % to; r != 0 { 1053 return n + to - r 1054 } 1055 1056 return n 1057 } 1058 1059 func (f *function) pin(n cc.Node, d *cc.Declarator) { 1060 local := f.locals[d] 1061 if local == nil || local.isPinned { 1062 return 1063 } 1064 1065 local.isPinned = true 1066 if oTracePin || f.project.task.tracePinning { 1067 fmt.Printf("%v: %s at %v: is pinned (%v)\n", n.Position(), d.Name(), d.Position(), origin(2)) 1068 } 1069 local.off = roundup(f.off, uintptr(d.Type().Align())) 1070 f.off = local.off + paramTypeDecay(d).Size() 1071 } 1072 1073 func paramTypeDecay(d *cc.Declarator) (r cc.Type) { 1074 r = d.Type() 1075 if d.IsParameter && r.Kind() == cc.Array { 1076 r = r.Decay() 1077 } 1078 return r 1079 } 1080 1081 func (f *function) layoutBlocks(n *cc.CompoundStatement) { 1082 block := f.blocks[n] 1083 type item struct { 1084 ds *cc.DeclarationSpecifiers 1085 d *cc.Declarator 1086 } 1087 var work []item 1088 for _, v := range block.params { 1089 if v.Type().Kind() == cc.Void { 1090 break 1091 } 1092 1093 work = append(work, item{nil, v.Declarator()}) 1094 } 1095 for _, decl := range block.decls { 1096 ds := decl.DeclarationSpecifiers 1097 for list := decl.InitDeclaratorList; list != nil; list = list.InitDeclaratorList { 1098 work = append(work, item{ds, list.InitDeclarator.Declarator}) 1099 } 1100 } 1101 block.scope.take(cc.String(f.tlsName)) 1102 if f.vaName != "" { 1103 block.scope.take(cc.String(f.vaName)) 1104 } 1105 for _, item := range work { 1106 d := item.d 1107 if f.ignore[d] { 1108 continue 1109 } 1110 1111 if !f.ignore[d] && d.IsStatic() { 1112 continue 1113 } 1114 1115 if d.IsFunctionPrototype() || d.IsExtern() { 1116 continue 1117 } 1118 1119 local := &local{forceRead: d.Read == 0} 1120 if t := d.Type(); t != nil && t.Name() == idVaList { 1121 local.forceRead = true 1122 } 1123 f.locals[d] = local 1124 local.name = block.scope.take(d.Name()) 1125 } 1126 } 1127 1128 func (f *function) layoutLocals(parent *block, n *cc.CompoundStatement, params []*cc.Parameter) { 1129 block := newBlock(parent, n, n.Declarations(), params, f.project.newScope(), n.IsJumpTarget()) 1130 f.blocks[n] = block 1131 if parent == nil { 1132 f.top = block 1133 f.top.topDecl = f.hasJumps 1134 } 1135 for _, ch := range n.Children() { 1136 f.layoutLocals(block, ch, nil) 1137 if f.hasJumps { 1138 chb := f.blocks[ch] 1139 chb.noDecl = true 1140 f.top.decls = append(f.top.decls, chb.decls...) 1141 chb.decls = nil 1142 } 1143 } 1144 } 1145 1146 func newDeclarator(name string) *cc.Declarator { 1147 return &cc.Declarator{ 1148 DirectDeclarator: &cc.DirectDeclarator{ 1149 Case: cc.DirectDeclaratorIdent, 1150 Token: cc.Token{Rune: cc.IDENTIFIER, Value: cc.String(name)}, 1151 }, 1152 } 1153 } 1154 1155 type enumSpec struct { 1156 decl *cc.Declaration 1157 spec *cc.EnumSpecifier 1158 1159 emitted bool 1160 } 1161 1162 func (n *enumSpec) emit(p *project) { 1163 if n == nil || p.pass1 || n.emitted { 1164 return 1165 } 1166 1167 n.emitted = true 1168 ok := false 1169 for list := n.spec.EnumeratorList; list != nil; list = list.EnumeratorList { 1170 nm := list.Enumerator.Token.Value 1171 if _, ok2 := p.emitedEnums[nm]; !ok2 && p.enumConsts[nm] != "" { 1172 ok = true 1173 break 1174 } 1175 } 1176 if !ok { 1177 return 1178 } 1179 1180 p.w("%s", tidyComment("\n", n.decl)) 1181 p.w("const ( /* %v: */", p.pos(n.decl)) 1182 for list := n.spec.EnumeratorList; list != nil; list = list.EnumeratorList { 1183 en := list.Enumerator 1184 nm := en.Token.Value 1185 if _, ok := p.emitedEnums[nm]; ok || p.enumConsts[nm] == "" { 1186 continue 1187 } 1188 1189 p.emitedEnums[nm] = struct{}{} 1190 p.w("%s%s = ", tidyComment("\n", en), p.enumConsts[nm]) 1191 p.intConst(en, "", en.Operand, en.Operand.Type(), fForceNoConv) 1192 p.w(";") 1193 } 1194 p.w(");") 1195 } 1196 1197 type typedef struct { 1198 sig uint64 1199 tld *tld 1200 } 1201 1202 type define struct { 1203 name string 1204 value cc.Value 1205 } 1206 1207 type project struct { 1208 ast *cc.AST 1209 buf bytes.Buffer 1210 capi []string 1211 defines map[cc.StringID]define 1212 defineLines []string 1213 emitedEnums map[cc.StringID]struct{} 1214 enumConsts map[cc.StringID]string 1215 enumSpecs map[*cc.EnumSpecifier]*enumSpec 1216 errors scanner.ErrorList 1217 externs map[cc.StringID]*tld 1218 fn string 1219 imports map[string]*imported // C name: import info 1220 intType cc.Type 1221 localTaggedStructs []func() 1222 mainName string 1223 ptrSize uintptr 1224 ptrType cc.Type 1225 scope scope 1226 sharedFns map[*cc.FunctionDefinition]struct{} 1227 sharedFnsEmitted map[*cc.FunctionDefinition]struct{} 1228 staticQueue []*cc.InitDeclarator 1229 structs map[cc.StringID]*taggedStruct // key: C tag 1230 symtab map[string]interface{} // *tld or *imported 1231 task *Task 1232 tldScope scope 1233 tlds map[*cc.Declarator]*tld 1234 ts bytes.Buffer // Text segment 1235 tsName string 1236 tsNameP string 1237 tsOffs map[cc.StringID]uintptr 1238 tsW []rune // Text segment, wchar_t 1239 tsWName string 1240 tsWNameP string 1241 tsWOffs map[cc.StringID]uintptr 1242 typeSigHash maphash.Hash 1243 typedefTypes map[cc.StringID]*typedef 1244 typedefsEmited map[string]struct{} 1245 verifyStructs map[string]cc.Type 1246 wanted map[*cc.Declarator]struct{} 1247 wcharSize uintptr 1248 1249 isMain bool 1250 pass1 bool 1251 pauseCodegen bool 1252 } 1253 1254 func newProject(t *Task) (*project, error) { 1255 voidType := t.cfg.ABI.Type(cc.Void) 1256 ptrType := t.cfg.ABI.Ptr(nil, voidType) 1257 intType := t.cfg.ABI.Type(cc.Int) 1258 if intType.Size() != 4 { // We're assuming wchar_t is int32. 1259 return nil, fmt.Errorf("unsupported C int size: %d", intType.Size()) 1260 } 1261 1262 if n := t.cfg.ABI.Types[cc.UChar].Size; n != 1 { 1263 return nil, fmt.Errorf("unsupported C unsigned char size: %d", n) 1264 } 1265 1266 if n := t.cfg.ABI.Types[cc.UShort].Size; n != 2 { 1267 return nil, fmt.Errorf("unsupported C unsigned short size: %d", n) 1268 } 1269 1270 if n := t.cfg.ABI.Types[cc.UInt].Size; n != 4 { 1271 return nil, fmt.Errorf("unsupported C unsigned int size: %d", n) 1272 } 1273 1274 if n := t.cfg.ABI.Types[cc.ULongLong].Size; n != 8 { 1275 return nil, fmt.Errorf("unsupported C unsigned long long size: %d", n) 1276 } 1277 1278 p := &project{ 1279 defines: map[cc.StringID]define{}, 1280 emitedEnums: map[cc.StringID]struct{}{}, 1281 enumConsts: map[cc.StringID]string{}, 1282 enumSpecs: map[*cc.EnumSpecifier]*enumSpec{}, 1283 externs: map[cc.StringID]*tld{}, 1284 imports: map[string]*imported{}, 1285 intType: intType, 1286 ptrSize: t.cfg.ABI.Types[cc.Ptr].Size, 1287 ptrType: ptrType, 1288 scope: newScope(), 1289 sharedFns: t.cfg.SharedFunctionDefinitions.M, 1290 sharedFnsEmitted: map[*cc.FunctionDefinition]struct{}{}, 1291 symtab: map[string]interface{}{}, 1292 task: t, 1293 tlds: map[*cc.Declarator]*tld{}, 1294 tsWOffs: map[cc.StringID]uintptr{}, 1295 tsOffs: map[cc.StringID]uintptr{}, 1296 typedefTypes: map[cc.StringID]*typedef{}, 1297 typedefsEmited: map[string]struct{}{}, 1298 verifyStructs: map[string]cc.Type{}, 1299 wanted: map[*cc.Declarator]struct{}{}, 1300 wcharSize: t.asts[0].WideCharType.Size(), 1301 } 1302 p.tldScope = p.scope 1303 p.scope.take(idCAPI) 1304 for _, v := range t.imported { 1305 var err error 1306 if v.name, v.exports, err = t.capi(v.path); err != nil { 1307 return nil, err 1308 } 1309 1310 v.qualifier = p.scope.take(cc.String(v.name)) + "." 1311 for k := range v.exports { 1312 if p.imports[k] == nil { 1313 p.imports[k] = v 1314 } 1315 } 1316 } 1317 p.tsNameP = p.scope.take(idTs) 1318 p.tsName = p.scope.take(idTs) 1319 p.tsWNameP = p.scope.take(idWtext) 1320 p.tsWName = p.scope.take(idWtext) 1321 if err := p.layout(); err != nil { 1322 return nil, err 1323 } 1324 1325 return p, nil 1326 } 1327 1328 func (p *project) newScope() scope { 1329 s := newScope() 1330 var a []cc.StringID 1331 for k := range p.structs { 1332 a = append(a, k) 1333 } 1334 sort.Slice(a, func(i, j int) bool { return a[i].String() < a[j].String() }) 1335 for _, k := range a { 1336 s.take(cc.String(p.structs[k].name)) 1337 } 1338 return s 1339 } 1340 1341 func (p *project) err(n cc.Node, s string, args ...interface{}) { 1342 if p.task.errTrace || strings.Contains(s, "internal error") { 1343 s = s + "(" + origin(2) + ")" 1344 } 1345 if p.task.traceTranslationUnits { 1346 trc("%v: error: %s (%v)", pos(n), fmt.Sprintf(s, args...), origin(2)) 1347 } 1348 if !p.task.allErrors && len(p.errors) >= 10 { 1349 return 1350 } 1351 1352 switch { 1353 case n == nil: 1354 p.errors.Add(token.Position{}, fmt.Sprintf(s, args...)) 1355 default: 1356 p.errors.Add(token.Position(n.Position()), fmt.Sprintf(s, args...)) 1357 if !p.task.allErrors && len(p.errors) == 10 { 1358 p.errors.Add(token.Position(n.Position()), tooManyErrors) 1359 } 1360 } 1361 } 1362 1363 func (p *project) o(s string, args ...interface{}) { 1364 if oTraceG { 1365 fmt.Printf(s, args...) 1366 } 1367 fmt.Fprintf(p.task.out, s, args...) 1368 } 1369 1370 func (p *project) w(s string, args ...interface{}) { 1371 if p.pass1 || p.pauseCodegen { 1372 return 1373 } 1374 1375 if coverExperiment { 1376 pc, _, _, ok := runtime.Caller(1) 1377 if ok { 1378 coverMap[pc] = struct{}{} 1379 } 1380 } 1381 if oTraceW { 1382 fmt.Printf(s, args...) 1383 } 1384 //fmt.Fprintf(&p.buf, "/* %s */", origin(2)) //TODO- 1385 fmt.Fprintf(&p.buf, s, args...) 1386 } 1387 1388 func (p *project) layout() error { 1389 if err := p.layoutTLDs(); err != nil { 1390 return err 1391 } 1392 1393 if err := p.layoutSymtab(); err != nil { 1394 return err 1395 } 1396 1397 if err := p.layoutStructs(); err != nil { 1398 return err 1399 } 1400 1401 if err := p.layoutEnums(); err != nil { 1402 return err 1403 } 1404 1405 if err := p.layoutDefines(); err != nil { 1406 return err 1407 } 1408 1409 return p.layoutStaticLocals() 1410 } 1411 1412 func (p *project) layoutSymtab() error { 1413 var t0 time.Time 1414 if p.task.traceTranslationUnits { 1415 fmt.Printf("processing symbol table ... ") 1416 t0 = time.Now() 1417 defer func() { fmt.Println(time.Since(t0)) }() 1418 } 1419 1420 for _, i := range p.task.symSearchOrder { 1421 switch { 1422 case i < 0: 1423 imported := p.task.imported[-i-1] 1424 for nm := range imported.exports { 1425 if _, ok := p.symtab[nm]; !ok { 1426 p.symtab[nm] = imported 1427 } 1428 } 1429 default: 1430 ast := p.task.asts[i] 1431 for d := range ast.TLD { 1432 if d.IsFunctionPrototype() || d.Linkage != cc.External { 1433 continue 1434 } 1435 1436 nm := d.Name() 1437 name := nm.String() 1438 if _, ok := p.symtab[name]; !ok { 1439 tld := p.externs[nm] 1440 if tld == nil { 1441 if d.Type().Kind() != cc.Function && !p.task.header { 1442 p.err(d, "back-end: undefined: %s %v %v", d.Name(), d.Type(), d.Type().Kind()) 1443 } 1444 continue 1445 } 1446 1447 p.symtab[name] = tld 1448 } 1449 } 1450 } 1451 } 1452 return nil 1453 } 1454 1455 func (p *project) layoutDefines() error { 1456 if !p.task.exportDefinesValid { 1457 return nil 1458 } 1459 1460 var t0 time.Time 1461 if p.task.traceTranslationUnits { 1462 fmt.Printf("processing #defines ... ") 1463 t0 = time.Now() 1464 defer func() { fmt.Println(time.Since(t0)) }() 1465 } 1466 1467 var prefix = p.task.exportDefines 1468 taken := map[cc.StringID]struct{}{} 1469 for _, ast := range p.task.asts { 1470 var a []cc.StringID 1471 for nm, m := range ast.Macros { 1472 if m.IsFnLike() { 1473 continue 1474 } 1475 1476 if strings.HasPrefix(nm.String(), "__") { 1477 continue 1478 } 1479 1480 if _, ok := taken[nm]; ok { 1481 continue 1482 } 1483 1484 taken[nm] = struct{}{} 1485 a = append(a, nm) 1486 } 1487 sort.Slice(a, func(i, j int) bool { return a[i].String() < a[j].String() }) 1488 for _, nm := range a { 1489 m := ast.Macros[nm] 1490 val, src := evalMacro(m, ast) 1491 if src == "" { 1492 continue 1493 } 1494 1495 name := nm.String() 1496 switch { 1497 case prefix == "": 1498 name = capitalize(name) 1499 default: 1500 name = prefix + name 1501 } 1502 name = p.scope.take(cc.String(name)) 1503 p.defines[nm] = define{name, val} 1504 p.defineLines = append(p.defineLines, fmt.Sprintf("%s = %s // %v:", name, src, p.pos(m))) 1505 } 1506 } 1507 return nil 1508 } 1509 1510 func evalMacro(m *cc.Macro, ast *cc.AST) (cc.Value, string) { 1511 toks := m.ReplacementTokens() 1512 if len(toks) != 1 { 1513 return evalMacro2(m, ast) 1514 } 1515 1516 src := strings.TrimSpace(toks[0].Src.String()) 1517 if len(src) == 0 { 1518 return nil, "" 1519 } 1520 1521 neg := "" 1522 switch src[0] { 1523 case '"': 1524 if _, err := strconv.Unquote(src); err == nil { 1525 return cc.StringValue(cc.String(src)), src 1526 } 1527 case '-': 1528 neg = "-" 1529 src = src[1:] 1530 fallthrough 1531 default: 1532 src = strings.TrimRight(src, "lLuU") 1533 if u64, err := strconv.ParseUint(src, 0, 64); err == nil { 1534 switch { 1535 case neg == "": 1536 return cc.Uint64Value(u64), src 1537 default: 1538 return cc.Int64Value(-u64), neg + src 1539 } 1540 } 1541 1542 src = strings.TrimRight(src, "fF") 1543 if f64, err := strconv.ParseFloat(src, 64); err == nil { 1544 return cc.Float64Value(f64), neg + src 1545 } 1546 } 1547 1548 return evalMacro2(m, ast) 1549 } 1550 1551 func evalMacro2(m *cc.Macro, ast *cc.AST) (cc.Value, string) { 1552 op, err := ast.Eval(m) 1553 if err != nil { 1554 return nil, "" 1555 } 1556 1557 switch x := op.Value().(type) { 1558 case cc.Int64Value: 1559 return op.Value(), fmt.Sprintf("%d", int64(x)) 1560 case cc.Uint64Value: 1561 return op.Value(), fmt.Sprintf("%d", uint64(x)) 1562 default: 1563 panic(todo("", pos(m))) 1564 } 1565 } 1566 1567 func (p *project) layoutEnums() error { 1568 var t0 time.Time 1569 if p.task.traceTranslationUnits { 1570 fmt.Printf("processing enum values ... ") 1571 t0 = time.Now() 1572 defer func() { fmt.Println(time.Since(t0)) }() 1573 } 1574 1575 export := doNotChange 1576 if p.task.exportEnumsValid { 1577 switch { 1578 case p.task.exportEnums != "": 1579 export = exportPrefix 1580 default: 1581 export = exportCapitalize 1582 } 1583 } else if p.task.defaultUnExport { 1584 export = doNotExport 1585 } 1586 1587 var enumList []*cc.EnumSpecifier 1588 for _, v := range p.task.asts { 1589 for list := v.TranslationUnit; list != nil; list = list.TranslationUnit { 1590 decl := list.ExternalDeclaration 1591 switch decl.Case { 1592 case cc.ExternalDeclarationDecl: // Declaration 1593 // ok 1594 default: 1595 continue 1596 } 1597 1598 cc.Inspect(decl.Declaration.DeclarationSpecifiers, func(n cc.Node, entry bool) bool { 1599 if !entry { 1600 return true 1601 } 1602 1603 x, ok := n.(*cc.EnumSpecifier) 1604 if !ok || x.Case != cc.EnumSpecifierDef { 1605 return true 1606 } 1607 1608 if _, ok := p.enumSpecs[x]; !ok { 1609 enumList = append(enumList, x) 1610 p.enumSpecs[x] = &enumSpec{decl: decl.Declaration, spec: x} 1611 } 1612 return true 1613 }) 1614 } 1615 } 1616 1617 vals := map[cc.StringID]interface{}{} 1618 for _, v := range enumList { 1619 for list := v.EnumeratorList; list != nil; list = list.EnumeratorList { 1620 en := list.Enumerator 1621 nm := en.Token.Value 1622 var val int64 1623 switch x := en.Operand.Value().(type) { 1624 case cc.Int64Value: 1625 val = int64(x) 1626 case cc.Uint64Value: 1627 val = int64(x) 1628 default: 1629 panic(todo("")) 1630 } 1631 switch ex, ok := vals[nm]; { 1632 case ok: 1633 switch { 1634 case ex == nil: // 1635 continue 1636 case ex == val: // same name and same value 1637 continue 1638 default: // same name, different value 1639 vals[nm] = nil 1640 } 1641 default: 1642 vals[nm] = val 1643 } 1644 p.enumConsts[nm] = "" 1645 } 1646 } 1647 var a []cc.StringID 1648 for nm := range p.enumConsts { 1649 if val, ok := vals[nm]; ok && val == nil { 1650 delete(p.enumConsts, nm) 1651 continue 1652 } 1653 1654 a = append(a, nm) 1655 } 1656 sort.Slice(a, func(i, j int) bool { return a[i].String() < a[j].String() }) 1657 for _, nm := range a { 1658 name := nm.String() 1659 switch export { 1660 case doNotExport: 1661 name = unCapitalize(name) 1662 case doNotChange: 1663 // nop 1664 case exportCapitalize: 1665 name = capitalize(name) 1666 case exportPrefix: 1667 name = p.task.exportEnums + name 1668 } 1669 name = p.scope.take(cc.String(name)) 1670 p.enumConsts[nm] = name 1671 } 1672 return nil 1673 } 1674 1675 func (p *project) layoutStaticLocals() error { 1676 var t0 time.Time 1677 if p.task.traceTranslationUnits { 1678 fmt.Printf("processing static local declarations ... ") 1679 t0 = time.Now() 1680 defer func() { fmt.Println(time.Since(t0)) }() 1681 } 1682 for _, v := range p.task.asts { 1683 for list := v.TranslationUnit; list != nil; list = list.TranslationUnit { 1684 decl := list.ExternalDeclaration 1685 switch decl.Case { 1686 case cc.ExternalDeclarationFuncDef: // FunctionDefinition 1687 // ok 1688 default: 1689 continue 1690 } 1691 1692 cc.Inspect(decl.FunctionDefinition.CompoundStatement, func(n cc.Node, entry bool) bool { 1693 switch x := n.(type) { 1694 case *cc.Declarator: 1695 if !entry || !x.IsStatic() || x.Read == 0 || x.IsParameter { 1696 break 1697 } 1698 1699 nm := x.Name() 1700 if s := p.task.staticLocalsPrefix; s != "" { 1701 nm = cc.String(s + nm.String()) 1702 } 1703 p.tlds[x] = &tld{name: p.scope.take(nm)} 1704 } 1705 return true 1706 }) 1707 } 1708 } 1709 return nil 1710 } 1711 1712 func (p *project) layoutStructs() error { 1713 var t0 time.Time 1714 if p.task.traceTranslationUnits { 1715 fmt.Printf("processing struct/union types ... ") 1716 t0 = time.Now() 1717 defer func() { fmt.Println(time.Since(t0)) }() 1718 } 1719 1720 export := doNotChange 1721 if p.task.exportStructsValid { 1722 switch { 1723 case p.task.exportStructs != "": 1724 export = exportPrefix 1725 default: 1726 export = exportCapitalize 1727 } 1728 } else if p.task.defaultUnExport { 1729 export = doNotExport 1730 } 1731 1732 m := map[cc.StringID]*taggedStruct{} 1733 var tags []cc.StringID 1734 for _, v := range p.task.asts { 1735 cc.Inspect(v.TranslationUnit, func(n cc.Node, entry bool) bool { 1736 if entry { 1737 switch x := n.(type) { 1738 case *cc.Declarator: 1739 if nm := x.Name().String(); strings.HasPrefix(nm, "_") { 1740 break 1741 } 1742 1743 p.captureStructTags(x, x.Type(), m, &tags) 1744 case *cc.Declaration: 1745 cc.Inspect(x.DeclarationSpecifiers, func(nn cc.Node, entry bool) bool { 1746 switch y := nn.(type) { 1747 case *cc.StructOrUnionSpecifier: 1748 if tag := y.Token.Value; tag != 0 { 1749 p.captureStructTags(y, y.Type(), m, &tags) 1750 } 1751 } 1752 return true 1753 }) 1754 } 1755 } 1756 return true 1757 }) 1758 } 1759 sort.Slice(tags, func(i, j int) bool { return tags[i].String() < tags[j].String() }) 1760 for _, k := range tags { 1761 v := m[k] 1762 //TODO rename conflicts 1763 if v.conflicts { 1764 delete(m, k) 1765 continue 1766 } 1767 1768 name := k.String() 1769 switch export { 1770 case doNotExport: 1771 name = unCapitalize(name) 1772 case doNotChange: 1773 // nop 1774 case exportCapitalize: 1775 name = capitalize(name) 1776 case exportPrefix: 1777 name = p.task.exportStructs + name 1778 } 1779 v.name = p.scope.take(cc.String(name)) 1780 } 1781 for _, k := range tags { 1782 v := m[k] 1783 if v != nil { 1784 v.gotyp = p.structType(nil, v.ctyp) 1785 } 1786 } 1787 p.structs = m 1788 return nil 1789 } 1790 1791 func (p *project) captureStructTags(n cc.Node, t cc.Type, m map[cc.StringID]*taggedStruct, tags *[]cc.StringID) { 1792 if t == nil { 1793 return 1794 } 1795 1796 t = t.Alias() 1797 for t.Kind() == cc.Ptr { 1798 t = t.Alias().Elem().Alias() 1799 } 1800 if t.Kind() == cc.Invalid || t.IsIncomplete() { 1801 return 1802 } 1803 1804 switch t.Kind() { 1805 case cc.Struct, cc.Union: 1806 tag := t.Tag() 1807 if tag == 0 { 1808 return 1809 } 1810 1811 ex := m[tag] 1812 if ex != nil { 1813 ts := p.typeSignature(n, t) 1814 exs := p.typeSignature(n, ex.ctyp) 1815 if ts != exs { 1816 ex.conflicts = true 1817 } 1818 return 1819 } 1820 1821 nf := t.NumField() 1822 m[tag] = &taggedStruct{ctyp: t, node: n} 1823 for idx := []int{0}; idx[0] < nf; idx[0]++ { 1824 p.captureStructTags(n, t.FieldByIndex(idx).Type(), m, tags) 1825 } 1826 *tags = append(*tags, tag) 1827 case cc.Array: 1828 p.captureStructTags(n, t.Elem(), m, tags) 1829 } 1830 } 1831 1832 func (p *project) typeSignature(n cc.Node, t cc.Type) (r uint64) { 1833 p.typeSigHash.Reset() 1834 p.typeSignature2(n, &p.typeSigHash, t) 1835 return p.typeSigHash.Sum64() 1836 } 1837 1838 func (p *project) typeSignature2(n cc.Node, b *maphash.Hash, t cc.Type) { 1839 t = t.Alias() 1840 if t.IsIntegerType() { 1841 if !t.IsSignedType() { 1842 b.WriteByte('u') 1843 } 1844 fmt.Fprintf(b, "int%d", t.Size()*8) 1845 return 1846 } 1847 1848 if t.IsArithmeticType() { 1849 b.WriteString(t.Kind().String()) 1850 return 1851 } 1852 1853 structOrUnion := "struct" 1854 switch t.Kind() { 1855 case cc.Ptr: 1856 fmt.Fprintf(b, "*%s", t.Elem()) 1857 case cc.Array: 1858 if t.IsVLA() { 1859 // trc("VLA") 1860 p.err(n, "variable length arrays not supported: %v", t) 1861 } 1862 1863 fmt.Fprintf(b, "[%d]%s", t.Len(), t.Elem()) 1864 case cc.Vector: 1865 fmt.Fprintf(b, "[%d]%s", t.Len(), t.Elem()) 1866 case cc.Union: 1867 structOrUnion = "union" 1868 fallthrough 1869 case cc.Struct: 1870 b.WriteString(structOrUnion) 1871 nf := t.NumField() 1872 fmt.Fprintf(b, " %d{", nf) 1873 b.WriteByte('{') 1874 for idx := []int{0}; idx[0] < nf; idx[0]++ { 1875 f := t.FieldByIndex(idx) 1876 fmt.Fprintf(b, "%s:%d:%d:%v:%d:%d:", 1877 f.Name(), f.BitFieldOffset(), f.BitFieldWidth(), f.IsBitField(), f.Offset(), f.Padding(), 1878 ) 1879 p.typeSignature2(f.Declarator(), b, f.Type()) 1880 b.WriteByte(';') 1881 } 1882 b.WriteByte('}') 1883 case cc.Void: 1884 b.WriteString("void") 1885 case cc.Invalid: 1886 b.WriteString("invalid") //TODO fix cc/v3 1887 default: 1888 panic(todo("", p.pos(n), t, t.Kind())) 1889 } 1890 } 1891 1892 func (p *project) structType(n cc.Node, t cc.Type) string { 1893 switch t.Kind() { 1894 case cc.Struct, cc.Union: 1895 tag := t.Tag() 1896 if tag != 0 && p.structs != nil { 1897 s := p.structs[tag] 1898 if s == nil { 1899 return p.structLiteral(n, t) 1900 } 1901 1902 if s.gotyp == "" { 1903 s.gotyp = p.structLiteral(n, t) 1904 } 1905 return s.gotyp 1906 } 1907 1908 return p.structLiteral(n, t) 1909 default: 1910 panic(todo("internal error: %v", t.Kind())) 1911 } 1912 } 1913 1914 func (p *project) padName(n *int) string { 1915 if !p.task.exportFieldsValid { 1916 return "_" 1917 } 1918 1919 *n++ 1920 return fmt.Sprintf("%s__ccgo_pad%d", p.task.exportFields, *n) 1921 } 1922 1923 func (p *project) structLiteral(n cc.Node, t cc.Type) string { 1924 var npad int 1925 b := bytesBufferPool.Get().(*bytes.Buffer) 1926 defer func() { b.Reset(); bytesBufferPool.Put(b) }() 1927 switch t.Kind() { 1928 case cc.Struct: 1929 info := cc.NewStructLayout(t) 1930 // trc("%v: %q\n%s", p.pos(n), t.Tag(), info) 1931 b.WriteString("struct {") 1932 if info.NeedExplicitAlign { 1933 fmt.Fprintf(b, "%s [0]uint%d;", p.padName(&npad), 8*p.align(n, t)) 1934 } 1935 var max uintptr 1936 for _, off := range info.Offsets { 1937 flds := info.OffsetToFields[off] 1938 if off < max { 1939 var a []string 1940 var nmf cc.Field 1941 for _, f := range flds { 1942 if f.Name() != 0 && nmf == nil { 1943 nmf = f 1944 } 1945 if !f.IsBitField() { 1946 panic(todo("internal error %q, off %v max %v\n%s", f.Name(), off, max, info)) 1947 } 1948 a = append(a, fmt.Sprintf("%s %s: %d", f.Type(), f.Name(), f.BitFieldWidth())) 1949 } 1950 fmt.Fprintf(b, "/* %s */", strings.Join(a, ", ")) 1951 continue 1952 } 1953 1954 f := flds[0] 1955 switch pad := info.PaddingsBefore[f]; { 1956 case pad < 0: 1957 continue 1958 case pad > 0: 1959 fmt.Fprintf(b, "%s [%d]byte;", p.padName(&npad), pad) 1960 } 1961 switch { 1962 case f.IsBitField(): 1963 max += uintptr(f.BitFieldBlockWidth()) >> 3 1964 var a []string 1965 var nmf cc.Field 1966 for _, f := range flds { 1967 if f.Name() != 0 && nmf == nil { 1968 nmf = f 1969 } 1970 if !f.IsBitField() { 1971 panic(todo("internal error %q\n%s", f.Name(), info)) 1972 } 1973 a = append(a, fmt.Sprintf("%s %s: %d", f.Type(), f.Name(), f.BitFieldWidth())) 1974 } 1975 if nmf == nil { 1976 nmf = f 1977 } 1978 fmt.Fprintf(b, "%s uint%d /* %s */;", p.bitFieldName(n, nmf), f.BitFieldBlockWidth(), strings.Join(a, ", ")) 1979 default: 1980 ft := f.Type() 1981 if ft.Kind() == cc.Array && ft.IsIncomplete() || ft.Size() == 0 { 1982 break 1983 } 1984 1985 max += ft.Size() 1986 fmt.Fprintf(b, "%s %s;", p.fieldName2(n, f), p.typ(n, ft)) 1987 } 1988 } 1989 if info.PaddingAfter != 0 { 1990 fmt.Fprintf(b, "%s [%d]byte;", p.padName(&npad), info.PaddingAfter) 1991 } 1992 b.WriteByte('}') 1993 case cc.Union: 1994 b.WriteString("struct {") 1995 info := cc.NewStructLayout(t) 1996 if info.NeedExplicitAlign { 1997 fmt.Fprintf(b, "%s [0]uint%d;", p.padName(&npad), 8*p.align(n, t)) 1998 } 1999 al := uintptr(t.Align()) 2000 sz := t.Size() 2001 if al > sz { 2002 panic(todo("", p.pos(n))) 2003 } 2004 2005 f := t.FieldByIndex([]int{0}) 2006 ft := f.Type() 2007 al0 := ft.Align() 2008 if f.IsBitField() { 2009 al0 = f.BitFieldBlockWidth() >> 3 2010 } 2011 if al != uintptr(al0) { 2012 fmt.Fprintf(b, "%s [0]uint%d;", p.padName(&npad), 8*al) 2013 } 2014 fsz := ft.Size() 2015 switch { 2016 case f.IsBitField(): 2017 fmt.Fprintf(b, "%s ", p.fieldName2(n, f)) 2018 fmt.Fprintf(b, "uint%d;", f.BitFieldBlockWidth()) 2019 fsz = uintptr(f.BitFieldBlockWidth()) >> 3 2020 default: 2021 fmt.Fprintf(b, "%s %s;", p.fieldName2(n, f), p.typ(n, ft)) 2022 } 2023 if pad := sz - fsz; pad != 0 { 2024 fmt.Fprintf(b, "%s [%d]byte;", p.padName(&npad), pad) 2025 } 2026 b.WriteByte('}') 2027 default: 2028 panic(todo("internal error: %v", t.Kind())) 2029 } 2030 r := b.String() 2031 if p.task.verifyStructs { 2032 if _, ok := p.verifyStructs[r]; !ok { 2033 p.verifyStructs[r] = t 2034 } 2035 } 2036 return r 2037 } 2038 2039 func (p *project) align(nd cc.Node, t cc.Type) int { 2040 switch n := t.Align(); { 2041 case n <= 1: 2042 return 1 2043 case n <= 2: 2044 return 2 2045 case n <= 4: 2046 return 4 2047 case n <= 8: 2048 return 8 2049 default: 2050 if !p.task.ignoreUnsupportedAligment { 2051 p.err(nd, "unsupported alignment of type %s: %v", t, n) 2052 } 2053 return 8 2054 } 2055 } 2056 2057 func (p *project) bitFieldName(n cc.Node, f cc.Field) string { 2058 if id := f.Name(); id != 0 { 2059 return p.fieldName(n, id) 2060 } 2061 2062 return fmt.Sprintf("__%d", f.Offset()) 2063 } 2064 2065 func (p *project) fieldName2(n cc.Node, f cc.Field) string { 2066 if f.Name() != 0 { 2067 return p.fieldName(n, f.Name()) 2068 } 2069 2070 return p.fieldName(n, cc.String(fmt.Sprintf("__%d", f.Offset()))) 2071 } 2072 2073 func (p *project) fieldName(n cc.Node, id cc.StringID) string { 2074 if id == 0 { 2075 panic(todo("", p.pos(n))) 2076 } 2077 2078 if !p.task.exportFieldsValid { 2079 s := id.String() 2080 if p.task.defaultUnExport { 2081 s = unCapitalize(s) 2082 } 2083 2084 if !reservedNames[s] { 2085 return s 2086 } 2087 2088 return "__" + s 2089 } 2090 2091 if s := p.task.exportFields; s != "" { 2092 return s + id.String() 2093 } 2094 2095 return capitalize(id.String()) 2096 } 2097 2098 func (p *project) dtyp(d *cc.Declarator) (r string) { 2099 t := d.Type() 2100 if t.IsIncomplete() { 2101 if t.Kind() == cc.Array && d.IsParameter { 2102 return "uintptr" 2103 } 2104 2105 panic(todo("")) 2106 } 2107 2108 return p.typ(d, t) 2109 } 2110 2111 func (p *project) typ(nd cc.Node, t cc.Type) (r string) { 2112 if t.IsIncomplete() { 2113 panic(todo("", p.pos(nd), t)) 2114 } 2115 2116 if t.IsAliasType() && !t.IsScalarType() { 2117 if tld := p.tlds[t.AliasDeclarator()]; tld != nil { 2118 return tld.name 2119 } 2120 } 2121 2122 b := bytesBufferPool.Get().(*bytes.Buffer) 2123 defer func() { b.Reset(); bytesBufferPool.Put(b) }() 2124 if t.IsIntegerType() { 2125 switch t.Kind() { 2126 case cc.Int128: 2127 fmt.Fprintf(b, "%sInt128", p.task.crt) 2128 return b.String() 2129 case cc.UInt128: 2130 fmt.Fprintf(b, "%sUint128", p.task.crt) 2131 return b.String() 2132 } 2133 2134 if !t.IsSignedType() { 2135 b.WriteByte('u') 2136 } 2137 if t.Size() > 8 { 2138 p.err(nd, "unsupported C type: %v", t) 2139 } 2140 fmt.Fprintf(b, "int%d", 8*t.Size()) 2141 return b.String() 2142 } 2143 2144 switch t.Kind() { 2145 case cc.Ptr, cc.Function: 2146 return "uintptr" 2147 case cc.Double: 2148 return "float64" 2149 case cc.Float: 2150 return "float32" 2151 case cc.Array: 2152 n := t.Len() 2153 switch { 2154 case t.IsVLA(): 2155 fmt.Fprintf(b, "uintptr") 2156 default: 2157 fmt.Fprintf(b, "[%d]%s", n, p.typ(nd, t.Elem())) 2158 } 2159 return b.String() 2160 case cc.Vector: 2161 n := t.Len() 2162 fmt.Fprintf(b, "[%d]%s", n, p.typ(nd, t.Elem())) 2163 return b.String() 2164 case cc.Struct, cc.Union: 2165 if tag := t.Tag(); tag != 0 { 2166 if s := p.structs[tag]; s != nil { 2167 if s.name == "" { 2168 panic(todo("internal error %q", tag)) 2169 } 2170 2171 return s.name 2172 } 2173 } 2174 2175 return p.structType(nd, t) 2176 } 2177 2178 panic(todo("", p.pos(nd), t.Kind(), t)) 2179 } 2180 2181 func isScalarKind(k cc.Kind) bool { 2182 switch k { 2183 case 2184 cc.Char, cc.SChar, cc.UChar, 2185 cc.Short, cc.UShort, 2186 cc.Int, cc.UInt, 2187 cc.Long, cc.ULong, 2188 cc.LongLong, cc.ULongLong, 2189 cc.Float, cc.Double, 2190 cc.Ptr: 2191 2192 return true 2193 } 2194 2195 return false 2196 } 2197 2198 func (p *project) layoutTLDs() error { 2199 var t0 time.Time 2200 if p.task.traceTranslationUnits { 2201 fmt.Printf("processing file scope declarations ... ") 2202 t0 = time.Now() 2203 defer func() { fmt.Println(time.Since(t0)) }() 2204 } 2205 2206 exportExtern, exportTypedef := doNotChange, doNotChange 2207 if p.task.exportExternsValid { 2208 switch { 2209 case p.task.exportExterns != "": 2210 exportExtern = exportPrefix 2211 default: 2212 exportExtern = exportCapitalize 2213 } 2214 } else if p.task.defaultUnExport { 2215 exportExtern = doNotExport 2216 } 2217 2218 if p.task.exportTypedefsValid { 2219 switch { 2220 case p.task.exportTypedefs != "": 2221 exportTypedef = exportPrefix 2222 default: 2223 exportTypedef = exportCapitalize 2224 } 2225 } else if p.task.defaultUnExport { 2226 exportTypedef = doNotExport 2227 } 2228 2229 var a []*cc.Declarator 2230 if p.task.pkgName == "" || p.task.pkgName == "main" { 2231 out: 2232 for _, ast := range p.task.asts { 2233 if a := ast.Scope[idMain]; len(a) != 0 { 2234 switch x := a[0].(type) { 2235 case *cc.Declarator: 2236 if x.Linkage == cc.External { 2237 p.isMain = true 2238 p.scope.take(idMain) 2239 break out 2240 } 2241 } 2242 } 2243 } 2244 } 2245 sharedFns := map[*cc.FunctionDefinition]struct{}{} 2246 for _, ast := range p.task.asts { 2247 a = a[:0] 2248 for d := range ast.TLD { 2249 if d.IsFunctionPrototype() { 2250 continue 2251 } 2252 2253 // https://gcc.gnu.org/onlinedocs/gcc/Inline.html 2254 // 2255 // If you specify both inline and extern in the function definition, then the 2256 // definition is used only for inlining. In no case is the function compiled on 2257 // its own, not even if you refer to its address explicitly. Such an address 2258 // becomes an external reference, as if you had only declared the function, and 2259 // had not defined it. 2260 // 2261 // This combination of inline and extern has almost the effect of a macro. The 2262 // way to use it is to put a function definition in a header file with these 2263 // keywords, and put another copy of the definition (lacking inline and extern) 2264 // in a library file. The definition in the header file causes most calls to 2265 // the function to be inlined. If any uses of the function remain, they refer 2266 // to the single copy in the library. 2267 if d.IsExtern() && d.Type().Inline() { 2268 continue 2269 } 2270 2271 if fn := d.FunctionDefinition(); fn != nil { 2272 if _, ok := p.sharedFns[fn]; ok { 2273 if _, ok := sharedFns[fn]; ok { 2274 continue 2275 } 2276 2277 sharedFns[fn] = struct{}{} 2278 } 2279 } 2280 2281 a = append(a, d) 2282 p.wanted[d] = struct{}{} 2283 } 2284 sort.Slice(a, func(i, j int) bool { 2285 return a[i].NameTok().Seq() < a[j].NameTok().Seq() 2286 }) 2287 for _, d := range a { 2288 switch d.Type().Kind() { 2289 case cc.Struct, cc.Union: 2290 p.checkAttributes(d.Type()) 2291 } 2292 nm := d.Name() 2293 name := nm.String() 2294 2295 switch d.Linkage { 2296 case cc.External: 2297 if ex := p.externs[nm]; ex != nil { 2298 if _, ok := p.task.hide[name]; ok { 2299 break 2300 } 2301 2302 if d.Type().Kind() != cc.Function { 2303 break 2304 } 2305 2306 p.err(d, "redeclared: %s", d.Name()) 2307 break 2308 } 2309 2310 isMain := p.isMain && nm == idMain 2311 switch exportExtern { 2312 case doNotExport: 2313 name = unCapitalize(name) 2314 case doNotChange: 2315 // nop 2316 case exportCapitalize: 2317 name = capitalize(name) 2318 case exportPrefix: 2319 name = p.task.exportExterns + name 2320 } 2321 name = p.scope.take(cc.String(name)) 2322 if isMain { 2323 p.mainName = name 2324 d.Read++ 2325 } 2326 tld := &tld{name: name} 2327 p.externs[nm] = tld 2328 for _, v := range ast.Scope[nm] { 2329 if d, ok := v.(*cc.Declarator); ok { 2330 p.tlds[d] = tld 2331 } 2332 } 2333 if !isMain { 2334 p.capi = append(p.capi, d.Name().String()) 2335 } 2336 case cc.Internal: 2337 if token.IsExported(name) && !p.isMain && p.task.exportExternsValid { 2338 name = "s" + name 2339 } 2340 tld := &tld{name: p.scope.take(cc.String(name))} 2341 for _, v := range ast.Scope[nm] { 2342 if d, ok := v.(*cc.Declarator); ok { 2343 p.tlds[d] = tld 2344 } 2345 } 2346 case cc.None: 2347 if d.IsTypedefName { 2348 if d.Type().IsIncomplete() { 2349 break 2350 } 2351 2352 if exportTypedef == doNotChange && strings.HasPrefix(name, "__") { 2353 break 2354 } 2355 2356 ex, ok := p.typedefTypes[d.Name()] 2357 if ok { 2358 sig := p.typeSignature(d, d.Type()) 2359 if ex.sig == sig { 2360 tld := ex.tld 2361 for _, v := range ast.Scope[nm] { 2362 if d, ok := v.(*cc.Declarator); ok { 2363 p.tlds[d] = tld 2364 } 2365 } 2366 break 2367 } 2368 } 2369 2370 switch exportTypedef { 2371 case doNotExport: 2372 name = unCapitalize(name) 2373 case doNotChange: 2374 // nop 2375 case exportCapitalize: 2376 name = capitalize(name) 2377 case exportPrefix: 2378 name = p.task.exportTypedefs + name 2379 } 2380 2381 tld := &tld{name: p.scope.take(cc.String(name))} 2382 p.typedefTypes[d.Name()] = &typedef{p.typeSignature(d, d.Type()), tld} 2383 for _, v := range ast.Scope[nm] { 2384 if d, ok := v.(*cc.Declarator); ok { 2385 p.tlds[d] = tld 2386 } 2387 } 2388 } 2389 default: 2390 panic(todo("", p.pos(d), nm, d.Linkage)) 2391 } 2392 } 2393 } 2394 for _, ast := range p.task.asts { 2395 for list := ast.TranslationUnit; list != nil; list = list.TranslationUnit { 2396 decl := list.ExternalDeclaration 2397 switch decl.Case { 2398 case cc.ExternalDeclarationFuncDef: // FunctionDefinition 2399 // ok 2400 default: 2401 continue 2402 } 2403 2404 cc.Inspect(decl.FunctionDefinition.CompoundStatement, func(n cc.Node, entry bool) bool { 2405 switch x := n.(type) { 2406 case *cc.Declarator: 2407 if x.IsFunctionPrototype() { 2408 nm := x.Name() 2409 if extern := p.externs[nm]; extern != nil { 2410 break 2411 } 2412 2413 tld := &tld{name: nm.String()} 2414 for _, nd := range ast.Scope[nm] { 2415 if d, ok := nd.(*cc.Declarator); ok { 2416 p.tlds[d] = tld 2417 } 2418 } 2419 } 2420 2421 } 2422 return true 2423 }) 2424 } 2425 } 2426 return nil 2427 } 2428 2429 func (p *project) checkAttributes(t cc.Type) (r bool) { 2430 r = true 2431 for _, v := range t.Attributes() { 2432 cc.Inspect(v, func(n cc.Node, entry bool) bool { 2433 if !entry { 2434 return true 2435 } 2436 2437 switch x := n.(type) { 2438 case *cc.AttributeValue: 2439 if x.Token.Value != idAligned { 2440 break 2441 } 2442 2443 //TODO switch v := x.ExpressionList.AssignmentExpression.Operand.Value().(type) { 2444 //TODO default: 2445 //TODO panic(todo("%T(%v)", v, v)) 2446 //TODO } 2447 } 2448 return true 2449 }) 2450 } 2451 switch t.Kind() { 2452 case cc.Struct, cc.Union: 2453 for i := []int{0}; i[0] < t.NumField(); i[0]++ { 2454 f := t.FieldByIndex(i) 2455 if !p.checkAttributes(f.Type()) { 2456 return false 2457 } 2458 2459 sd := f.Declarator() 2460 if sd == nil { 2461 continue 2462 } 2463 2464 cc.Inspect(sd.StructDeclaration().SpecifierQualifierList, func(n cc.Node, entry bool) bool { 2465 if !entry { 2466 return true 2467 } 2468 2469 switch x := n.(type) { 2470 case *cc.AttributeValue: 2471 if x.Token.Value == idPacked { 2472 p.err(sd, "unsupported attribute: packed") 2473 r = false 2474 return false 2475 } 2476 2477 if x.Token.Value != idAligned { 2478 break 2479 } 2480 2481 switch v := x.ExpressionList.AssignmentExpression.Operand.Value().(type) { 2482 case cc.Int64Value: 2483 if int(v) != t.Align() { 2484 p.err(sd, "unsupported attribute: alignment") 2485 r = false 2486 return false 2487 } 2488 default: 2489 panic(todo("%T(%v)", v, v)) 2490 } 2491 } 2492 return true 2493 }) 2494 if !r { 2495 return false 2496 } 2497 } 2498 } 2499 return r 2500 } 2501 2502 func unCapitalize(s string) string { 2503 if strings.HasPrefix(s, "_") { 2504 return s 2505 } 2506 a := []rune(s) 2507 return strings.ToLower(string(a[0])) + string(a[1:]) 2508 } 2509 2510 func capitalize(s string) string { 2511 if strings.HasPrefix(s, "_") { 2512 s = "X" + s 2513 } 2514 a := []rune(s) 2515 return strings.ToUpper(string(a[0])) + string(a[1:]) 2516 } 2517 2518 func (p *project) main() error { 2519 targs := append([]string(nil), p.task.args...) 2520 for i, v := range targs { 2521 if v == "" { 2522 targs[i] = `""` 2523 } 2524 } 2525 p.o(`// Code generated by '%s %s', DO NOT EDIT. 2526 2527 package %s 2528 2529 `, 2530 filepath.Base(p.task.args[0]), 2531 strings.Join(targs[1:], " "), 2532 p.task.pkgName, 2533 ) 2534 if len(p.defineLines) != 0 { 2535 p.w("\nconst (") 2536 p.w("%s", strings.Join(p.defineLines, "\n")) 2537 p.w("\n)\n\n") 2538 } 2539 var a []*enumSpec 2540 for _, es := range p.enumSpecs { 2541 if es.spec.LexicalScope().Parent() == nil && !es.emitted { 2542 a = append(a, es) 2543 } 2544 } 2545 sort.Slice(a, func(i, j int) bool { 2546 return a[i].decl.Position().String() < a[j].decl.Position().String() 2547 }) 2548 for _, es := range a { 2549 es.emit(p) 2550 } 2551 for i, v := range p.task.asts { 2552 var t0 time.Time 2553 if p.task.traceTranslationUnits { 2554 fmt.Printf("Go back end %v/%v: %s ... ", i+1, len(p.task.asts), filepath.Base(p.task.sources[i].Name)) 2555 t0 = time.Now() 2556 } 2557 p.oneAST(v) 2558 if p.task.traceTranslationUnits { 2559 fmt.Println(time.Since(t0)) 2560 } 2561 p.task.asts[i] = nil 2562 memGuard(i, p.task.isScripted) 2563 } 2564 sort.Slice(p.task.imported, func(i, j int) bool { return p.task.imported[i].path < p.task.imported[j].path }) 2565 p.o(`import ( 2566 "math" 2567 "reflect" 2568 "sync/atomic" 2569 "unsafe" 2570 `) 2571 if len(p.verifyStructs) != 0 { 2572 p.o("\t\"fmt\"\n") 2573 } 2574 first := true 2575 libc := false 2576 for _, v := range p.task.imported { 2577 if v.used { 2578 if v.path == p.task.crtImportPath { 2579 libc = true 2580 } 2581 if first { 2582 p.o("\n") 2583 first = false 2584 } 2585 p.o("\t%q\n", v.path) 2586 } 2587 } 2588 if p.task.crtImportPath != "" { 2589 if !libc { 2590 p.o("\t%q\n", p.task.crtImportPath) 2591 } 2592 p.o("\t%q\n", p.task.crtImportPath+"/sys/types") 2593 } 2594 p.o(`) 2595 2596 var _ = math.Pi 2597 var _ reflect.Kind 2598 var _ atomic.Value 2599 var _ unsafe.Pointer 2600 `) 2601 if p.task.crtImportPath != "" { 2602 if libc { 2603 p.o("var _ *libc.TLS\n") 2604 } 2605 p.o("var _ types.Size_t\n") 2606 } 2607 if p.isMain { 2608 p.o(` 2609 func main() { %sStart(%s) }`, p.task.crt, p.mainName) 2610 } 2611 p.flushStructs() 2612 p.initPatches() 2613 p.flushTS() 2614 if !p.task.noCapi { 2615 p.flushCAPI() 2616 } 2617 p.doVerifyStructs() 2618 if err := p.Err(); err != nil { 2619 return err 2620 } 2621 2622 if _, err := p.buf.WriteTo(p.task.out); err != nil { 2623 return err 2624 } 2625 2626 return p.Err() 2627 } 2628 2629 func (p *project) doVerifyStructs() { 2630 if len(p.verifyStructs) == 0 { 2631 return 2632 } 2633 2634 var a []string 2635 for k := range p.verifyStructs { 2636 a = append(a, k) 2637 } 2638 sort.Strings(a) 2639 p.w("\n\nfunc init() {") 2640 n := 0 2641 for _, k := range a { 2642 t := p.verifyStructs[k] 2643 p.w("\nvar v%d %s", n, k) 2644 p.w("\nif g, e := unsafe.Sizeof(v%d), uintptr(%d); g != e { panic(fmt.Sprintf(`invalid struct/union size, got %%v, expected %%v`, g, e))}", n, t.Size()) 2645 nf := t.NumField() 2646 for idx := []int{0}; idx[0] < nf; idx[0]++ { 2647 f := t.FieldByIndex(idx) 2648 if f.IsFlexible() { 2649 break 2650 } 2651 2652 if f.IsBitField() || f.Type().Size() == 0 { 2653 continue 2654 } 2655 2656 nm := p.fieldName2(f.Declarator(), f) 2657 switch { 2658 case t.Kind() == cc.Union: 2659 if f.Offset() != 0 { 2660 panic(todo("")) 2661 } 2662 2663 if idx[0] != 0 { 2664 break 2665 } 2666 2667 fallthrough 2668 default: 2669 p.w("\nif g, e := unsafe.Offsetof(v%d.%s), uintptr(%d); g != e { panic(fmt.Sprintf(`invalid struct/union field offset, got %%v, expected %%v`, g, e))}", n, nm, f.Offset()) 2670 p.w("\nif g, e := unsafe.Sizeof(v%d.%s), uintptr(%d); g != e { panic(fmt.Sprintf(`invalid struct/union field size, got %%v, expected %%v`, g, e))}", n, nm, f.Type().Size()) 2671 } 2672 } 2673 n++ 2674 } 2675 p.w("\n}\n") 2676 } 2677 2678 func (p *project) flushCAPI() { 2679 if p.isMain { 2680 return 2681 } 2682 2683 b := bytes.NewBuffer(nil) 2684 fmt.Fprintf(b, `// Code generated by '%s %s', DO NOT EDIT. 2685 2686 package %s 2687 2688 `, 2689 filepath.Base(p.task.args[0]), 2690 strings.Join(p.task.args[1:], " "), 2691 p.task.pkgName, 2692 ) 2693 fmt.Fprintf(b, "\n\nvar CAPI = map[string]struct{}{") 2694 sort.Strings(p.capi) 2695 for _, nm := range p.capi { 2696 fmt.Fprintf(b, "\n%q: {},", nm) 2697 } 2698 fmt.Fprintf(b, "\n}\n") 2699 if err := ioutil.WriteFile(p.task.capif, b.Bytes(), 0644); err != nil { 2700 p.err(nil, "%v", err) 2701 return 2702 } 2703 2704 if out, err := exec.Command("gofmt", "-r", "(x) -> x", "-l", "-s", "-w", p.task.capif).CombinedOutput(); err != nil { 2705 p.err(nil, "%s: %v", out, err) 2706 } 2707 2708 if out, err := exec.Command("gofmt", "-l", "-s", "-w", p.task.capif).CombinedOutput(); err != nil { 2709 p.err(nil, "%s: %v", out, err) 2710 } 2711 } 2712 2713 func (p *project) initPatches() { 2714 var tlds []*tld 2715 for _, tld := range p.tlds { 2716 if len(tld.patches) != 0 { 2717 tlds = append(tlds, tld) 2718 } 2719 } 2720 if len(tlds) == 0 { 2721 return 2722 } 2723 2724 sort.Slice(tlds, func(i, j int) bool { return tlds[i].name < tlds[j].name }) 2725 p.w("\n\nfunc init() {") 2726 for _, tld := range tlds { 2727 for _, patch := range tld.patches { 2728 var fld string 2729 if patch.fld != nil { 2730 fld = fmt.Sprintf("/* .%s */", patch.fld.Name()) 2731 } 2732 init := patch.init 2733 expr := init.AssignmentExpression 2734 d := expr.Declarator() 2735 switch { 2736 case d != nil && d.Type().Kind() == cc.Function: 2737 p.w("\n*(*") 2738 p.functionSignature(d, nil, d.Type(), "") 2739 p.w(")(unsafe.Pointer(uintptr(unsafe.Pointer(&%s))+%d%s)) = ", tld.name, init.Offset, fld) 2740 p.declarator(init, nil, d, d.Type(), exprFunc, 0) 2741 default: 2742 p.w("\n*(*%s)(unsafe.Pointer(uintptr(unsafe.Pointer(&%s))+%d%s)) = ", p.typ(init, patch.t), tld.name, init.Offset, fld) 2743 p.assignmentExpression(nil, expr, patch.t, exprValue, 0) 2744 } 2745 p.w("// %s:", p.pos(init)) 2746 } 2747 } 2748 p.w("\n}\n") 2749 } 2750 2751 func (p *project) Err() error { 2752 if len(p.errors) == 0 { 2753 return nil 2754 } 2755 2756 var lpos token.Position 2757 w := 0 2758 for _, v := range p.errors { 2759 if lpos.Filename != "" { 2760 if v.Pos.Filename == lpos.Filename && v.Pos.Line == lpos.Line && !strings.HasPrefix(v.Msg, tooManyErrors) { 2761 continue 2762 } 2763 } 2764 2765 p.errors[w] = v 2766 w++ 2767 lpos = v.Pos 2768 } 2769 p.errors = p.errors[:w] 2770 sort.Slice(p.errors, func(i, j int) bool { 2771 a := p.errors[i] 2772 if a.Msg == tooManyErrors { 2773 return false 2774 } 2775 2776 b := p.errors[j] 2777 if b.Msg == tooManyErrors { 2778 return true 2779 } 2780 2781 if !a.Pos.IsValid() && b.Pos.IsValid() { 2782 return true 2783 } 2784 2785 if a.Pos.IsValid() && !b.Pos.IsValid() { 2786 return false 2787 } 2788 2789 if a.Pos.Filename < b.Pos.Filename { 2790 return true 2791 } 2792 2793 if a.Pos.Filename > b.Pos.Filename { 2794 return false 2795 } 2796 2797 if a.Pos.Line < b.Pos.Line { 2798 return true 2799 } 2800 2801 if a.Pos.Line > b.Pos.Line { 2802 return false 2803 } 2804 2805 return a.Pos.Column < b.Pos.Column 2806 }) 2807 a := make([]string, 0, len(p.errors)) 2808 for _, v := range p.errors { 2809 a = append(a, v.Error()) 2810 } 2811 return fmt.Errorf("%s", strings.Join(a, "\n")) 2812 } 2813 2814 func (p *project) flushTS() { 2815 b := p.ts.Bytes() 2816 if len(b) != 0 { 2817 p.w("\n\n") 2818 //TODO add cmd line option for this 2819 //TODO s := strings.TrimSpace(hex.Dump(b)) 2820 //TODO a := strings.Split(s, "\n") 2821 //TODO p.w("// %s\n", strings.Join(a, "\n// ")) 2822 p.w("var %s = %q\n", p.tsName, b) 2823 p.w("var %s = (*reflect.StringHeader)(unsafe.Pointer(&%s)).Data\n", p.tsNameP, p.tsName) 2824 } 2825 if len(p.tsW) != 0 { 2826 p.w("var %s = [...]%s{", p.tsWName, p.typ(nil, p.ast.WideCharType)) 2827 for _, v := range p.tsW { 2828 p.w("%d, ", v) 2829 } 2830 p.w("}\n") 2831 p.w("var %s = uintptr(unsafe.Pointer(&%s[0]))\n", p.tsWNameP, p.tsWName) 2832 } 2833 } 2834 2835 func (p *project) flushStructs() { 2836 var a []*taggedStruct 2837 for _, v := range p.structs { 2838 if !v.emitted { 2839 a = append(a, v) 2840 } 2841 } 2842 sort.Slice(a, func(i, j int) bool { return a[i].name < a[j].name }) 2843 for _, v := range a { 2844 v.emit(p, nil) 2845 } 2846 } 2847 2848 func (p *project) oneAST(ast *cc.AST) { 2849 p.ast = ast 2850 for list := ast.TranslationUnit; list != nil; list = list.TranslationUnit { 2851 p.externalDeclaration(list.ExternalDeclaration) 2852 } 2853 p.w("%s", tidyCommentString(ast.TrailingSeperator.String())) 2854 } 2855 2856 func (p *project) externalDeclaration(n *cc.ExternalDeclaration) { 2857 switch n.Case { 2858 case cc.ExternalDeclarationFuncDef: // FunctionDefinition 2859 p.functionDefinition(n.FunctionDefinition) 2860 case cc.ExternalDeclarationDecl: // Declaration 2861 p.declaration(nil, n.Declaration, false) 2862 case cc.ExternalDeclarationAsm: // AsmFunctionDefinition 2863 // nop 2864 case cc.ExternalDeclarationAsmStmt: // AsmStatement 2865 panic(todo("", p.pos(n))) 2866 case cc.ExternalDeclarationEmpty: // ';' 2867 // nop 2868 case cc.ExternalDeclarationPragma: // PragmaSTDC 2869 panic(todo("", p.pos(n))) 2870 default: 2871 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 2872 } 2873 } 2874 2875 func (p *project) declaration(f *function, n *cc.Declaration, topDecl bool) { 2876 cc.Inspect(n.DeclarationSpecifiers, func(m cc.Node, entry bool) bool { 2877 switch x := m.(type) { 2878 case *cc.EnumSpecifier: 2879 if f == nil { 2880 p.enumSpecs[x].emit(p) 2881 } 2882 case *cc.StructOrUnionSpecifier: 2883 if tag := x.Token.Value; tag != 0 { 2884 switch { 2885 case f == nil: 2886 p.structs[tag].emit(p, n.DeclarationSpecifiers) 2887 default: 2888 p.localTaggedStructs = append(p.localTaggedStructs, func() { 2889 p.structs[tag].emit(p, n.DeclarationSpecifiers) 2890 }) 2891 } 2892 } 2893 } 2894 return true 2895 }) 2896 2897 if n.InitDeclaratorList == nil { 2898 return 2899 } 2900 2901 // DeclarationSpecifiers InitDeclaratorList ';' 2902 sep := tidyComment("\n", n) //TODO repeats 2903 for list := n.InitDeclaratorList; list != nil; list = list.InitDeclaratorList { 2904 p.initDeclarator(f, list.InitDeclarator, sep, topDecl) 2905 sep = "\n" 2906 } 2907 } 2908 2909 func (p *project) initDeclarator(f *function, n *cc.InitDeclarator, sep string, topDecl bool) { 2910 if f == nil { 2911 p.tld(f, n, sep, false) 2912 return 2913 } 2914 2915 d := n.Declarator 2916 if d.IsExtern() || d.IsTypedefName { 2917 return 2918 } 2919 2920 if tld := p.tlds[d]; tld != nil && !topDecl { // static local 2921 if !p.pass1 { 2922 p.staticQueue = append(p.staticQueue, n) 2923 } 2924 return 2925 } 2926 2927 local := f.locals[d] 2928 if local == nil { // Dead declaration. 2929 return 2930 } 2931 2932 block := f.block 2933 t := d.Type() 2934 vla := t.Kind() == cc.Array && t.IsVLA() 2935 if vla && p.pass1 { 2936 f.vlas[d] = struct{}{} 2937 return 2938 } 2939 2940 switch n.Case { 2941 case cc.InitDeclaratorDecl: // Declarator AttributeSpecifierList 2942 if block.noDecl || block.topDecl && !topDecl { 2943 return 2944 } 2945 2946 switch { 2947 case vla: 2948 p.initDeclaratorDeclVLA(f, n, sep) 2949 default: 2950 p.initDeclaratorDecl(f, n, sep) 2951 } 2952 case cc.InitDeclaratorInit: // Declarator AttributeSpecifierList '=' Initializer 2953 if vla { 2954 panic(todo("")) 2955 } 2956 2957 if f.block.topDecl { 2958 switch { 2959 case topDecl: 2960 p.initDeclaratorDecl(f, n, sep) 2961 if local.forceRead && !local.isPinned { 2962 p.w("_ = %s;", local.name) 2963 } 2964 default: 2965 sv := f.condInitPrefix 2966 f.condInitPrefix = func() { 2967 p.declarator(d, f, d, d.Type(), exprLValue, 0) 2968 p.w(" = ") 2969 } 2970 switch { 2971 case p.isConditionalInitializer(n.Initializer): 2972 p.assignmentExpression(f, n.Initializer.AssignmentExpression, d.Type(), exprCondInit, 0) 2973 default: 2974 f.condInitPrefix() 2975 p.initializer(f, n.Initializer, d.Type(), d.StorageClass, nil) 2976 } 2977 f.condInitPrefix = sv 2978 p.w(";") 2979 } 2980 return 2981 } 2982 2983 p.w("%s", sep) 2984 switch { 2985 case local.isPinned: 2986 sv := f.condInitPrefix 2987 f.condInitPrefix = func() { 2988 //TODO- p.declarator(d, f, d, d.Type(), exprLValue, 0) 2989 //TODO- p.w(" = ") 2990 p.w("*(*%s)(unsafe.Pointer(%s%s/* %s */)) = ", p.typ(n, d.Type()), f.bpName, nonZeroUintptr(local.off), local.name) 2991 } 2992 switch { 2993 case p.isConditionalInitializer(n.Initializer): 2994 p.assignmentExpression(f, n.Initializer.AssignmentExpression, d.Type(), exprCondInit, 0) 2995 default: 2996 f.condInitPrefix() 2997 p.initializer(f, n.Initializer, d.Type(), d.StorageClass, nil) 2998 p.w(";") 2999 } 3000 f.condInitPrefix = sv 3001 p.w(";") 3002 default: 3003 var semi string 3004 switch { 3005 case block.noDecl: 3006 semi = "" 3007 default: 3008 p.w("var %s ", local.name) 3009 if !isAggregateTypeOrUnion(d.Type()) { 3010 p.w("%s ", p.typ(n, d.Type())) 3011 } 3012 semi = ";" 3013 } 3014 switch { 3015 case p.isConditionalInitializer(n.Initializer): 3016 p.w("%s", semi) 3017 sv := f.condInitPrefix 3018 f.condInitPrefix = func() { p.w("%s = ", local.name) } 3019 p.assignmentExpression(f, n.Initializer.AssignmentExpression, d.Type(), exprCondInit, 0) 3020 f.condInitPrefix = sv 3021 default: 3022 if block.noDecl { 3023 p.w("%s", local.name) 3024 } 3025 p.w(" = ") 3026 p.initializer(f, n.Initializer, d.Type(), d.StorageClass, nil) 3027 } 3028 p.w(";") 3029 } 3030 default: 3031 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 3032 } 3033 if !block.noDecl && local.forceRead && !local.isPinned { 3034 p.w("_ = %s;", local.name) 3035 } 3036 } 3037 3038 func (p *project) isConditionalInitializer(n *cc.Initializer) bool { 3039 return n.Case == cc.InitializerExpr && p.isConditionalAssignmentExpr(n.AssignmentExpression) 3040 } 3041 3042 func (p *project) isConditionalAssignmentExpr(n *cc.AssignmentExpression) bool { 3043 return n.Case == cc.AssignmentExpressionCond && 3044 n.ConditionalExpression.Case == cc.ConditionalExpressionCond 3045 } 3046 3047 func (p *project) initDeclaratorDeclVLA(f *function, n *cc.InitDeclarator, sep string) { 3048 d := n.Declarator 3049 local := f.locals[d] 3050 if strings.TrimSpace(sep) == "" { 3051 sep = "\n" 3052 } 3053 if local.isPinned { 3054 panic(todo("")) 3055 p.w("%s// var %s %s at %s%s, %d\n", sep, local.name, p.typ(n, d.Type()), f.bpName, nonZeroUintptr(local.off), d.Type().Size()) 3056 return 3057 } 3058 3059 p.w("%s%s = %sXrealloc(%s, %s, types.Size_t(", sep, local.name, p.task.crt, f.tlsName, local.name) 3060 e := d.Type().LenExpr() 3061 p.assignmentExpression(f, e, e.Operand.Type(), exprValue, 0) 3062 if sz := d.Type().Elem().Size(); sz != 1 { 3063 p.w("*%d", sz) 3064 } 3065 p.w("));") 3066 } 3067 3068 func (p *project) initDeclaratorDecl(f *function, n *cc.InitDeclarator, sep string) { 3069 d := n.Declarator 3070 local := f.locals[d] 3071 if strings.TrimSpace(sep) == "" { 3072 sep = "\n" 3073 } 3074 if local.isPinned { 3075 p.w("%s// var %s %s at %s%s, %d\n", sep, local.name, p.typ(n, d.Type()), f.bpName, nonZeroUintptr(local.off), d.Type().Size()) 3076 return 3077 } 3078 3079 p.w("%svar %s %s;", sep, local.name, p.typ(n, d.Type())) 3080 } 3081 3082 func (p *project) declarator(n cc.Node, f *function, d *cc.Declarator, t cc.Type, mode exprMode, flags flags) { 3083 switch mode { 3084 case exprLValue: 3085 p.declaratorLValue(n, f, d, t, mode, flags) 3086 case exprFunc: 3087 p.declaratorFunc(n, f, d, t, mode, flags) 3088 case exprValue: 3089 p.declaratorValue(n, f, d, t, mode, flags) 3090 case exprAddrOf: 3091 p.declaratorAddrOf(n, f, d, t, flags) 3092 case exprSelect: 3093 p.declaratorSelect(n, f, d) 3094 case exprDecay: 3095 p.declaratorDecay(n, f, d, t, mode, flags) 3096 default: 3097 panic(todo("", mode)) 3098 } 3099 } 3100 3101 func (p *project) declaratorDecay(n cc.Node, f *function, d *cc.Declarator, t cc.Type, mode exprMode, flags flags) { 3102 if d.Type().Kind() != cc.Array { 3103 panic(todo("", n.Position(), p.pos(d))) 3104 } 3105 3106 if f != nil { 3107 if local := f.locals[d]; local != nil { 3108 if d.Type().IsVLA() { 3109 switch { 3110 case local.isPinned: 3111 panic(todo("")) 3112 default: 3113 p.w("%s", local.name) 3114 return 3115 } 3116 } 3117 3118 if d.IsParameter { 3119 p.w("%s", local.name) 3120 return 3121 } 3122 3123 if p.pass1 { 3124 if !d.Type().IsVLA() { 3125 f.pin(n, d) 3126 } 3127 return 3128 } 3129 3130 if !local.isPinned { 3131 p.err(n, "%v: %v: missed pinning", n.Position(), d.Position(), d.Name()) 3132 } 3133 p.w("(%s%s)/* &%s[0] */", f.bpName, nonZeroUintptr(local.off), local.name) 3134 return 3135 } 3136 } 3137 3138 if x := p.tlds[d]; x != nil && d.IsStatic() { 3139 p.w("uintptr(unsafe.Pointer(&%s))", x.name) 3140 return 3141 } 3142 3143 switch x := p.symtab[d.Name().String()].(type) { 3144 case *tld: 3145 p.w("uintptr(unsafe.Pointer(&%s))", x.name) 3146 case *imported: 3147 x.used = true 3148 p.w("uintptr(unsafe.Pointer(&%sX%s))", x.qualifier, d.Name()) 3149 default: 3150 panic(todo("%v: %v: %q %T", n.Position(), p.pos(d), d.Name(), x)) 3151 } 3152 } 3153 3154 func (p *project) declaratorValue(n cc.Node, f *function, d *cc.Declarator, t cc.Type, mode exprMode, flags flags) { 3155 switch k := p.declaratorKind(d); k { 3156 case opNormal: 3157 p.declaratorValueNormal(n, f, d, t, mode, flags) 3158 case opArray: 3159 p.declaratorValueArray(n, f, d, t, mode, flags) 3160 case opFunction: 3161 p.declarator(n, f, d, t, exprAddrOf, flags) 3162 case opUnion: 3163 p.declaratorValueUnion(n, f, d, t, mode, flags) 3164 case opArrayParameter: 3165 p.declaratorValueArrayParameter(n, f, d, t, mode, flags) 3166 default: 3167 panic(todo("", d.Position(), k)) 3168 } 3169 } 3170 3171 func (p *project) declaratorValueArrayParameter(n cc.Node, f *function, d *cc.Declarator, t cc.Type, mode exprMode, flags flags) { 3172 if d.Type().IsScalarType() { 3173 defer p.w("%s", p.convertType(n, d.Type(), t, flags)) 3174 } 3175 local := f.locals[d] 3176 if local.isPinned { 3177 p.w("*(*%s)(unsafe.Pointer(%s%s/* %s */))", p.typ(n, paramTypeDecay(d)), f.bpName, nonZeroUintptr(local.off), local.name) 3178 return 3179 } 3180 3181 p.w("%s", local.name) 3182 } 3183 3184 func (p *project) declaratorValueUnion(n cc.Node, f *function, d *cc.Declarator, t cc.Type, mode exprMode, flags flags) { 3185 if d.Type().IsScalarType() { 3186 defer p.w("%s", p.convertType(n, d.Type(), t, flags)) 3187 } 3188 if f != nil { 3189 if local := f.locals[d]; local != nil { 3190 if local.isPinned { 3191 p.w("*(*%s)(unsafe.Pointer(%s%s/* %s */))", p.typ(d, d.Type()), f.bpName, nonZeroUintptr(local.off), local.name) 3192 return 3193 } 3194 3195 p.w("%s", local.name) 3196 return 3197 } 3198 } 3199 3200 p.declaratorDefault(n, d) 3201 } 3202 3203 func (p *project) isVolatileOrAtomic(d *cc.Declarator) bool { 3204 if d.Type().IsVolatile() || d.Type().IsAtomic() { 3205 return true 3206 } 3207 3208 _, ok := p.task.volatiles[d.Name()] 3209 return ok 3210 } 3211 3212 func (p *project) declaratorDefault(n cc.Node, d *cc.Declarator) { 3213 if x := p.tlds[d]; x != nil && d.IsStatic() { 3214 if p.isVolatileOrAtomic(d) { 3215 p.atomicLoadNamedAddr(n, d.Type(), x.name) 3216 return 3217 } 3218 3219 p.w("%s", x.name) 3220 return 3221 } 3222 3223 switch x := p.symtab[d.Name().String()].(type) { 3224 case *tld: 3225 if p.isVolatileOrAtomic(d) { 3226 p.atomicLoadNamedAddr(n, d.Type(), x.name) 3227 return 3228 } 3229 3230 p.w("%s", x.name) 3231 case *imported: 3232 x.used = true 3233 if p.isVolatileOrAtomic(d) { 3234 p.atomicLoadNamedAddr(n, d.Type(), fmt.Sprintf("%sX%s", x.qualifier, d.Name())) 3235 return 3236 } 3237 3238 p.w("%sX%s", x.qualifier, d.Name()) 3239 default: 3240 if d.IsExtern() { 3241 switch d.Name() { 3242 case idEnviron: 3243 if d.Type().String() == "pointer to pointer to char" { 3244 p.w("%sEnviron()", p.task.crt) 3245 return 3246 } 3247 } 3248 } 3249 3250 if d.Linkage == cc.External && p.task.nostdlib { 3251 p.w("X%s", d.Name()) 3252 return 3253 } 3254 3255 id := fmt.Sprintf("__builtin_%s", d.Name()) 3256 switch x := p.symtab[id].(type) { 3257 case *imported: 3258 x.used = true 3259 p.w("%sX%s", x.qualifier, d.Name()) 3260 return 3261 } 3262 3263 if !d.IsImplicit() { 3264 nm := d.Name() 3265 name := nm.String() 3266 switch d.Linkage { 3267 case cc.External: 3268 name = p.task.exportExterns + name 3269 tld := &tld{name: name} 3270 p.externs[nm] = tld 3271 p.w("%s", name) 3272 return 3273 case cc.Internal: 3274 if token.IsExported(name) { 3275 name = "s" + name 3276 } 3277 tld := &tld{name: p.scope.take(cc.String(name))} 3278 for _, v := range p.ast.Scope[nm] { 3279 if d, ok := v.(*cc.Declarator); ok { 3280 p.tlds[d] = tld 3281 } 3282 } 3283 p.w("%s", name) 3284 return 3285 } 3286 } 3287 3288 p.err(n, "back-end: undefined: %s", d.Name()) 3289 } 3290 } 3291 3292 func (p *project) declaratorValueArray(n cc.Node, f *function, d *cc.Declarator, t cc.Type, mode exprMode, flags flags) { 3293 if t.IsIntegerType() { 3294 defer p.w("%s", p.convertType(n, nil, t, flags)) 3295 } 3296 if f != nil { 3297 if local := f.locals[d]; local != nil { 3298 if local.isPinned { 3299 p.w("(%s%s)/* %s */", f.bpName, nonZeroUintptr(local.off), local.name) 3300 return 3301 } 3302 3303 p.w("%s", local.name) 3304 return 3305 } 3306 } 3307 3308 p.declaratorDefault(n, d) 3309 } 3310 3311 func (p *project) declaratorValueNormal(n cc.Node, f *function, d *cc.Declarator, t cc.Type, mode exprMode, flags flags) { 3312 if d.Type().IsScalarType() { 3313 defer p.w("%s", p.convertType(n, d.Type(), t, flags)) 3314 } 3315 if f != nil { 3316 if local := f.locals[d]; local != nil { 3317 if local.isPinned { 3318 if p.isVolatileOrAtomic(d) && d.IsParameter && d.Write != 0 { 3319 p.w("%sAtomicLoadP%s(%s%s/* %s */)", p.task.crt, p.helperType(n, d.Type()), f.bpName, nonZeroUintptr(local.off), local.name) 3320 return 3321 } 3322 3323 p.w("*(*%s)(unsafe.Pointer(%s%s/* %s */))", p.typ(d, d.Type()), f.bpName, nonZeroUintptr(local.off), local.name) 3324 return 3325 } 3326 3327 if p.isVolatileOrAtomic(d) && d.IsParameter && d.Write != 0 { 3328 p.atomicLoadNamedAddr(n, d.Type(), local.name) 3329 return 3330 } 3331 3332 p.w("%s", local.name) 3333 return 3334 } 3335 } 3336 3337 p.declaratorDefault(n, d) 3338 } 3339 3340 func (p *project) declaratorFunc(n cc.Node, f *function, d *cc.Declarator, t cc.Type, mode exprMode, flags flags) { 3341 switch k := p.declaratorKind(d); k { 3342 case opFunction: 3343 p.declaratorFuncFunc(n, f, d, t, exprValue, flags) 3344 case opNormal: 3345 p.declaratorFuncNormal(n, f, d, t, exprValue, flags) 3346 default: 3347 panic(todo("", d.Position(), k)) 3348 } 3349 } 3350 3351 func (p *project) declaratorFuncNormal(n cc.Node, f *function, d *cc.Declarator, t cc.Type, mode exprMode, flags flags) { 3352 u := d.Type() 3353 if u.Kind() == cc.Ptr { 3354 u = u.Elem() 3355 } 3356 switch u.Kind() { 3357 case cc.Function: 3358 if local := f.locals[d]; local != nil { 3359 if local.isPinned { 3360 p.w("(*(*") 3361 p.functionSignature(n, f, u, "") 3362 p.w(")(unsafe.Pointer(%s%s)))", f.bpName, nonZeroUintptr(local.off)) 3363 return 3364 } 3365 3366 if d.IsParameter { 3367 p.w("(*(*") 3368 p.functionSignature(n, f, u, "") 3369 p.w(")(unsafe.Pointer(&%s)))", local.name) 3370 return 3371 } 3372 3373 panic(todo("", p.pos(d))) 3374 } 3375 3376 if x := p.tlds[d]; x != nil && d.IsStatic() { 3377 p.w("(*(*") 3378 p.functionSignature(n, f, u, "") 3379 p.w(")(unsafe.Pointer(&%s)))", x.name) 3380 return 3381 } 3382 3383 switch x := p.symtab[d.Name().String()].(type) { 3384 case *tld: 3385 p.w("(*(*") 3386 p.functionSignature(n, f, u, "") 3387 p.w(")(unsafe.Pointer(&%s)))", x.name) 3388 case *imported: 3389 x.used = true 3390 p.w("uintptr(unsafe.Pointer(&%sX%s))", x.qualifier, d.Name()) 3391 default: 3392 panic(todo("%v: %v: %q", n.Position(), p.pos(d), d.Name())) 3393 } 3394 default: 3395 panic(todo("", p.pos(d), u)) 3396 } 3397 } 3398 3399 func (p *project) declaratorFuncFunc(n cc.Node, f *function, d *cc.Declarator, t cc.Type, mode exprMode, flags flags) { 3400 switch d.Type().Kind() { 3401 case cc.Function: 3402 // ok 3403 default: 3404 panic(todo("", p.pos(d), d.Type(), d.Type().Kind())) 3405 } 3406 3407 if f != nil { 3408 if local := f.locals[d]; local != nil { 3409 if local.isPinned { 3410 panic(todo("")) 3411 } 3412 3413 p.w(" %s", local.name) 3414 return 3415 } 3416 } 3417 3418 p.declaratorDefault(n, d) 3419 } 3420 3421 func (p *project) declaratorLValue(n cc.Node, f *function, d *cc.Declarator, t cc.Type, mode exprMode, flags flags) { 3422 switch k := p.declaratorKind(d); k { 3423 case opNormal, opArrayParameter, opUnion: 3424 p.declaratorLValueNormal(n, f, d, t, mode, flags) 3425 case opArray: 3426 p.declaratorLValueArray(n, f, d, t, mode, flags) 3427 default: 3428 panic(todo("", d.Position(), k)) 3429 } 3430 } 3431 3432 func (p *project) declaratorLValueArray(n cc.Node, f *function, d *cc.Declarator, t cc.Type, mode exprMode, flags flags) { 3433 if f != nil { 3434 if local := f.locals[d]; local != nil { 3435 if local.isPinned { 3436 p.w("*(*%s)(unsafe.Pointer(%s%s/* %s */))", p.typ(d, d.Type()), f.bpName, nonZeroUintptr(local.off), local.name) 3437 return 3438 } 3439 3440 p.w("%s", local.name) 3441 return 3442 } 3443 } 3444 3445 p.declaratorDefault(n, d) 3446 } 3447 3448 func (p *project) declaratorLValueNormal(n cc.Node, f *function, d *cc.Declarator, t cc.Type, mode exprMode, flags flags) { 3449 if p.isVolatileOrAtomic(d) && flags&fVolatileOk == 0 { 3450 panic(todo("", n.Position(), d.Position())) 3451 } 3452 3453 if d.Type().IsScalarType() { 3454 defer p.w("%s", p.convertType(n, d.Type(), t, flags)) 3455 } 3456 if f != nil { 3457 if local := f.locals[d]; local != nil { 3458 if local.isPinned { 3459 p.w("*(*%s)(unsafe.Pointer(%s%s/* %s */))", p.dtyp(d), f.bpName, nonZeroUintptr(local.off), local.name) 3460 return 3461 } 3462 3463 p.w("%s", local.name) 3464 return 3465 } 3466 } 3467 3468 p.declaratorLValueDefault(n, d) 3469 } 3470 3471 func (p *project) declaratorLValueDefault(n cc.Node, d *cc.Declarator) { 3472 if x := p.tlds[d]; x != nil && d.IsStatic() { 3473 p.w("%s", x.name) 3474 return 3475 } 3476 3477 switch x := p.symtab[d.Name().String()].(type) { 3478 case *tld: 3479 p.w("%s", x.name) 3480 case *imported: 3481 x.used = true 3482 p.w("%sX%s", x.qualifier, d.Name()) 3483 default: 3484 if d.IsExtern() { 3485 switch d.Name() { 3486 case idEnviron: 3487 if d.Type().String() == "pointer to pointer to char" { 3488 p.w("*(*uintptr)(unsafe.Pointer(%sEnvironP()))", p.task.crt) 3489 return 3490 } 3491 } 3492 } 3493 3494 panic(todo("%v: %v: %q", n.Position(), p.pos(d), d.Name())) 3495 } 3496 } 3497 3498 func (p *project) declaratorKind(d *cc.Declarator) opKind { 3499 switch { 3500 case p.isArrayParameterDeclarator(d): 3501 return opArrayParameter 3502 case !p.pass1 && p.isArrayDeclarator(d): 3503 return opArray 3504 case d.Type().Kind() == cc.Function && !d.IsParameter: 3505 return opFunction 3506 case d.Type().Kind() == cc.Union: 3507 return opUnion 3508 default: 3509 return opNormal 3510 } 3511 } 3512 3513 func (p *project) declaratorSelect(n cc.Node, f *function, d *cc.Declarator) { 3514 switch k := p.declaratorKind(d); k { 3515 case opNormal: 3516 p.declaratorSelectNormal(n, f, d) 3517 case opArray: 3518 p.declaratorSelectArray(n, f, d) 3519 default: 3520 panic(todo("", d.Position(), k)) 3521 } 3522 } 3523 3524 func (p *project) declaratorSelectArray(n cc.Node, f *function, d *cc.Declarator) { 3525 if local := f.locals[d]; local != nil { 3526 if local.isPinned { 3527 panic(todo("", p.pos(n))) 3528 //TODO type error 3529 p.w("(*%s)(unsafe.Pointer(%s%s/* &%s */))", p.typ(d, d.Type()), f.bpName, nonZeroUintptr(local.off), local.name) 3530 return 3531 } 3532 3533 p.w("%s", local.name) 3534 return 3535 } 3536 3537 p.declaratorDefault(n, d) 3538 } 3539 3540 func (p *project) declaratorSelectNormal(n cc.Node, f *function, d *cc.Declarator) { 3541 if local := f.locals[d]; local != nil { 3542 if local.isPinned { 3543 p.w("(*%s)(unsafe.Pointer(%s%s/* &%s */))", p.typ(d, d.Type()), f.bpName, nonZeroUintptr(local.off), local.name) 3544 return 3545 } 3546 3547 p.w("%s", local.name) 3548 return 3549 } 3550 3551 p.declaratorDefault(n, d) 3552 } 3553 3554 func (p *project) declaratorAddrOf(n cc.Node, f *function, d *cc.Declarator, t cc.Type, flags flags) { 3555 switch k := p.declaratorKind(d); k { 3556 case opArray: 3557 p.declaratorAddrOfArray(n, f, d) 3558 case opNormal: 3559 p.declaratorAddrOfNormal(n, f, d, flags) 3560 case opUnion: 3561 p.declaratorAddrOfUnion(n, f, d) 3562 case opFunction: 3563 p.declaratorAddrOfFunction(n, f, d) 3564 case opArrayParameter: 3565 p.declaratorAddrOfArrayParameter(n, f, d) 3566 default: 3567 panic(todo("", d.Position(), k)) 3568 } 3569 } 3570 3571 func (p *project) declaratorAddrOfArrayParameter(n cc.Node, f *function, d *cc.Declarator) { 3572 if p.pass1 { 3573 f.pin(n, d) 3574 return 3575 } 3576 3577 local := f.locals[d] 3578 p.w("(%s%s)/* &%s */", f.bpName, nonZeroUintptr(local.off), local.name) 3579 } 3580 3581 func (p *project) declaratorAddrOfFunction(n cc.Node, f *function, d *cc.Declarator) { 3582 if d.Type().Kind() != cc.Function { 3583 panic(todo("", p.pos(n))) 3584 } 3585 3586 if x := p.tlds[d]; x != nil && d.IsStatic() { 3587 p.w("*(*uintptr)(unsafe.Pointer(&struct{f ") 3588 p.functionSignature(n, f, d.Type(), "") 3589 p.w("}{%s}))", x.name) 3590 return 3591 } 3592 3593 switch x := p.symtab[d.Name().String()].(type) { 3594 case *tld: 3595 p.w("*(*uintptr)(unsafe.Pointer(&struct{f ") 3596 p.functionSignature(n, f, d.Type(), "") 3597 p.w("}{%s}))", x.name) 3598 case *imported: 3599 x.used = true 3600 p.w("*(*uintptr)(unsafe.Pointer(&struct{f ") 3601 p.functionSignature(n, f, d.Type(), "") 3602 p.w("}{%sX%s}))", x.qualifier, d.Name()) 3603 default: 3604 p.err(d, "back-end: undefined: %s", d.Name()) 3605 } 3606 } 3607 3608 func (p *project) declaratorAddrOfUnion(n cc.Node, f *function, d *cc.Declarator) { 3609 if f != nil { 3610 if local := f.locals[d]; local != nil { 3611 if p.pass1 { 3612 f.pin(n, d) 3613 return 3614 } 3615 3616 if local.isPinned { 3617 p.w("(%s%s)/* &%s */", f.bpName, nonZeroUintptr(local.off), local.name) 3618 return 3619 } 3620 3621 panic(todo("", p.pos(n))) 3622 } 3623 } 3624 3625 if x := p.tlds[d]; x != nil && d.IsStatic() { 3626 p.w("uintptr(unsafe.Pointer(&%s))", x.name) 3627 return 3628 } 3629 3630 switch x := p.symtab[d.Name().String()].(type) { 3631 case *tld: 3632 p.w("uintptr(unsafe.Pointer(&%s))", x.name) 3633 case *imported: 3634 x.used = true 3635 p.w("uintptr(unsafe.Pointer(&%sX%s))", x.qualifier, d.Name()) 3636 default: 3637 panic(todo("%v: %v: %q", n.Position(), p.pos(d), d.Name())) 3638 } 3639 } 3640 3641 func (p *project) declaratorAddrOfNormal(n cc.Node, f *function, d *cc.Declarator, flags flags) { 3642 if f != nil { 3643 if local := f.locals[d]; local != nil { 3644 if p.pass1 && flags&fAddrOfFuncPtrOk == 0 { 3645 f.pin(n, d) 3646 return 3647 } 3648 3649 if local.isPinned { 3650 p.w("(%s%s)/* &%s */", f.bpName, nonZeroUintptr(local.off), local.name) 3651 return 3652 } 3653 3654 if flags&fAddrOfFuncPtrOk != 0 { 3655 if dt := d.Type(); dt.Kind() == cc.Ptr { 3656 if elem := dt.Elem(); elem.Kind() == cc.Function || elem.Kind() == cc.Ptr && elem.Elem().Kind() == cc.Function { 3657 p.w("&%s", local.name) 3658 return 3659 } 3660 } 3661 } 3662 3663 panic(todo("", p.pos(n), p.pos(d), d.Name(), d.Type(), d.IsParameter, d.AddressTaken, flags&fAddrOfFuncPtrOk != 0)) 3664 } 3665 } 3666 3667 if x := p.tlds[d]; x != nil && d.IsStatic() { 3668 p.w("uintptr(unsafe.Pointer(&%s))", x.name) 3669 return 3670 } 3671 3672 switch x := p.symtab[d.Name().String()].(type) { 3673 case *tld: 3674 p.w("uintptr(unsafe.Pointer(&%s))", x.name) 3675 case *imported: 3676 x.used = true 3677 p.w("uintptr(unsafe.Pointer(&%sX%s))", x.qualifier, d.Name()) 3678 default: 3679 p.err(n, "undefined: %s", d.Name()) 3680 } 3681 } 3682 3683 func (p *project) declaratorAddrOfArray(n cc.Node, f *function, d *cc.Declarator) { 3684 if f != nil { 3685 if local := f.locals[d]; local != nil { 3686 if p.pass1 { 3687 f.pin(n, d) 3688 return 3689 } 3690 3691 if local.isPinned { 3692 p.w("(%s%s)/* &%s */", f.bpName, nonZeroUintptr(local.off), local.name) 3693 return 3694 } 3695 3696 panic(todo("", p.pos(d), d.Name(), d.Type(), d.IsParameter)) 3697 } 3698 } 3699 3700 if x := p.tlds[d]; x != nil && d.IsStatic() { 3701 p.w("uintptr(unsafe.Pointer(&%s))", x.name) 3702 return 3703 } 3704 3705 switch x := p.symtab[d.Name().String()].(type) { 3706 case *tld: 3707 p.w("uintptr(unsafe.Pointer(&%s))", x.name) 3708 case *imported: 3709 x.used = true 3710 p.w("uintptr(unsafe.Pointer(&%sX%s))", x.qualifier, d.Name()) 3711 default: 3712 panic(todo("%v: %v: %q", n.Position(), p.pos(d), d.Name())) 3713 } 3714 } 3715 3716 func (p *project) convertType(n cc.Node, from, to cc.Type, flags flags) string { 3717 // trc("%v: %v: %v -> %v %v", n.Position(), origin(1), from, to, flags) //TODO- DBG 3718 if from != nil { 3719 switch from.Kind() { 3720 case cc.Int128: 3721 return p.convertTypeFromInt128(n, to, flags) 3722 case cc.UInt128: 3723 return p.convertTypeFromUint128(n, to, flags) 3724 } 3725 } 3726 3727 switch to.Kind() { 3728 case cc.Int128: 3729 return p.convertTypeToInt128(n, from, flags) 3730 case cc.UInt128: 3731 return p.convertTypeToUint128(n, from, flags) 3732 } 3733 3734 // trc("%v: %v -> %v\n%s", p.pos(n), from, to, debug.Stack()[:600]) //TODO- 3735 force := flags&fForceConv != 0 3736 if from == nil { 3737 p.w("%s(", p.typ(n, to)) 3738 return ")" 3739 } 3740 3741 if from.IsScalarType() { 3742 switch { 3743 case force: 3744 p.w("%s(", p.helperType2(n, from, to)) 3745 return ")" 3746 case from.Kind() == to.Kind(): 3747 return "" 3748 default: 3749 p.w("%s(", p.typ(n, to)) 3750 return ")" 3751 } 3752 } 3753 3754 switch from.Kind() { 3755 case cc.Function, cc.Struct, cc.Union, cc.Ptr, cc.Array: 3756 if from.Kind() == to.Kind() { 3757 return "" 3758 } 3759 3760 panic(todo("", n.Position(), from, to, from.Alias(), to.Alias())) 3761 case cc.Double, cc.Float: 3762 p.w("%s(", p.typ(n, to)) 3763 return ")" 3764 } 3765 3766 panic(todo("", n.Position(), from, to, from.Alias(), to.Alias())) 3767 } 3768 3769 func (p *project) convertTypeFromInt128(n cc.Node, to cc.Type, flags flags) string { 3770 switch k := to.Kind(); { 3771 case k == cc.Float, k == cc.Double: 3772 p.w("(") 3773 return fmt.Sprintf(").Float%d()", to.Size()*8) 3774 case k == cc.Int128: 3775 return "" 3776 case k == cc.UInt128: 3777 p.w("%sUint128FromInt128(", p.task.crt) 3778 return ")" 3779 case to.IsIntegerType() && to.IsSignedType(): 3780 p.w("int%d((", to.Size()*8) 3781 return ").Lo)" 3782 case to.IsIntegerType() && !to.IsSignedType(): 3783 p.w("uint%d((", to.Size()*8) 3784 return ").Lo)" 3785 default: 3786 panic(todo("", n.Position(), to, to.Alias())) 3787 } 3788 } 3789 3790 func (p *project) convertTypeFromUint128(n cc.Node, to cc.Type, flags flags) string { 3791 switch k := to.Kind(); { 3792 case k == cc.Float, k == cc.Double: 3793 p.w("(") 3794 return fmt.Sprintf(").Float%d()", to.Size()*8) 3795 case k == cc.Int128: 3796 p.w("(") 3797 return ").Int128()" 3798 case k == cc.UInt128: 3799 return "" 3800 case to.IsIntegerType() && to.IsSignedType(): 3801 p.w("int%d((", to.Size()*8) 3802 return ").Lo)" 3803 case to.IsIntegerType() && !to.IsSignedType(): 3804 p.w("uint%d((", to.Size()*8) 3805 return ").Lo)" 3806 default: 3807 panic(todo("", n.Position(), to, to.Alias())) 3808 } 3809 } 3810 3811 func (p *project) convertTypeToInt128(n cc.Node, from cc.Type, flags flags) string { 3812 switch k := from.Kind(); { 3813 case k == cc.Float, k == cc.Double: 3814 p.w("%sInt128FromFloat%d(", p.task.crt, from.Size()*8) 3815 return ")" 3816 case k == cc.Int128: 3817 return "" 3818 case k == cc.UInt128: 3819 p.w("%sInt128FromUint128(", p.task.crt) 3820 return ")" 3821 case from.IsIntegerType() && from.IsSignedType(): 3822 p.w("%sInt128FromInt%d(", p.task.crt, from.Size()*8) 3823 return ")" 3824 case from.IsIntegerType() && !from.IsSignedType(): 3825 p.w("%sInt128FromUint%d(", p.task.crt, from.Size()*8) 3826 return ")" 3827 default: 3828 panic(todo("", n.Position(), from, from.Alias())) 3829 } 3830 } 3831 3832 func (p *project) convertTypeToUint128(n cc.Node, from cc.Type, flags flags) string { 3833 switch k := from.Kind(); { 3834 case k == cc.Float, k == cc.Double: 3835 p.w("%sUint128FromFloat%d(", p.task.crt, from.Size()*8) 3836 return ")" 3837 case k == cc.Int128: 3838 p.w("(") 3839 return ").Uint128()" 3840 case k == cc.UInt128: 3841 return "" 3842 case from.IsIntegerType() && from.IsSignedType(): 3843 p.w("%sUint128FromInt%d(", p.task.crt, from.Size()*8) 3844 return ")" 3845 case from.IsIntegerType() && !from.IsSignedType(): 3846 p.w("%sUint128FromUint%d(", p.task.crt, from.Size()*8) 3847 return ")" 3848 default: 3849 panic(todo("", n.Position(), from, from.Alias())) 3850 } 3851 } 3852 3853 func (p *project) convertFromInt128(n cc.Node, op cc.Operand, to cc.Type, flags flags) string { 3854 switch k := to.Kind(); { 3855 case k == cc.Float, k == cc.Double: 3856 p.w("(") 3857 return fmt.Sprintf(").Float%d()", to.Size()*8) 3858 case k == cc.Int128: 3859 return "" 3860 case k == cc.UInt128: 3861 p.w("(") 3862 return ").Uint128()" 3863 case to.IsIntegerType() && to.IsSignedType(): 3864 p.w("%sInt%d(", p.task.crt, to.Size()*8) 3865 return ")" 3866 case to.IsIntegerType() && !to.IsSignedType(): 3867 p.w("%sUint%d(", p.task.crt, to.Size()*8) 3868 return ")" 3869 default: 3870 panic(todo("", n.Position(), to, to.Alias())) 3871 } 3872 } 3873 3874 func (p *project) convertFromUint128(n cc.Node, op cc.Operand, to cc.Type, flags flags) string { 3875 switch k := to.Kind(); { 3876 case k == cc.Float, k == cc.Double: 3877 p.w("%sUint128FromFloat%d(", p.task.crt, to.Size()*8) 3878 return ")" 3879 case k == cc.Int128: 3880 p.w("(") 3881 return ").Int128()" 3882 case k == cc.UInt128: 3883 return "" 3884 case to.IsIntegerType() && to.IsSignedType(): 3885 p.w("%sInt%d(", p.task.crt, to.Size()*8) 3886 return ")" 3887 case to.IsIntegerType() && !to.IsSignedType(): 3888 p.w("%sUint%d(", p.task.crt, to.Size()*8) 3889 return ")" 3890 default: 3891 panic(todo("", n.Position(), to, to.Alias())) 3892 } 3893 } 3894 3895 func (p *project) convertToInt128(n cc.Node, op cc.Operand, to cc.Type, flags flags) string { 3896 from := op.Type() 3897 switch k := from.Kind(); { 3898 case k == cc.Float, k == cc.Double: 3899 p.w("%sInt128FromFloat%d(", p.task.crt, from.Size()*8) 3900 return ")" 3901 case k == cc.Int128: 3902 return "" 3903 case k == cc.UInt128: 3904 p.w("(") 3905 return ").Int128()" 3906 case from.IsIntegerType() && from.IsSignedType(): 3907 p.w("%sInt128FromInt%d(", p.task.crt, from.Size()*8) 3908 return ")" 3909 case from.IsIntegerType() && !from.IsSignedType(): 3910 p.w("%sInt128FromUint%d(", p.task.crt, from.Size()*8) 3911 return ")" 3912 default: 3913 panic(todo("", n.Position(), from, from.Alias())) 3914 } 3915 } 3916 3917 func (p *project) convertToUint128(n cc.Node, op cc.Operand, to cc.Type, flags flags) string { 3918 from := op.Type() 3919 switch k := from.Kind(); { 3920 case k == cc.Float, k == cc.Double: 3921 p.w("%sUint128FromFloat%d(", p.task.crt, from.Size()*8) 3922 return ")" 3923 case k == cc.Int128: 3924 p.w("(") 3925 return ").Uint128()" 3926 case k == cc.UInt128: 3927 return "" 3928 case from.IsIntegerType() && from.IsSignedType(): 3929 p.w("%sUint128FromInt%d(", p.task.crt, from.Size()*8) 3930 return ")" 3931 case from.IsIntegerType() && !from.IsSignedType(): 3932 p.w("%sUint128FromUint%d(", p.task.crt, from.Size()*8) 3933 return ")" 3934 default: 3935 panic(todo("", n.Position(), from, from.Alias())) 3936 } 3937 } 3938 3939 func (p *project) convertNil(n cc.Node, to cc.Type, flags flags) string { 3940 switch to.Kind() { 3941 case cc.Int128: 3942 panic(todo("", p.pos(n))) 3943 case cc.UInt128: 3944 panic(todo("", p.pos(n))) 3945 } 3946 3947 p.w("%s(", p.typ(n, to)) 3948 return ")" 3949 } 3950 3951 func (p *project) convert(n cc.Node, op cc.Operand, to cc.Type, flags flags) string { 3952 if op == nil { 3953 panic(todo("internal error")) 3954 } 3955 3956 from := op.Type() 3957 switch from.Kind() { 3958 case cc.Int128: 3959 return p.convertFromInt128(n, op, to, flags) 3960 case cc.UInt128: 3961 return p.convertFromUint128(n, op, to, flags) 3962 } 3963 switch to.Kind() { 3964 case cc.Int128: 3965 return p.convertToInt128(n, op, to, flags) 3966 case cc.UInt128: 3967 return p.convertToUint128(n, op, to, flags) 3968 } 3969 3970 if flags&fForceRuntimeConv != 0 { 3971 flags |= fForceConv 3972 } 3973 force := flags&fForceConv != 0 3974 if !force && from.IsScalarType() && from.Kind() == to.Kind() { 3975 return "" 3976 } 3977 3978 if from.IsIntegerType() { 3979 return p.convertInt(n, op, to, flags) 3980 } 3981 3982 if from == to { 3983 return "" 3984 } 3985 3986 switch from.Kind() { 3987 case cc.Ptr: 3988 if !force && from.Kind() == to.Kind() { 3989 return "" 3990 } 3991 3992 if to.IsIntegerType() { 3993 p.w("%s(", p.typ(n, to)) 3994 return ")" 3995 } 3996 3997 if to.Kind() == cc.Ptr { 3998 return "" 3999 } 4000 4001 panic(todo("%v: force %v, %q %v -> %q %v", p.pos(n), force, from, from.Kind(), to, to.Kind())) 4002 case cc.Function, cc.Struct, cc.Union: 4003 if !force && from.Kind() == to.Kind() { 4004 return "" 4005 } 4006 4007 trc("%p %p", from, to) 4008 panic(todo("%q %v -> %q %v", from, from.Kind(), to, to.Kind())) 4009 case cc.Double, cc.Float: 4010 switch { 4011 case to.IsIntegerType(): 4012 p.w("%s(", p.helperType2(n, from, to)) 4013 return ")" 4014 default: 4015 p.w("%s(", p.typ(n, to)) 4016 return ")" 4017 } 4018 case cc.Array: 4019 if from.Kind() == to.Kind() { 4020 return "" 4021 } 4022 4023 switch to.Kind() { 4024 case cc.Ptr: 4025 return "" 4026 } 4027 4028 panic(todo("%q, %v -> %q, %v", from, from.Kind(), to.Kind())) 4029 } 4030 4031 panic(todo("%q -> %q", from, to)) 4032 } 4033 4034 func (p *project) convertInt(n cc.Node, op cc.Operand, to cc.Type, flags flags) string { 4035 from := op.Type() 4036 switch from.Kind() { 4037 case cc.Int128: 4038 panic(todo("", p.pos(n))) 4039 case cc.UInt128: 4040 panic(todo("", p.pos(n))) 4041 } 4042 switch to.Kind() { 4043 case cc.Int128: 4044 panic(todo("", p.pos(n))) 4045 case cc.UInt128: 4046 panic(todo("", p.pos(n))) 4047 } 4048 4049 force := flags&fForceConv != 0 4050 value := op.Value() 4051 if value == nil || !to.IsIntegerType() { 4052 if to.IsScalarType() { 4053 p.w("%s(", p.typ(n, to)) 4054 return ")" 4055 } 4056 4057 panic(todo("", op.Type(), to)) 4058 } 4059 4060 if flags&fForceRuntimeConv != 0 { 4061 p.w("%s(", p.helperType2(n, op.Type(), to)) 4062 return ")" 4063 } 4064 4065 switch { 4066 case from.IsSignedType(): 4067 switch { 4068 case to.IsSignedType(): 4069 switch x := value.(type) { 4070 case cc.Int64Value: 4071 switch to.Size() { 4072 case 1: 4073 if x >= math.MinInt8 && x <= math.MaxInt8 { 4074 switch { 4075 case !force && from.Size() == to.Size(): 4076 return "" 4077 default: 4078 p.w("int8(") 4079 return ")" 4080 } 4081 } 4082 4083 p.w("%sInt8FromInt%d(", p.task.crt, from.Size()*8) 4084 return ")" 4085 case 2: 4086 if x >= math.MinInt16 && x <= math.MaxInt16 { 4087 switch { 4088 case !force && from.Size() == to.Size(): 4089 return "" 4090 default: 4091 p.w("int16(") 4092 return ")" 4093 } 4094 } 4095 4096 p.w("%sInt16FromInt%d(", p.task.crt, from.Size()*8) 4097 return ")" 4098 case 4: 4099 if x >= math.MinInt32 && x <= math.MaxInt32 { 4100 switch { 4101 case !force && from.Size() == to.Size(): 4102 return "" 4103 default: 4104 p.w("int32(") 4105 return ")" 4106 } 4107 } 4108 4109 p.w("%sInt32FromInt%d(", p.task.crt, from.Size()*8) 4110 return ")" 4111 case 8: 4112 switch { 4113 case !force && from.Size() == to.Size(): 4114 return "" 4115 default: 4116 p.w("int64(") 4117 return ")" 4118 } 4119 default: 4120 panic(todo("%T(%v) %v -> %v", x, op.Value(), from, to)) 4121 } 4122 default: 4123 panic(todo("%T(%v) %v -> %v", x, op.Value(), from, to)) 4124 } 4125 default: // to is unsigned 4126 switch x := value.(type) { 4127 case cc.Int64Value: 4128 switch to.Size() { 4129 case 1: 4130 if x >= 0 && x <= math.MaxUint8 { 4131 p.w("%s(", p.typ(n, to)) 4132 return ")" 4133 } 4134 4135 p.w("%sUint8FromInt%d(", p.task.crt, from.Size()*8) 4136 return ")" 4137 case 2: 4138 if x >= 0 && x <= math.MaxUint16 { 4139 p.w("%s(", p.typ(n, to)) 4140 return ")" 4141 } 4142 4143 p.w("%sUint16FromInt%d(", p.task.crt, from.Size()*8) 4144 return ")" 4145 case 4: 4146 if x >= 0 && x <= math.MaxUint32 { 4147 p.w("%s(", p.typ(n, to)) 4148 return ")" 4149 } 4150 4151 p.w("%sUint32FromInt%d(", p.task.crt, from.Size()*8) 4152 return ")" 4153 case 8: 4154 if x >= 0 { 4155 p.w("uint64(") 4156 return ")" 4157 } 4158 4159 p.w("%sUint64FromInt%d(", p.task.crt, from.Size()*8) 4160 return ")" 4161 default: 4162 panic(todo("%T(%v) %v -> %v", x, op.Value(), from, to)) 4163 } 4164 case cc.Uint64Value: 4165 switch to.Size() { 4166 case 1: 4167 if x <= math.MaxUint8 { 4168 p.w("%s(", p.typ(n, to)) 4169 return ")" 4170 } 4171 4172 p.w("%sUint8FromUint%d(", p.task.crt, from.Size()*8) 4173 return ")" 4174 case 2: 4175 if x <= math.MaxUint16 { 4176 p.w("%s(", p.typ(n, to)) 4177 return ")" 4178 } 4179 4180 p.w("%sUint16FromUint%d(", p.task.crt, from.Size()*8) 4181 return ")" 4182 case 4: 4183 if x <= math.MaxUint32 { 4184 p.w("%s(", p.typ(n, to)) 4185 return ")" 4186 } 4187 4188 p.w("%sUint32FromUint%d(", p.task.crt, from.Size()*8) 4189 return ")" 4190 case 8: 4191 p.w("uint64(") 4192 return ")" 4193 default: 4194 panic(todo("%T(%v) %v -> %v", x, op.Value(), from, to)) 4195 } 4196 default: 4197 panic(todo("%T(%v) %v -> %v", x, op.Value(), from, to)) 4198 } 4199 } 4200 default: // from is unsigned 4201 switch { 4202 case to.IsSignedType(): 4203 switch x := value.(type) { 4204 case cc.Uint64Value: 4205 switch to.Size() { 4206 case 1: 4207 if x <= math.MaxInt8 { 4208 p.w("int8(") 4209 return ")" 4210 } 4211 4212 p.w("%sInt8FromUint%d(", p.task.crt, from.Size()*8) 4213 return ")" 4214 case 2: 4215 if x <= math.MaxInt16 { 4216 p.w("int16(") 4217 return ")" 4218 } 4219 4220 p.w("%sInt16FromUint%d(", p.task.crt, from.Size()*8) 4221 return ")" 4222 case 4: 4223 if x <= math.MaxInt32 { 4224 p.w("int32(") 4225 return ")" 4226 } 4227 4228 p.w("%sInt32FromUint%d(", p.task.crt, from.Size()*8) 4229 return ")" 4230 case 8: 4231 if x <= math.MaxInt64 { 4232 p.w("int64(") 4233 return ")" 4234 } 4235 4236 p.w("%sInt64FromUint%d(", p.task.crt, from.Size()*8) 4237 return ")" 4238 default: 4239 panic(todo("%T(%v) %v -> %v", x, op.Value(), from, to)) 4240 } 4241 default: 4242 panic(todo("%T(%v) %v -> %v", x, op.Value(), from, to)) 4243 } 4244 default: // to is unsigned 4245 switch x := value.(type) { 4246 case cc.Uint64Value: 4247 switch to.Size() { 4248 case 1: 4249 if x <= math.MaxUint8 { 4250 switch { 4251 case !force && from.Size() == 1: 4252 return "" 4253 default: 4254 p.w("uint8(") 4255 return ")" 4256 } 4257 } 4258 4259 p.w("%sUint8FromUint%d(", p.task.crt, from.Size()*8) 4260 return ")" 4261 case 2: 4262 if x <= math.MaxUint16 { 4263 switch { 4264 case !force && from.Size() == 2: 4265 return "" 4266 default: 4267 p.w("uint16(") 4268 return ")" 4269 } 4270 } 4271 4272 p.w("%sUint16FromUint%d(", p.task.crt, from.Size()*8) 4273 return ")" 4274 case 4: 4275 if x <= math.MaxUint32 { 4276 switch { 4277 case !force && from.Size() == 4: 4278 return "" 4279 default: 4280 p.w("uint32(") 4281 return ")" 4282 } 4283 } 4284 4285 p.w("%sUint32FromUint%d(", p.task.crt, from.Size()*8) 4286 return ")" 4287 case 8: 4288 switch { 4289 case !force && from.Size() == 8: 4290 return "" 4291 default: 4292 p.w("uint64(") 4293 return ")" 4294 } 4295 default: 4296 panic(todo("%T(%v) %v -> %v", x, op.Value(), from, to)) 4297 } 4298 default: 4299 panic(todo("%T(%v) %v -> %v", x, op.Value(), from, to)) 4300 } 4301 } 4302 } 4303 } 4304 4305 func nonZeroUintptr(n uintptr) string { 4306 if n == 0 { 4307 return "" 4308 } 4309 4310 return fmt.Sprintf("%+d", n) 4311 } 4312 4313 func alias(attr []*cc.AttributeSpecifier) (r cc.StringID) { 4314 for _, v := range attr { 4315 cc.Inspect(v, func(n cc.Node, entry bool) bool { 4316 if !entry { 4317 return true 4318 } 4319 4320 if x, ok := n.(*cc.AttributeValue); ok && x.Token.Value == idAlias { 4321 switch y := x.ExpressionList.AssignmentExpression.Operand.Value().(type) { 4322 case cc.StringValue: 4323 r = cc.StringID(y) 4324 return false 4325 } 4326 } 4327 return true 4328 }) 4329 if r != 0 { 4330 return r 4331 } 4332 } 4333 return 0 4334 } 4335 4336 func (p *project) tld(f *function, n *cc.InitDeclarator, sep string, staticLocal bool) { 4337 d := n.Declarator 4338 if d.IsExtern() && d.Linkage == cc.External && !d.IsTypedefName { 4339 if alias := alias(attrs(d.Type())); alias != 0 { 4340 p.capi = append(p.capi, d.Name().String()) 4341 p.w("\n\nvar %s%s = %s\t// %v:\n", p.task.exportExterns, d.Name(), p.externs[alias].name, p.pos(d)) 4342 return 4343 } 4344 } 4345 4346 if _, ok := p.wanted[d]; !ok && !staticLocal { 4347 isFn := d.Type().Kind() == cc.Function 4348 if isFn && p.task.header && p.task.funcSig { 4349 if nm := d.Name().String(); !strings.HasPrefix(nm, "__") { 4350 p.w("\n\n") 4351 t := p.tlds[d] 4352 if t == nil { 4353 t = &tld{} 4354 t.name = p.tldScope.take(d.Name()) 4355 } 4356 p.functionSignature2(n, nil, d.Type(), t.name) 4357 } 4358 } 4359 return 4360 } 4361 4362 tld := p.tlds[d] 4363 if tld == nil { // Dead declaration. 4364 return 4365 } 4366 4367 t := d.Type() 4368 if d.IsTypedefName { 4369 p.checkAttributes(t) 4370 if _, ok := p.typedefsEmited[tld.name]; ok { 4371 return 4372 } 4373 4374 p.typedefsEmited[tld.name] = struct{}{} 4375 if t.Kind() != cc.Void { 4376 p.w("%stype %s = %s; /* %v */", sep, tld.name, p.typ(n, t), p.pos(d)) 4377 } 4378 return 4379 } 4380 4381 switch n.Case { 4382 case cc.InitDeclaratorDecl: // Declarator AttributeSpecifierList 4383 p.w("%svar %s %s\t/* %v: */", sep, tld.name, p.typ(n, t), p.pos(n)) 4384 switch t.Kind() { 4385 case cc.Struct, cc.Union: 4386 p.structs[t.Tag()].emit(p, nil) 4387 } 4388 case cc.InitDeclaratorInit: // Declarator AttributeSpecifierList '=' Initializer 4389 if d.IsStatic() && d.Read == 0 && d.Write == 1 && n.Initializer.IsConst() { // Initialized with no side effects and unused. 4390 break 4391 } 4392 4393 p.w("%svar %s ", sep, tld.name) 4394 if !isAggregateTypeOrUnion(d.Type()) { 4395 p.w("%s ", p.typ(n, d.Type())) 4396 } 4397 p.w("= ") 4398 p.initializer(f, n.Initializer, d.Type(), d.StorageClass, tld) 4399 p.w("; /* %v */", p.pos(d)) 4400 default: 4401 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 4402 } 4403 } 4404 4405 func (p *project) functionDefinition(n *cc.FunctionDefinition) { 4406 // DeclarationSpecifiers Declarator DeclarationList CompoundStatement 4407 if p.task.header && !p.task.funcSig { 4408 return 4409 } 4410 4411 if _, ok := p.sharedFns[n]; ok { 4412 if _, ok := p.sharedFnsEmitted[n]; ok { 4413 return 4414 } 4415 4416 p.sharedFnsEmitted[n] = struct{}{} 4417 } 4418 4419 d := n.Declarator 4420 if d.IsExtern() && d.Type().Inline() { 4421 // https://gcc.gnu.org/onlinedocs/gcc/Inline.html 4422 // 4423 // If you specify both inline and extern in the function definition, then the 4424 // definition is used only for inlining. In no case is the function compiled on 4425 // its own, not even if you refer to its address explicitly. Such an address 4426 // becomes an external reference, as if you had only declared the function, and 4427 // had not defined it. 4428 // 4429 // This combination of inline and extern has almost the effect of a macro. The 4430 // way to use it is to put a function definition in a header file with these 4431 // keywords, and put another copy of the definition (lacking inline and extern) 4432 // in a library file. The definition in the header file causes most calls to 4433 // the function to be inlined. If any uses of the function remain, they refer 4434 // to the single copy in the library. 4435 return 4436 } 4437 4438 name := d.Name().String() 4439 if _, ok := p.task.hide[name]; ok { 4440 return 4441 } 4442 4443 if p.isMain && d.Linkage == cc.External && d.Read == 0 && !d.AddressTaken && len(p.task.asts) == 1 { 4444 return 4445 } 4446 4447 if d.Linkage == cc.Internal && d.Read == 0 && !d.AddressTaken /*TODO- && strings.HasPrefix(name, "__") */ { 4448 return 4449 } 4450 4451 tld := p.tlds[d] 4452 if tld == nil { 4453 return 4454 } 4455 4456 p.fn = name 4457 4458 defer func() { p.fn = "" }() 4459 4460 f := newFunction(p, n) 4461 p.pass1 = true 4462 p.compoundStatement(f, n.CompoundStatement, "", false, false, 0) 4463 p.pass1 = false 4464 p.w("\n\n") 4465 p.functionDefinitionSignature(n, f, tld) 4466 if p.task.header && p.task.funcSig { 4467 return 4468 } 4469 4470 p.w(" ") 4471 comment := fmt.Sprintf("/* %v: */", p.pos(d)) 4472 if p.task.panicStubs { 4473 p.w("%s{ panic(%q) }", comment, tld.name) 4474 return 4475 } 4476 4477 brace := "{" 4478 if need := f.off; need != 0 { 4479 scope := f.blocks[n.CompoundStatement].scope 4480 f.bpName = scope.take(idBp) 4481 p.w("{%s\n%s := %s.Alloc(%d)\n", comment, f.bpName, f.tlsName, need) 4482 p.w("defer %s.Free(%d)\n", f.tlsName, need) 4483 for _, v := range d.Type().Parameters() { 4484 if local := f.locals[v.Declarator()]; local != nil && local.isPinned { // Pin it. 4485 p.w("*(*%s)(unsafe.Pointer(%s%s)) = %s\n", p.typ(v.Declarator(), paramTypeDecay(v.Declarator())), f.bpName, nonZeroUintptr(local.off), local.name) 4486 } 4487 } 4488 comment = "" 4489 brace = "" 4490 } 4491 if len(f.vlas) != 0 { 4492 p.w("%s%s\n", brace, comment) 4493 var vlas []*cc.Declarator 4494 for k := range f.vlas { 4495 vlas = append(vlas, k) 4496 } 4497 sort.Slice(vlas, func(i, j int) bool { 4498 return vlas[i].NameTok().Seq() < vlas[j].NameTok().Seq() 4499 }) 4500 for _, v := range vlas { 4501 local := f.locals[v] 4502 switch { 4503 case local.isPinned: 4504 panic(todo("", v.Position())) 4505 default: 4506 p.w("var %s uintptr // %v: %v\n", local.name, p.pos(v), v.Type()) 4507 } 4508 } 4509 switch { 4510 case len(vlas) == 1: 4511 p.w("defer %sXfree(%s, %s)\n", p.task.crt, f.tlsName, f.locals[vlas[0]].name) 4512 default: 4513 p.w("defer func() {\n") 4514 for _, v := range vlas { 4515 p.w("%sXfree(%s, %s)\n", p.task.crt, f.tlsName, f.locals[v].name) 4516 } 4517 p.w("\n}()\n") 4518 } 4519 } 4520 p.compoundStatement(f, n.CompoundStatement, comment, false, true, 0) 4521 p.w(";") 4522 p.flushLocalTaggesStructs() 4523 p.flushStaticTLDs() 4524 } 4525 4526 func (p *project) flushLocalTaggesStructs() { 4527 for _, v := range p.localTaggedStructs { 4528 v() 4529 } 4530 p.localTaggedStructs = nil 4531 } 4532 4533 func (p *project) flushStaticTLDs() { 4534 for _, v := range p.staticQueue { 4535 p.tld(nil, v, "\n", true) 4536 } 4537 p.staticQueue = nil 4538 } 4539 4540 func (p *project) compoundStatement(f *function, n *cc.CompoundStatement, scomment string, forceNoBraces, fnBody bool, mode exprMode) { 4541 if p.task.panicStubs { 4542 return 4543 } 4544 4545 // '{' BlockItemList '}' 4546 brace := (!n.IsJumpTarget() || n.Parent() == nil) && !forceNoBraces 4547 if brace && len(f.vlas) == 0 && (n.Parent() != nil || f.off == 0) { 4548 p.w("{%s", scomment) 4549 } 4550 if fnBody { 4551 p.instrument(n) 4552 } 4553 sv := f.block 4554 f.block = f.blocks[n] 4555 if f.block.topDecl { 4556 for _, v := range f.block.decls { 4557 p.declaration(f, v, true) 4558 } 4559 } 4560 var r *cc.JumpStatement 4561 for list := n.BlockItemList; list != nil; list = list.BlockItemList { 4562 m := mode 4563 if list.BlockItemList != nil { 4564 m = 0 4565 } 4566 r = p.blockItem(f, list.BlockItem, m) 4567 } 4568 if n.Parent() == nil && r == nil && f.rt.Kind() != cc.Void { 4569 p.w("\nreturn ") 4570 p.zeroValue(n, f.rt) 4571 } 4572 s := tidyComment("\n", &n.Token2) 4573 p.w("%s", s) 4574 if brace { 4575 if !strings.HasSuffix(s, "\n") { 4576 p.w("\n") 4577 } 4578 p.w("}") 4579 } 4580 f.block = sv 4581 } 4582 4583 func (p *project) zeroValue(n cc.Node, t cc.Type) { 4584 if t.IsScalarType() { 4585 p.w("%s(0)", p.typ(n, t)) 4586 return 4587 } 4588 4589 switch t.Kind() { 4590 case cc.Struct, cc.Union: 4591 p.w("%s{}", p.typ(n, t)) 4592 default: 4593 panic(todo("", t, t.Kind())) 4594 } 4595 } 4596 4597 func (p *project) blockItem(f *function, n *cc.BlockItem, mode exprMode) (r *cc.JumpStatement) { 4598 switch n.Case { 4599 case cc.BlockItemDecl: // Declaration 4600 p.declaration(f, n.Declaration, false) 4601 case cc.BlockItemStmt: // Statement 4602 r = p.statement(f, n.Statement, false, false, false, mode) 4603 p.w(";") 4604 if r == nil { 4605 p.instrument(n) 4606 } 4607 case cc.BlockItemLabel: // LabelDeclaration 4608 panic(todo("", p.pos(n))) 4609 p.w(";") 4610 case cc.BlockItemFuncDef: // DeclarationSpecifiers Declarator CompoundStatement 4611 p.err(n, "nested functions not supported") 4612 p.w(";") 4613 case cc.BlockItemPragma: // PragmaSTDC 4614 panic(todo("", p.pos(n))) 4615 p.w(";") 4616 default: 4617 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 4618 } 4619 return r 4620 } 4621 4622 func (p *project) instrument(n cc.Node) { 4623 if p.task.cover { 4624 p.w("%sCover();", p.task.crt) 4625 } 4626 if p.task.coverC { 4627 p.w("%sCoverC(%q);", p.task.crt, p.pos(n).String()+" "+p.fn) 4628 } 4629 if p.task.watch { 4630 p.w("%sWatch();", p.task.crt) 4631 } 4632 } 4633 4634 var dummyJumpStatement = &cc.JumpStatement{} 4635 4636 func (p *project) statement(f *function, n *cc.Statement, forceCompoundStmtBrace, forceNoBraces, switchBlock bool, mode exprMode) (r *cc.JumpStatement) { 4637 if forceCompoundStmtBrace { 4638 if f.switchCtx == inSwitchFirst && p.pauseCodegen { 4639 p.pauseCodegen = false 4640 p.w(" {") 4641 p.pauseCodegen = true 4642 } 4643 p.w(" {") 4644 if !switchBlock { 4645 p.instrument(n) 4646 } 4647 } 4648 switch n.Case { 4649 case cc.StatementLabeled: // LabeledStatement 4650 r = p.labeledStatement(f, n.LabeledStatement) 4651 case cc.StatementCompound: // CompoundStatement 4652 if !forceCompoundStmtBrace { 4653 p.w("%s", n.CompoundStatement.Token.Sep) 4654 } 4655 if f.hasJumps { 4656 forceNoBraces = true 4657 } 4658 p.compoundStatement(f, n.CompoundStatement, "", forceCompoundStmtBrace || forceNoBraces, false, 0) 4659 case cc.StatementExpr: // ExpressionStatement 4660 if mode != 0 { 4661 p.w("return ") 4662 e := n.ExpressionStatement.Expression 4663 p.expression(f, e, e.Operand.Type(), exprValue, 0) 4664 r = dummyJumpStatement 4665 break 4666 } 4667 4668 p.expressionStatement(f, n.ExpressionStatement) 4669 case cc.StatementSelection: // SelectionStatement 4670 p.selectionStatement(f, n.SelectionStatement) 4671 case cc.StatementIteration: // IterationStatement 4672 p.iterationStatement(f, n.IterationStatement) 4673 case cc.StatementJump: // JumpStatement 4674 r = p.jumpStatement(f, n.JumpStatement) 4675 case cc.StatementAsm: // AsmStatement 4676 // AsmStatement: 4677 // Asm AttributeSpecifierList ';' 4678 // Asm: 4679 // "__asm__" AsmQualifierList '(' STRINGLITERAL AsmArgList ')' 4680 if n.AsmStatement.Asm.Token3.Value == 0 && n.AsmStatement.Asm.AsmArgList == nil { 4681 break 4682 } 4683 4684 p.w("panic(`%s: assembler statements not supported`)", n.Position()) 4685 default: 4686 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 4687 } 4688 if forceCompoundStmtBrace { 4689 // We need to do this, to guarantee that we always close the brace is we opened it 4690 if f.switchCtx == inSwitchFirst && p.pauseCodegen { 4691 p.pauseCodegen = false 4692 p.w("}") 4693 p.pauseCodegen = true 4694 } 4695 p.w("}") 4696 } 4697 return r 4698 } 4699 4700 func (p *project) jumpStatement(f *function, n *cc.JumpStatement) (r *cc.JumpStatement) { 4701 p.w("%s", tidyComment("\n", n)) 4702 if _, ok := n.Context().(*cc.SelectionStatement); ok && f.ifCtx == nil { 4703 switch f.switchCtx { 4704 case inSwitchCase: 4705 f.switchCtx = inSwitchSeenBreak 4706 case inSwitchSeenBreak: 4707 // nop but TODO 4708 case inSwitchFlat: 4709 // ok 4710 default: 4711 panic(todo("", n.Position(), f.switchCtx)) 4712 } 4713 } 4714 4715 switch n.Case { 4716 case cc.JumpStatementGoto: // "goto" IDENTIFIER ';' 4717 p.w("goto %s", f.labelNames[n.Token2.Value]) 4718 case cc.JumpStatementGotoExpr: // "goto" '*' Expression ';' 4719 panic(todo("", p.pos(n))) 4720 case cc.JumpStatementContinue: // "continue" ';' 4721 switch { 4722 case f.continueCtx != 0: 4723 p.w("goto __%d", f.continueCtx) 4724 default: 4725 p.w("continue") 4726 } 4727 case cc.JumpStatementBreak: // "break" ';' 4728 switch { 4729 case f.breakCtx != 0: 4730 p.w("goto __%d", f.breakCtx) 4731 default: 4732 p.w("break") 4733 } 4734 case cc.JumpStatementReturn: // "return" Expression ';' 4735 r = n 4736 switch { 4737 case f.rt != nil && f.rt.Kind() == cc.Void: 4738 if n.Expression != nil { 4739 p.expression(f, n.Expression, n.Expression.Operand.Type(), exprVoid, 0) 4740 p.w(";") 4741 } 4742 p.w("return") 4743 case f.rt != nil && f.rt.Kind() != cc.Void: 4744 if n.Expression != nil { 4745 p.expression(f, n.Expression, f.rt, exprCondReturn, 0) 4746 break 4747 } 4748 4749 p.w("return ") 4750 p.zeroValue(n, f.rt) 4751 default: 4752 if n.Expression != nil { 4753 p.expression(f, n.Expression, n.Expression.Operand.Type(), exprVoid, 0) 4754 p.w(";") 4755 } 4756 p.w("return") 4757 } 4758 default: 4759 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 4760 } 4761 return r 4762 } 4763 4764 func (p *project) expression(f *function, n *cc.Expression, t cc.Type, mode exprMode, flags flags) { 4765 switch mode { 4766 case exprVoid: 4767 p.expressionVoid(f, n, t, mode, flags) 4768 case exprValue, exprCondReturn, exprCondInit: 4769 p.expressionValue(f, n, t, mode, flags) 4770 case exprBool: 4771 p.expressionBool(f, n, t, mode, flags) 4772 case exprAddrOf: 4773 p.expressionAddrOf(f, n, t, mode, flags) 4774 case exprPSelect: 4775 p.expressionPSelect(f, n, t, mode, flags) 4776 case exprLValue: 4777 p.expressionLValue(f, n, t, mode, flags) 4778 case exprFunc: 4779 p.expressionFunc(f, n, t, mode, flags) 4780 case exprSelect: 4781 p.expressionSelect(f, n, t, mode, flags) 4782 case exprDecay: 4783 p.expressionDecay(f, n, t, mode, flags) 4784 default: 4785 panic(todo("", n.Position(), mode)) 4786 } 4787 } 4788 4789 func (p *project) expressionDecay(f *function, n *cc.Expression, t cc.Type, mode exprMode, flags flags) { 4790 switch n.Case { 4791 case cc.ExpressionAssign: // AssignmentExpression 4792 p.assignmentExpression(f, n.AssignmentExpression, t, mode, flags) 4793 case cc.ExpressionComma: // Expression ',' AssignmentExpression 4794 p.w("func() uintptr {") 4795 p.expression(f, n.Expression, n.Expression.Operand.Type(), exprVoid, flags) 4796 p.w("; return ") 4797 p.assignmentExpression(f, n.AssignmentExpression, t, mode, flags) 4798 p.w("}()") 4799 default: 4800 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 4801 } 4802 } 4803 4804 func (p *project) expressionSelect(f *function, n *cc.Expression, t cc.Type, mode exprMode, flags flags) { 4805 switch n.Case { 4806 case cc.ExpressionAssign: // AssignmentExpression 4807 p.assignmentExpression(f, n.AssignmentExpression, t, mode, flags) 4808 case cc.ExpressionComma: // Expression ',' AssignmentExpression 4809 panic(todo("", p.pos(n))) 4810 default: 4811 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 4812 } 4813 } 4814 4815 func (p *project) expressionFunc(f *function, n *cc.Expression, t cc.Type, mode exprMode, flags flags) { 4816 switch n.Case { 4817 case cc.ExpressionAssign: // AssignmentExpression 4818 p.assignmentExpression(f, n.AssignmentExpression, t, mode, flags) 4819 case cc.ExpressionComma: // Expression ',' AssignmentExpression 4820 panic(todo("", p.pos(n))) 4821 default: 4822 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 4823 } 4824 } 4825 4826 func (p *project) expressionLValue(f *function, n *cc.Expression, t cc.Type, mode exprMode, flags flags) { 4827 switch n.Case { 4828 case cc.ExpressionAssign: // AssignmentExpression 4829 p.assignmentExpression(f, n.AssignmentExpression, t, mode, flags) 4830 case cc.ExpressionComma: // Expression ',' AssignmentExpression 4831 panic(todo("", p.pos(n))) 4832 default: 4833 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 4834 } 4835 } 4836 4837 func (p *project) expressionPSelect(f *function, n *cc.Expression, t cc.Type, mode exprMode, flags flags) { 4838 switch n.Case { 4839 case cc.ExpressionAssign: // AssignmentExpression 4840 p.assignmentExpression(f, n.AssignmentExpression, t, mode, flags) 4841 case cc.ExpressionComma: // Expression ',' AssignmentExpression 4842 panic(todo("", p.pos(n))) 4843 default: 4844 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 4845 } 4846 } 4847 4848 func (p *project) expressionAddrOf(f *function, n *cc.Expression, t cc.Type, mode exprMode, flags flags) { 4849 switch n.Case { 4850 case cc.ExpressionAssign: // AssignmentExpression 4851 p.assignmentExpression(f, n.AssignmentExpression, t, mode, flags) 4852 case cc.ExpressionComma: // Expression ',' AssignmentExpression 4853 p.w(" func() uintptr {") 4854 p.expression(f, n.Expression, n.Expression.Operand.Type(), exprVoid, flags) 4855 p.w("; return ") 4856 p.assignmentExpression(f, n.AssignmentExpression, t, mode, flags) 4857 p.w("}()") 4858 default: 4859 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 4860 } 4861 } 4862 4863 func (p *project) expressionBool(f *function, n *cc.Expression, t cc.Type, mode exprMode, flags flags) { 4864 switch n.Case { 4865 case cc.ExpressionAssign: // AssignmentExpression 4866 p.assignmentExpression(f, n.AssignmentExpression, t, mode, flags) 4867 case cc.ExpressionComma: // Expression ',' AssignmentExpression 4868 p.w("func() bool {") 4869 p.expression(f, n.Expression, n.Expression.Operand.Type(), exprVoid, flags) 4870 p.w("; return ") 4871 p.assignmentExpression(f, n.AssignmentExpression, n.AssignmentExpression.Operand.Type(), mode, flags) 4872 p.w("}()") 4873 default: 4874 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 4875 } 4876 } 4877 4878 func (p *project) expressionValue(f *function, n *cc.Expression, t cc.Type, mode exprMode, flags flags) { 4879 switch n.Case { 4880 case cc.ExpressionAssign: // AssignmentExpression 4881 p.assignmentExpression(f, n.AssignmentExpression, t, mode, flags) 4882 case cc.ExpressionComma: // Expression ',' AssignmentExpression 4883 if mode == exprCondReturn { 4884 p.expression(f, n.Expression, n.Expression.Operand.Type(), exprVoid, flags) 4885 p.w("; return ") 4886 p.assignmentExpression(f, n.AssignmentExpression, n.AssignmentExpression.Operand.Type(), exprValue, flags) 4887 return 4888 } 4889 4890 switch { 4891 case n.AssignmentExpression.Operand.Type().Kind() == cc.Array: 4892 p.expressionDecay(f, n, t, exprDecay, flags) 4893 default: 4894 defer p.w("%s", p.convertType(n, n.Operand.Type(), t, flags)) 4895 p.w("func() %v {", p.typ(n, n.AssignmentExpression.Operand.Type())) 4896 p.expression(f, n.Expression, n.Expression.Operand.Type(), exprVoid, flags) 4897 p.w("; return ") 4898 p.assignmentExpression(f, n.AssignmentExpression, n.AssignmentExpression.Operand.Type(), exprValue, flags) 4899 p.w("}()") 4900 } 4901 default: 4902 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 4903 } 4904 } 4905 4906 func (p *project) expressionVoid(f *function, n *cc.Expression, t cc.Type, mode exprMode, flags flags) { 4907 switch n.Case { 4908 case cc.ExpressionAssign: // AssignmentExpression 4909 p.assignmentExpression(f, n.AssignmentExpression, t, mode, flags) 4910 case cc.ExpressionComma: // Expression ',' AssignmentExpression 4911 p.expression(f, n.Expression, t, mode, flags) 4912 p.w(";") 4913 p.assignmentExpression(f, n.AssignmentExpression, t, mode, flags) 4914 default: 4915 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 4916 } 4917 } 4918 4919 func (p *project) opKind(f *function, d declarator, t cc.Type) opKind { 4920 switch { 4921 case p.isArrayParameter(d, t): 4922 return opArrayParameter 4923 case !p.pass1 && p.isArray(f, d, t): 4924 return opArray 4925 case t.Kind() == cc.Union: 4926 return opUnion 4927 case t.Kind() == cc.Struct: 4928 return opStruct 4929 case t.IsBitFieldType(): 4930 return opBitfield 4931 case t.Kind() == cc.Function: 4932 return opFunction 4933 default: 4934 return opNormal 4935 } 4936 } 4937 4938 func (p *project) assignmentExpression(f *function, n *cc.AssignmentExpression, t cc.Type, mode exprMode, flags flags) { 4939 switch mode { 4940 case exprVoid: 4941 p.assignmentExpressionVoid(f, n, t, mode, flags) 4942 case exprValue, exprCondReturn, exprCondInit: 4943 p.assignmentExpressionValue(f, n, t, mode, flags) 4944 case exprAddrOf: 4945 p.assignmentExpressionAddrOf(f, n, t, mode, flags) 4946 case exprBool: 4947 p.assignmentExpressionBool(f, n, t, mode, flags) 4948 case exprLValue: 4949 p.assignmentExpressionLValue(f, n, t, mode, flags) 4950 case exprPSelect: 4951 p.assignmentExpressionPSelect(f, n, t, mode, flags) 4952 case exprFunc: 4953 p.assignmentExpressionFunc(f, n, t, mode, flags) 4954 case exprSelect: 4955 p.assignmentExpressionSelect(f, n, t, mode, flags) 4956 case exprDecay: 4957 p.assignmentExpressionDecay(f, n, t, mode, flags) 4958 default: 4959 panic(todo("", n.Position(), mode)) 4960 } 4961 } 4962 4963 func (p *project) assignmentExpressionDecay(f *function, n *cc.AssignmentExpression, t cc.Type, mode exprMode, flags flags) { 4964 switch n.Case { 4965 case cc.AssignmentExpressionCond: // ConditionalExpression 4966 p.conditionalExpression(f, n.ConditionalExpression, t, mode, flags) 4967 case cc.AssignmentExpressionAssign: // UnaryExpression '=' AssignmentExpression 4968 panic(todo("", p.pos(n))) 4969 case cc.AssignmentExpressionMul: // UnaryExpression "*=" AssignmentExpression 4970 panic(todo("", p.pos(n))) 4971 case cc.AssignmentExpressionDiv: // UnaryExpression "/=" AssignmentExpression 4972 panic(todo("", p.pos(n))) 4973 case cc.AssignmentExpressionMod: // UnaryExpression "%=" AssignmentExpression 4974 panic(todo("", p.pos(n))) 4975 case cc.AssignmentExpressionAdd: // UnaryExpression "+=" AssignmentExpression 4976 panic(todo("", p.pos(n))) 4977 case cc.AssignmentExpressionSub: // UnaryExpression "-=" AssignmentExpression 4978 panic(todo("", p.pos(n))) 4979 case cc.AssignmentExpressionLsh: // UnaryExpression "<<= AssignmentExpression 4980 panic(todo("", p.pos(n))) 4981 case cc.AssignmentExpressionRsh: // UnaryExpression ">>=" AssignmentExpression 4982 panic(todo("", p.pos(n))) 4983 case cc.AssignmentExpressionAnd: // UnaryExpression "&=" AssignmentExpression 4984 panic(todo("", p.pos(n))) 4985 case cc.AssignmentExpressionXor: // UnaryExpression "^=" AssignmentExpression 4986 panic(todo("", p.pos(n))) 4987 case cc.AssignmentExpressionOr: // UnaryExpression "|=" AssignmentExpression 4988 panic(todo("", p.pos(n))) 4989 default: 4990 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 4991 } 4992 } 4993 4994 func (p *project) assignmentExpressionSelect(f *function, n *cc.AssignmentExpression, t cc.Type, mode exprMode, flags flags) { 4995 switch n.Case { 4996 case cc.AssignmentExpressionCond: // ConditionalExpression 4997 p.conditionalExpression(f, n.ConditionalExpression, t, mode, flags) 4998 case cc.AssignmentExpressionAssign: // UnaryExpression '=' AssignmentExpression 4999 panic(todo("", p.pos(n))) 5000 case cc.AssignmentExpressionMul: // UnaryExpression "*=" AssignmentExpression 5001 panic(todo("", p.pos(n))) 5002 case cc.AssignmentExpressionDiv: // UnaryExpression "/=" AssignmentExpression 5003 panic(todo("", p.pos(n))) 5004 case cc.AssignmentExpressionMod: // UnaryExpression "%=" AssignmentExpression 5005 panic(todo("", p.pos(n))) 5006 case cc.AssignmentExpressionAdd: // UnaryExpression "+=" AssignmentExpression 5007 panic(todo("", p.pos(n))) 5008 case cc.AssignmentExpressionSub: // UnaryExpression "-=" AssignmentExpression 5009 panic(todo("", p.pos(n))) 5010 case cc.AssignmentExpressionLsh: // UnaryExpression "<<=" AssignmentExpression 5011 panic(todo("", p.pos(n))) 5012 case cc.AssignmentExpressionRsh: // UnaryExpression ">>=" AssignmentExpression 5013 panic(todo("", p.pos(n))) 5014 case cc.AssignmentExpressionAnd: // UnaryExpression "&=" AssignmentExpression 5015 panic(todo("", p.pos(n))) 5016 case cc.AssignmentExpressionXor: // UnaryExpression "^=" AssignmentExpression 5017 panic(todo("", p.pos(n))) 5018 case cc.AssignmentExpressionOr: // UnaryExpression "|=" AssignmentExpression 5019 panic(todo("", p.pos(n))) 5020 default: 5021 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 5022 } 5023 } 5024 5025 func (p *project) assignmentExpressionFunc(f *function, n *cc.AssignmentExpression, t cc.Type, mode exprMode, flags flags) { 5026 switch n.Case { 5027 case cc.AssignmentExpressionCond: // ConditionalExpression 5028 p.conditionalExpression(f, n.ConditionalExpression, t, mode, flags) 5029 case cc.AssignmentExpressionAssign: // UnaryExpression '=' AssignmentExpression 5030 panic(todo("", p.pos(n))) 5031 case cc.AssignmentExpressionMul: // UnaryExpression "*=" AssignmentExpression 5032 panic(todo("", p.pos(n))) 5033 case cc.AssignmentExpressionDiv: // UnaryExpression "/=" AssignmentExpression 5034 panic(todo("", p.pos(n))) 5035 case cc.AssignmentExpressionMod: // UnaryExpression "%=" AssignmentExpression 5036 panic(todo("", p.pos(n))) 5037 case cc.AssignmentExpressionAdd: // UnaryExpression "+=" AssignmentExpression 5038 panic(todo("", p.pos(n))) 5039 case cc.AssignmentExpressionSub: // UnaryExpression "-=" AssignmentExpression 5040 panic(todo("", p.pos(n))) 5041 case cc.AssignmentExpressionLsh: // UnaryExpremode, ssion "<<= 5042 panic(todo("", p.pos(n))) 5043 case cc.AssignmentExpressionRsh: // UnaryExpression ">>=" AssignmentExpression 5044 panic(todo("", p.pos(n))) 5045 case cc.AssignmentExpressionAnd: // UnaryExpression "&=" AssignmentExpression 5046 panic(todo("", p.pos(n))) 5047 case cc.AssignmentExpressionXor: // UnaryExpression "^=" AssignmentExpression 5048 panic(todo("", p.pos(n))) 5049 case cc.AssignmentExpressionOr: // UnaryExpression "|=" AssignmentExpression 5050 panic(todo("", p.pos(n))) 5051 default: 5052 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 5053 } 5054 } 5055 5056 func (p *project) assignmentExpressionPSelect(f *function, n *cc.AssignmentExpression, t cc.Type, mode exprMode, flags flags) { 5057 switch n.Case { 5058 case cc.AssignmentExpressionCond: // ConditionalExpression 5059 p.conditionalExpression(f, n.ConditionalExpression, t, mode, flags) 5060 case cc.AssignmentExpressionAssign: // UnaryExpression '=' AssignmentExpression 5061 p.w("(*%s)(unsafe.Pointer(", p.typ(n, n.AssignmentExpression.Operand.Type().Elem())) 5062 p.assignmentExpression(f, n, t, exprValue, flags) 5063 p.w("))") 5064 case cc.AssignmentExpressionMul: // UnaryExpression "*=" AssignmentExpression 5065 panic(todo("", p.pos(n))) 5066 case cc.AssignmentExpressionDiv: // UnaryExpression "/=" AssignmentExpression 5067 panic(todo("", p.pos(n))) 5068 case cc.AssignmentExpressionMod: // UnaryExpression "%=" AssignmentExpression 5069 panic(todo("", p.pos(n))) 5070 case cc.AssignmentExpressionAdd: // UnaryExpression "+=" AssignmentExpression 5071 panic(todo("", p.pos(n))) 5072 case cc.AssignmentExpressionSub: // UnaryExpression "-=" AssignmentExpression 5073 panic(todo("", p.pos(n))) 5074 case cc.AssignmentExpressionLsh: // UnaryExpression "<<=" AssignmentExpression 5075 panic(todo("", p.pos(n))) 5076 case cc.AssignmentExpressionRsh: // UnaryExpression ">>=" AssignmentExpression 5077 panic(todo("", p.pos(n))) 5078 case cc.AssignmentExpressionAnd: // UnaryExpression "&=" AssignmentExpression 5079 panic(todo("", p.pos(n))) 5080 case cc.AssignmentExpressionXor: // UnaryExpression "^=" AssignmentExpression 5081 panic(todo("", p.pos(n))) 5082 case cc.AssignmentExpressionOr: // UnaryExpression "|=" AssignmentExpression 5083 panic(todo("", p.pos(n))) 5084 default: 5085 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 5086 } 5087 } 5088 5089 func (p *project) assignmentExpressionLValue(f *function, n *cc.AssignmentExpression, t cc.Type, mode exprMode, flags flags) { 5090 switch n.Case { 5091 case cc.AssignmentExpressionCond: // ConditionalExpression 5092 p.conditionalExpression(f, n.ConditionalExpression, t, mode, flags) 5093 case cc.AssignmentExpressionAssign: // UnaryExpression '=' AssignmentExpression 5094 panic(todo("", p.pos(n))) 5095 case cc.AssignmentExpressionMul: // UnaryExpression "*=" AssignmentExpression 5096 panic(todo("", p.pos(n))) 5097 case cc.AssignmentExpressionDiv: // UnaryExpression "/=" AssignmentExpression 5098 panic(todo("", p.pos(n))) 5099 case cc.AssignmentExpressionMod: // UnaryExpression "%=" AssignmentExpression 5100 panic(todo("", p.pos(n))) 5101 case cc.AssignmentExpressionAdd: // UnaryExpression "+=" AssignmentExpression 5102 panic(todo("", p.pos(n))) 5103 case cc.AssignmentExpressionSub: // UnaryExpression "-=" AssignmentExpression 5104 panic(todo("", p.pos(n))) 5105 case cc.AssignmentExpressionLsh: // UnaryExpression "<<=" AssignmentExpression 5106 panic(todo("", p.pos(n))) 5107 case cc.AssignmentExpressionRsh: // UnaryExpression ">>=" AssignmentExpression 5108 panic(todo("", p.pos(n))) 5109 case cc.AssignmentExpressionAnd: // UnaryExpression "&=" AssignmentExpression 5110 panic(todo("", p.pos(n))) 5111 case cc.AssignmentExpressionXor: // UnaryExpression "^=" AssignmentExpression 5112 panic(todo("", p.pos(n))) 5113 case cc.AssignmentExpressionOr: // UnaryExpression "|=" AssignmentExpression 5114 panic(todo("", p.pos(n))) 5115 default: 5116 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 5117 } 5118 } 5119 5120 func (p *project) assignmentExpressionBool(f *function, n *cc.AssignmentExpression, t cc.Type, mode exprMode, flags flags) { 5121 switch n.Case { 5122 case cc.AssignmentExpressionCond: // ConditionalExpression 5123 p.conditionalExpression(f, n.ConditionalExpression, t, mode, flags) 5124 default: 5125 // case cc.AssignmentExpressionAssign: // UnaryExpression '=' AssignmentExpression 5126 // case cc.AssignmentExpressionMul: // UnaryExpression "*=" AssignmentExpression 5127 // case cc.AssignmentExpressionDiv: // UnaryExpression "/=" AssignmentExpression 5128 // case cc.AssignmentExpressionMod: // UnaryExpression "%=" AssignmentExpression 5129 // case cc.AssignmentExpressionAdd: // UnaryExpression "+=" AssignmentExpression 5130 // case cc.AssignmentExpressionSub: // UnaryExpression "-=" AssignmentExpression 5131 // case cc.AssignmentExpressionLsh: // UnaryExpression "<<=" AssignmentExpression 5132 // case cc.AssignmentExpressionRsh: // UnaryExpression ">>=" AssignmentExpression 5133 // case cc.AssignmentExpressionAnd: // UnaryExpression "&=" AssignmentExpression 5134 // case cc.AssignmentExpressionXor: // UnaryExpression "^=" AssignmentExpression 5135 // case cc.AssignmentExpressionOr: // UnaryExpression "|=" AssignmentExpression 5136 p.w("(") 5137 defer p.w(")") 5138 defer p.w(" != 0 ") 5139 p.assignmentExpression(f, n, t, exprValue, flags) 5140 } 5141 } 5142 5143 func (p *project) assignmentExpressionAddrOf(f *function, n *cc.AssignmentExpression, t cc.Type, mode exprMode, flags flags) { 5144 switch n.Case { 5145 case cc.AssignmentExpressionCond: // ConditionalExpression 5146 p.conditionalExpression(f, n.ConditionalExpression, t, mode, flags) 5147 case cc.AssignmentExpressionAssign: // UnaryExpression '=' AssignmentExpression 5148 p.assignmentExpressionValueAddrOf(f, n, t, mode, flags) 5149 case cc.AssignmentExpressionMul: // UnaryExpression "*=" AssignmentExpression 5150 panic(todo("", p.pos(n))) 5151 case cc.AssignmentExpressionDiv: // UnaryExpression "/=" AssignmentExpression 5152 panic(todo("", p.pos(n))) 5153 case cc.AssignmentExpressionMod: // UnaryExpression "%=" AssignmentExpression 5154 panic(todo("", p.pos(n))) 5155 case cc.AssignmentExpressionAdd: // UnaryExpression "+=" AssignmentExpression 5156 panic(todo("", p.pos(n))) 5157 case cc.AssignmentExpressionSub: // UnaryExpression "-=" AssignmentExpression 5158 panic(todo("", p.pos(n))) 5159 case cc.AssignmentExpressionLsh: // UnaryExpression "<<=" AssignmentExpression 5160 panic(todo("", p.pos(n))) 5161 case cc.AssignmentExpressionRsh: // UnaryExpression ">>=" AssignmentExpression 5162 panic(todo("", p.pos(n))) 5163 case cc.AssignmentExpressionAnd: // UnaryExpression "&=" AssignmentExpression 5164 panic(todo("", p.pos(n))) 5165 case cc.AssignmentExpressionXor: // UnaryExpression "^=" AssignmentExpression 5166 panic(todo("", p.pos(n))) 5167 case cc.AssignmentExpressionOr: // UnaryExpression "|=" AssignmentExpression 5168 panic(todo("", p.pos(n))) 5169 default: 5170 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 5171 } 5172 } 5173 5174 func (p *project) assignmentExpressionValueAddrOf(f *function, n *cc.AssignmentExpression, t cc.Type, mode exprMode, flags flags) { 5175 // UnaryExpression '=' AssignmentExpression 5176 if mode == exprCondReturn { 5177 panic(todo("", p.pos(n))) 5178 } 5179 5180 lhs := n.UnaryExpression 5181 switch k := p.opKind(f, lhs, lhs.Operand.Type()); k { 5182 case opStruct, opUnion: 5183 p.assignmentExpressionValueAssignStructAddrof(f, n, n.Operand.Type(), mode, flags) 5184 default: 5185 panic(todo("", n.Position(), k)) 5186 } 5187 } 5188 5189 func (p *project) assignmentExpressionValueAssignStructAddrof(f *function, n *cc.AssignmentExpression, t cc.Type, mode exprMode, flags flags) { 5190 // UnaryExpression '=' AssignmentExpression 5191 lhs := n.UnaryExpression.Operand.Type() 5192 rhs := n.AssignmentExpression.Operand.Type() 5193 if lhs.Kind() == cc.Array || rhs.Kind() == cc.Array { 5194 panic(todo("", p.pos(n))) 5195 } 5196 5197 if d := n.UnaryExpression.Declarator(); d != nil { 5198 if local := f.locals[d]; local != nil { 5199 if local.isPinned { 5200 if !p.pass1 { 5201 p.w("%sXmemmove(tls, ", p.task.crt) 5202 p.unaryExpression(f, n.UnaryExpression, lhs, exprAddrOf, flags) 5203 p.w(", ") 5204 p.assignmentExpression(f, n.AssignmentExpression, rhs, exprAddrOf, flags) 5205 p.w(", %d)", lhs.Size()) 5206 return 5207 } 5208 } 5209 5210 if !p.pass1 { 5211 panic(todo("", p.pos(n))) 5212 } 5213 } 5214 } 5215 5216 p.w("%sXmemmove(tls, ", p.task.crt) 5217 p.unaryExpression(f, n.UnaryExpression, lhs, exprAddrOf, flags) 5218 p.w(", ") 5219 p.assignmentExpression(f, n.AssignmentExpression, rhs, exprAddrOf, flags) 5220 p.w(", %d)", lhs.Size()) 5221 } 5222 5223 func (p *project) assignmentExpressionValue(f *function, n *cc.AssignmentExpression, t cc.Type, mode exprMode, flags flags) { 5224 switch n.Case { 5225 case cc.AssignmentExpressionCond: // ConditionalExpression 5226 p.conditionalExpression(f, n.ConditionalExpression, t, mode, flags) 5227 case cc.AssignmentExpressionAssign: // UnaryExpression '=' AssignmentExpression 5228 p.assignmentExpressionValueAssign(f, n, t, mode, flags) 5229 case cc.AssignmentExpressionMul: // UnaryExpression "*=" AssignmentExpression 5230 p.assignOp(f, n, t, mode, "*", "Mul", flags) 5231 case cc.AssignmentExpressionDiv: // UnaryExpression "/=" AssignmentExpression 5232 p.assignOp(f, n, t, mode, "/", "Div", flags) 5233 case cc.AssignmentExpressionMod: // UnaryExpression "%=" AssignmentExpression 5234 p.assignOp(f, n, t, mode, "%", "Rem", flags) 5235 case cc.AssignmentExpressionAdd: // UnaryExpression "+=" AssignmentExpression 5236 p.assignOp(f, n, t, mode, "+", "Add", flags) 5237 case cc.AssignmentExpressionSub: // UnaryExpression "-=" AssignmentExpression 5238 p.assignOp(f, n, t, mode, "-", "Sub", flags) 5239 case cc.AssignmentExpressionLsh: // UnaryExpremode, ssion "<<= 5240 p.assignOp(f, n, t, mode, "<<", "Shl", flags) 5241 case cc.AssignmentExpressionRsh: // UnaryExpression ">>=" AssignmentExpression 5242 p.assignOp(f, n, t, mode, ">>", "Shr", flags) 5243 case cc.AssignmentExpressionAnd: // UnaryExpression "&=" AssignmentExpression 5244 p.assignOp(f, n, t, mode, "&", "And", flags) 5245 case cc.AssignmentExpressionXor: // UnaryExpression "^=" AssignmentExpression 5246 p.assignOp(f, n, t, mode, "^", "Xor", flags) 5247 case cc.AssignmentExpressionOr: // UnaryExpression "|=" AssignmentExpression 5248 p.assignOp(f, n, t, mode, "|", "Or", flags) 5249 default: 5250 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 5251 } 5252 } 5253 5254 func (p *project) assignmentExpressionValueAssign(f *function, n *cc.AssignmentExpression, t cc.Type, mode exprMode, flags flags) { 5255 // UnaryExpression '=' AssignmentExpression 5256 if mode == exprCondReturn { 5257 p.w("return ") 5258 } 5259 lhs := n.UnaryExpression 5260 switch k := p.opKind(f, lhs, lhs.Operand.Type()); k { 5261 case opNormal: 5262 p.assignmentExpressionValueAssignNormal(f, n, t, mode, flags) 5263 case opBitfield: 5264 p.assignmentExpressionValueAssignBitfield(f, n, t, mode, flags) 5265 case opStruct, opUnion: 5266 p.assignmentExpressionValueAssignStruct(f, n, t, mode, flags) 5267 default: 5268 panic(todo("", n.Position(), k)) 5269 } 5270 } 5271 5272 func (p *project) assignmentExpressionValueAssignStruct(f *function, n *cc.AssignmentExpression, t cc.Type, mode exprMode, flags flags) { 5273 // UnaryExpression '=' AssignmentExpression 5274 lhs := n.UnaryExpression.Operand.Type() 5275 rhs := n.AssignmentExpression.Operand.Type() 5276 if lhs.Kind() == cc.Array || rhs.Kind() == cc.Array { 5277 panic(todo("", p.pos(n))) 5278 } 5279 5280 p.w(" func() %s { __v := ", p.typ(n, lhs)) 5281 p.assignmentExpression(f, n.AssignmentExpression, rhs, exprValue, flags) 5282 p.w(";") 5283 p.unaryExpression(f, n.UnaryExpression, lhs, exprLValue, flags) 5284 p.w(" = __v; return __v}()") 5285 } 5286 5287 func (p *project) assignmentExpressionValueAssignBitfield(f *function, n *cc.AssignmentExpression, t cc.Type, mode exprMode, flags flags) { 5288 if d := n.UnaryExpression.Declarator(); d != nil { 5289 panic(todo("", p.pos(n))) 5290 } 5291 5292 lhs := n.UnaryExpression 5293 lt := lhs.Operand.Type() 5294 bf := lt.BitField() 5295 defer p.w("%s", p.convertType(n, lt, t, flags)) 5296 p.w("%sAssignBitFieldPtr%d%s(", p.task.crt, bf.BitFieldBlockWidth(), p.bfHelperType(lt)) 5297 p.unaryExpression(f, lhs, lt, exprAddrOf, flags) 5298 p.w(", ") 5299 p.assignmentExpression(f, n.AssignmentExpression, lt, exprValue, flags) 5300 p.w(", %d, %d, %#x)", bf.BitFieldWidth(), bf.BitFieldOffset(), bf.Mask()) 5301 } 5302 5303 func (p *project) assignmentExpressionValueAssignNormal(f *function, n *cc.AssignmentExpression, t cc.Type, mode exprMode, flags flags) { 5304 if d := n.UnaryExpression.Declarator(); d != nil { 5305 if !d.Type().IsScalarType() { 5306 panic(todo("", p.pos(n))) 5307 } 5308 5309 if local := f.locals[d]; local != nil { 5310 if local.isPinned { 5311 defer p.w(")%s", p.convertType(n, d.Type(), t, flags)) 5312 p.w("%sAssignPtr%s(", p.task.crt, p.helperType(d, d.Type())) 5313 p.w("%s%s /* %s */", f.bpName, nonZeroUintptr(local.off), local.name) 5314 p.w(", ") 5315 p.assignmentExpression(f, n.AssignmentExpression, n.UnaryExpression.Operand.Type(), exprValue, flags) 5316 return 5317 } 5318 5319 defer p.w(")%s", p.convertType(n, d.Type(), t, flags)) 5320 p.w("%sAssign%s(&%s, ", p.task.crt, p.helperType(n, d.Type()), local.name) 5321 p.assignmentExpression(f, n.AssignmentExpression, n.UnaryExpression.Operand.Type(), exprValue, flags) 5322 return 5323 } 5324 } 5325 5326 defer p.w(")%s", p.convertType(n, n.UnaryExpression.Operand.Type(), t, flags)) 5327 p.w("%sAssignPtr%s(", p.task.crt, p.helperType(n, n.UnaryExpression.Operand.Type())) 5328 p.unaryExpression(f, n.UnaryExpression, n.UnaryExpression.Operand.Type(), exprAddrOf, flags) 5329 p.w(", ") 5330 p.assignmentExpression(f, n.AssignmentExpression, n.UnaryExpression.Operand.Type(), exprValue, flags) 5331 } 5332 5333 func (p *project) assignmentExpressionVoid(f *function, n *cc.AssignmentExpression, t cc.Type, mode exprMode, flags flags) { 5334 switch n.Case { 5335 case cc.AssignmentExpressionCond: // ConditionalExpression 5336 p.conditionalExpression(f, n.ConditionalExpression, t, mode, flags) 5337 case cc.AssignmentExpressionAssign: // UnaryExpression '=' AssignmentExpression 5338 d := n.UnaryExpression.Declarator() 5339 lhs := n.UnaryExpression 5340 lt := lhs.Operand.Type() 5341 sv := f.condInitPrefix 5342 switch k := p.opKind(f, lhs, lt); k { 5343 case opArrayParameter: 5344 lt = lt.Decay() 5345 fallthrough 5346 case opNormal, opStruct: 5347 mode = exprValue 5348 if p.isArrayOrPinnedArray(f, n.AssignmentExpression, n.AssignmentExpression.Operand.Type()) { 5349 mode = exprDecay 5350 } 5351 switch { 5352 case flags&fNoCondAssignment == 0 && mode == exprValue && n.UnaryExpression.Declarator() != nil && p.isConditionalAssignmentExpr(n.AssignmentExpression): 5353 f.condInitPrefix = func() { 5354 p.unaryExpression(f, lhs, lt, exprLValue, flags) 5355 p.w(" = ") 5356 } 5357 p.assignmentExpression(f, n.AssignmentExpression, lt, exprCondInit, flags) 5358 p.w(";") 5359 default: 5360 if d != nil && p.isVolatileOrAtomic(d) { 5361 p.setVolatileDeclarator(d, f, n.AssignmentExpression, lt, mode, flags) 5362 return 5363 } 5364 5365 p.unaryExpression(f, lhs, lt, exprLValue, flags) 5366 p.w(" = ") 5367 p.assignmentExpression(f, n.AssignmentExpression, lt, mode, flags) 5368 } 5369 case opBitfield: 5370 bf := lt.BitField() 5371 p.w("%sSetBitFieldPtr%d%s(", p.task.crt, bf.BitFieldBlockWidth(), p.bfHelperType(lt)) 5372 p.unaryExpression(f, lhs, lt, exprAddrOf, flags) 5373 p.w(", ") 5374 p.assignmentExpression(f, n.AssignmentExpression, lt, exprValue, flags) 5375 p.w(", %d, %#x)", bf.BitFieldOffset(), bf.Mask()) 5376 case opUnion: 5377 p.unaryExpression(f, lhs, lt, exprLValue, flags) 5378 p.w(" = ") 5379 p.assignmentExpression(f, n.AssignmentExpression, lt, exprValue, flags) 5380 default: 5381 panic(todo("", n.Position(), k)) 5382 } 5383 f.condInitPrefix = sv 5384 case cc.AssignmentExpressionMul: // UnaryExpression "*=" AssignmentExpression 5385 p.assignOp(f, n, t, mode, "*", "Mul", flags) 5386 case cc.AssignmentExpressionDiv: // UnaryExpression "/=" AssignmentExpression 5387 p.assignOp(f, n, t, mode, "/", "Div", flags) 5388 case cc.AssignmentExpressionMod: // UnaryExpression "%=" AssignmentExpression 5389 p.assignOp(f, n, t, mode, "%", "Mod", flags) 5390 case cc.AssignmentExpressionAdd: // UnaryExpression "+=" AssignmentExpression 5391 p.assignOp(f, n, t, mode, "+", "Add", flags) 5392 case cc.AssignmentExpressionSub: // UnaryExpression "-=" AssignmentExpression 5393 p.assignOp(f, n, t, mode, "-", "Sub", flags) 5394 case cc.AssignmentExpressionLsh: // UnaryExpression "<<=" AssignmentExpression 5395 p.assignShiftOp(f, n, t, mode, "<<", "Shl", flags) 5396 case cc.AssignmentExpressionRsh: // UnaryExpression ">>=" AssignmentExpression 5397 p.assignShiftOp(f, n, t, mode, ">>", "Shr", flags) 5398 case cc.AssignmentExpressionAnd: // UnaryExpression "&=" AssignmentExpression 5399 p.assignOp(f, n, t, mode, "&", "And", flags) 5400 case cc.AssignmentExpressionXor: // UnaryExpression "^=" AssignmentExpression 5401 p.assignOp(f, n, t, mode, "^", "Xor", flags) 5402 case cc.AssignmentExpressionOr: // UnaryExpression "|=" AssignmentExpression 5403 p.assignOp(f, n, t, mode, "|", "Or", flags) 5404 default: 5405 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 5406 } 5407 } 5408 5409 func (p *project) setVolatileDeclarator(d *cc.Declarator, f *function, n *cc.AssignmentExpression, t cc.Type, mode exprMode, flags flags) { 5410 sz := d.Type().Size() 5411 switch sz { 5412 case 4, 8: 5413 // ok 5414 default: 5415 p.err(d, "unsupported volatile declarator size: %v", sz) 5416 return 5417 } 5418 5419 if local := f.locals[d]; local != nil { 5420 if local.isPinned { 5421 p.w("%sAtomicStoreP%s(%s%s /* %s */, ", p.task.crt, p.helperType(n, d.Type()), f.bpName, nonZeroUintptr(local.off), local.name) 5422 p.assignmentExpression(f, n, t, mode, flags) 5423 p.w(")") 5424 return 5425 } 5426 5427 p.atomicStoreNamedAddr(n, d.Type(), local.name, n, f, mode, flags) 5428 return 5429 } 5430 5431 if tld := p.tlds[d]; tld != nil { 5432 p.atomicStoreNamedAddr(n, d.Type(), tld.name, n, f, mode, flags) 5433 return 5434 } 5435 5436 if imp := p.imports[d.Name().String()]; imp != nil { 5437 p.atomicStoreNamedAddr(n, d.Type(), fmt.Sprintf("%sX%s", imp.qualifier, d.Name()), n, f, mode, flags) 5438 return 5439 } 5440 5441 panic(todo("", n.Position(), d.Position(), d.Name())) 5442 } 5443 5444 func (p *project) atomicStoreNamedAddr(n cc.Node, t cc.Type, nm string, expr *cc.AssignmentExpression, f *function, mode exprMode, flags flags) { 5445 sz := t.Size() 5446 switch sz { 5447 case 4, 8: 5448 // ok 5449 default: 5450 p.err(n, "unsupported volatile declarator size: %v", sz) 5451 return 5452 } 5453 5454 var ht string 5455 switch { 5456 case t.IsScalarType(): 5457 ht = p.helperType(n, t) 5458 default: 5459 p.err(n, "unsupported volatile declarator type: %v", t) 5460 return 5461 } 5462 5463 p.w("%sAtomicStore%s(&%s, %s(", p.task.crt, ht, nm, p.typ(n, t)) 5464 p.assignmentExpression(f, expr, t, mode, flags) 5465 p.w("))") 5466 } 5467 5468 func (p *project) atomicLoadNamedAddr(n cc.Node, t cc.Type, nm string) { 5469 sz := t.Size() 5470 switch sz { 5471 case 4, 8: 5472 // ok 5473 default: 5474 p.err(n, "unsupported volatile declarator size: %v", sz) 5475 return 5476 } 5477 5478 var ht string 5479 switch { 5480 case t.IsScalarType(): 5481 ht = p.helperType(n, t) 5482 default: 5483 p.err(n, "unsupported volatile declarator type: %v", t) 5484 return 5485 } 5486 5487 p.w("%sAtomicLoad%s(&%s)", p.task.crt, ht, nm) 5488 } 5489 5490 func isRealType(op cc.Operand) bool { 5491 switch op.Type().Kind() { 5492 case cc.Float, cc.Double: 5493 return true 5494 default: 5495 return false 5496 } 5497 } 5498 5499 func (p *project) bfHelperType(t cc.Type) string { 5500 switch { 5501 case t.IsSignedType(): 5502 return fmt.Sprintf("Int%d", t.Size()*8) 5503 default: 5504 return fmt.Sprintf("Uint%d", t.Size()*8) 5505 } 5506 } 5507 5508 func (p *project) helperType(n cc.Node, t cc.Type) string { 5509 for t.IsAliasType() { 5510 if t2 := t.Alias(); t2 != t { //TODO HDF5 H5O.c 5511 t = t2 5512 continue 5513 } 5514 5515 break 5516 } 5517 switch t.Kind() { 5518 case cc.Int128: 5519 return "Int128" 5520 case cc.UInt128: 5521 return "Uint128" 5522 } 5523 5524 s := p.typ(n, t) 5525 return strings.ToUpper(s[:1]) + s[1:] 5526 } 5527 5528 func (p *project) helperType2(n cc.Node, from, to cc.Type) string { 5529 if from.Kind() == to.Kind() { 5530 return fmt.Sprintf("%s%s", p.task.crt, p.helperType(n, from)) 5531 } 5532 5533 return fmt.Sprintf("%s%sFrom%s", p.task.crt, p.helperType(n, to), p.helperType(n, from)) 5534 } 5535 5536 func (p *project) conditionalExpression(f *function, n *cc.ConditionalExpression, t cc.Type, mode exprMode, flags flags) { 5537 switch mode { 5538 case exprValue: 5539 p.conditionalExpressionValue(f, n, t, mode, flags) 5540 case exprVoid: 5541 p.conditionalExpressionVoid(f, n, t, mode, flags) 5542 case exprAddrOf: 5543 p.conditionalExpressionAddrOf(f, n, t, mode, flags) 5544 case exprBool: 5545 p.conditionalExpressionBool(f, n, t, mode, flags) 5546 case exprLValue: 5547 p.conditionalExpressionLValue(f, n, t, mode, flags) 5548 case exprPSelect: 5549 p.conditionalExpressionPSelect(f, n, t, mode, flags) 5550 case exprFunc: 5551 p.conditionalExpressionFunc(f, n, t, mode, flags) 5552 case exprSelect: 5553 p.conditionalExpressionSelect(f, n, t, mode, flags) 5554 case exprCondReturn: 5555 p.conditionalExpressionReturn(f, n, t, mode, flags) 5556 case exprCondInit: 5557 p.conditionalExpressionInit(f, n, t, mode, flags) 5558 case exprDecay: 5559 p.conditionalExpressionDecay(f, n, t, mode, flags) 5560 default: 5561 panic(todo("", n.Position(), mode)) 5562 } 5563 } 5564 5565 func (p *project) conditionalExpressionDecay(f *function, n *cc.ConditionalExpression, t cc.Type, mode exprMode, flags flags) { 5566 switch n.Case { 5567 case cc.ConditionalExpressionLOr: // LogicalOrExpression 5568 p.logicalOrExpression(f, n.LogicalOrExpression, t, mode, flags) 5569 case cc.ConditionalExpressionCond: // LogicalOrExpression '?' Expression ':' ConditionalExpression 5570 t = t.Decay() 5571 p.w(" func() %s { if ", p.typ(n, t)) 5572 p.logicalOrExpression(f, n.LogicalOrExpression, n.LogicalOrExpression.Operand.Type(), exprBool, flags) 5573 p.w(" { return ") 5574 switch n.Expression.Operand.Type().Kind() { 5575 case cc.Array: 5576 p.expression(f, n.Expression, t, exprDecay, flags) 5577 case cc.Ptr: 5578 panic(todo("", n.Expression.Position(), n.Expression.Operand.Type())) 5579 default: 5580 panic(todo("", n.Expression.Position(), n.Expression.Operand.Type())) 5581 } 5582 p.w("}; return ") 5583 switch n.ConditionalExpression.Operand.Type().Kind() { 5584 case cc.Array: 5585 p.conditionalExpression(f, n.ConditionalExpression, t, exprDecay, flags) 5586 default: 5587 p.conditionalExpression(f, n.ConditionalExpression, t, exprValue, flags) 5588 } 5589 p.w("}()") 5590 default: 5591 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 5592 } 5593 } 5594 5595 func (p *project) conditionalExpressionInit(f *function, n *cc.ConditionalExpression, t cc.Type, mode exprMode, flags flags) { 5596 switch n.Case { 5597 case cc.ConditionalExpressionLOr: // LogicalOrExpression 5598 f.condInitPrefix() 5599 p.logicalOrExpression(f, n.LogicalOrExpression, t, exprValue, flags) 5600 case cc.ConditionalExpressionCond: // LogicalOrExpression '?' Expression ':' ConditionalExpression 5601 t = t.Decay() 5602 p.w("if ") 5603 p.logicalOrExpression(f, n.LogicalOrExpression, n.LogicalOrExpression.Operand.Type(), exprBool, flags) 5604 p.w(" {") 5605 p.expression(f, n.Expression, t, mode, flags) 5606 p.w("} else { ") 5607 p.conditionalExpression(f, n.ConditionalExpression, t, mode, flags) 5608 p.w("}") 5609 default: 5610 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 5611 } 5612 } 5613 5614 func (p *project) conditionalExpressionReturn(f *function, n *cc.ConditionalExpression, t cc.Type, mode exprMode, flags flags) { 5615 switch n.Case { 5616 case cc.ConditionalExpressionLOr: // LogicalOrExpression 5617 p.w("return ") 5618 p.logicalOrExpression(f, n.LogicalOrExpression, t, exprValue, flags) 5619 case cc.ConditionalExpressionCond: // LogicalOrExpression '?' Expression ':' ConditionalExpression 5620 t = t.Decay() 5621 p.w("if ") 5622 p.logicalOrExpression(f, n.LogicalOrExpression, n.LogicalOrExpression.Operand.Type(), exprBool, flags) 5623 p.w(" {") 5624 p.expression(f, n.Expression, t, mode, flags) 5625 p.w("}; ") 5626 p.conditionalExpression(f, n.ConditionalExpression, t, mode, flags) 5627 default: 5628 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 5629 } 5630 } 5631 5632 func (p *project) conditionalExpressionSelect(f *function, n *cc.ConditionalExpression, t cc.Type, mode exprMode, flags flags) { 5633 switch n.Case { 5634 case cc.ConditionalExpressionLOr: // LogicalOrExpression 5635 p.logicalOrExpression(f, n.LogicalOrExpression, t, mode, flags) 5636 case cc.ConditionalExpressionCond: // LogicalOrExpression '?' Expression ':' ConditionalExpression 5637 panic(todo("", p.pos(n))) 5638 default: 5639 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 5640 } 5641 } 5642 5643 func (p *project) conditionalExpressionFunc(f *function, n *cc.ConditionalExpression, t cc.Type, mode exprMode, flags flags) { 5644 switch n.Case { 5645 case cc.ConditionalExpressionLOr: // LogicalOrExpression 5646 p.logicalOrExpression(f, n.LogicalOrExpression, t, mode, flags) 5647 case cc.ConditionalExpressionCond: // LogicalOrExpression '?' Expression ':' ConditionalExpression 5648 switch ot := n.Operand.Type(); ot.Kind() { 5649 case cc.Function: 5650 if t.Kind() != cc.Function { 5651 panic(todo("", n.Position())) 5652 } 5653 default: 5654 panic(todo("", ot.Kind())) 5655 } 5656 5657 p.w(" func() ") 5658 p.functionSignature(n, f, t, "") 5659 p.w("{ if ") 5660 p.logicalOrExpression(f, n.LogicalOrExpression, n.LogicalOrExpression.Operand.Type(), exprBool, flags) 5661 p.w(" { return ") 5662 switch d := n.Expression.Declarator(); { 5663 case d != nil: 5664 p.declaratorDefault(n, d) 5665 default: 5666 panic(todo("", n.Position())) 5667 } 5668 p.w("}; return ") 5669 switch d := n.ConditionalExpression.Declarator(); { 5670 case d != nil: 5671 p.declaratorDefault(n, d) 5672 default: 5673 panic(todo("", n.Position())) 5674 } 5675 p.w("}()") 5676 default: 5677 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 5678 } 5679 } 5680 5681 func (p *project) conditionalExpressionPSelect(f *function, n *cc.ConditionalExpression, t cc.Type, mode exprMode, flags flags) { 5682 switch n.Case { 5683 case cc.ConditionalExpressionLOr: // LogicalOrExpression 5684 p.logicalOrExpression(f, n.LogicalOrExpression, t, mode, flags) 5685 case cc.ConditionalExpressionCond: // LogicalOrExpression '?' Expression ':' ConditionalExpression 5686 p.w("(*%s)(unsafe.Pointer(", p.typ(n, n.Operand.Type().Elem())) 5687 p.conditionalExpression(f, n, t, exprValue, flags) 5688 p.w("))") 5689 default: 5690 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 5691 } 5692 } 5693 5694 func (p *project) conditionalExpressionLValue(f *function, n *cc.ConditionalExpression, t cc.Type, mode exprMode, flags flags) { 5695 switch n.Case { 5696 case cc.ConditionalExpressionLOr: // LogicalOrExpression 5697 p.logicalOrExpression(f, n.LogicalOrExpression, t, mode, flags) 5698 case cc.ConditionalExpressionCond: // LogicalOrExpression '?' Expression ':' ConditionalExpression 5699 panic(todo("", p.pos(n))) 5700 default: 5701 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 5702 } 5703 } 5704 5705 func (p *project) conditionalExpressionBool(f *function, n *cc.ConditionalExpression, t cc.Type, mode exprMode, flags flags) { 5706 switch n.Case { 5707 case cc.ConditionalExpressionLOr: // LogicalOrExpression 5708 p.logicalOrExpression(f, n.LogicalOrExpression, t, mode, flags) 5709 case cc.ConditionalExpressionCond: // LogicalOrExpression '?' Expression ':' ConditionalExpression 5710 p.w("(") 5711 defer p.w(")") 5712 defer p.w(" != 0 ") 5713 p.conditionalExpression(f, n, t, exprValue, flags) 5714 default: 5715 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 5716 } 5717 } 5718 5719 func (p *project) conditionalExpressionAddrOf(f *function, n *cc.ConditionalExpression, t cc.Type, mode exprMode, flags flags) { 5720 switch n.Case { 5721 case cc.ConditionalExpressionLOr: // LogicalOrExpression 5722 p.logicalOrExpression(f, n.LogicalOrExpression, t, mode, flags) 5723 case cc.ConditionalExpressionCond: // LogicalOrExpression '?' Expression ':' ConditionalExpression 5724 t = t.Decay() 5725 p.w(" func() %s { if ", p.typ(n, t)) 5726 p.logicalOrExpression(f, n.LogicalOrExpression, n.LogicalOrExpression.Operand.Type(), exprBool, flags) 5727 p.w(" { return ") 5728 p.expression(f, n.Expression, t, exprValue, flags) 5729 p.w("}; return ") 5730 p.conditionalExpression(f, n.ConditionalExpression, t, exprValue, flags) 5731 p.w("}()") 5732 default: 5733 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 5734 } 5735 } 5736 5737 func (p *project) conditionalExpressionVoid(f *function, n *cc.ConditionalExpression, t cc.Type, mode exprMode, flags flags) { 5738 switch n.Case { 5739 case cc.ConditionalExpressionLOr: // LogicalOrExpression 5740 p.logicalOrExpression(f, n.LogicalOrExpression, t, mode, flags) 5741 case cc.ConditionalExpressionCond: // LogicalOrExpression '?' Expression ':' ConditionalExpression 5742 switch { 5743 case n.Expression.IsSideEffectsFree: 5744 p.w("if !(") 5745 p.logicalOrExpression(f, n.LogicalOrExpression, n.LogicalOrExpression.Operand.Type(), exprBool, flags) 5746 p.w(") {") 5747 p.conditionalExpression(f, n.ConditionalExpression, n.ConditionalExpression.Operand.Type(), mode, flags) 5748 p.w("}") 5749 default: 5750 p.w("if ") 5751 p.logicalOrExpression(f, n.LogicalOrExpression, n.LogicalOrExpression.Operand.Type(), exprBool, flags) 5752 p.w(" {") 5753 p.expression(f, n.Expression, n.Expression.Operand.Type(), mode, flags) 5754 p.w("} else {") 5755 p.conditionalExpression(f, n.ConditionalExpression, n.ConditionalExpression.Operand.Type(), mode, flags) 5756 p.w("}") 5757 } 5758 default: 5759 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 5760 } 5761 } 5762 5763 func (p *project) conditionalExpressionValue(f *function, n *cc.ConditionalExpression, t cc.Type, mode exprMode, flags flags) { 5764 switch n.Case { 5765 case cc.ConditionalExpressionLOr: // LogicalOrExpression 5766 p.logicalOrExpression(f, n.LogicalOrExpression, t, exprValue, flags) 5767 case cc.ConditionalExpressionCond: // LogicalOrExpression '?' Expression ':' ConditionalExpression 5768 t = t.Decay() 5769 p.w(" func() %s { if ", p.typ(n, t)) 5770 p.logicalOrExpression(f, n.LogicalOrExpression, n.LogicalOrExpression.Operand.Type(), exprBool, flags) 5771 p.w(" { return ") 5772 p.expression(f, n.Expression, t, exprValue, flags) 5773 p.w("}; return ") 5774 p.conditionalExpression(f, n.ConditionalExpression, t, exprValue, flags) 5775 p.w("}()") 5776 default: 5777 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 5778 } 5779 } 5780 5781 func (p *project) logicalOrExpression(f *function, n *cc.LogicalOrExpression, t cc.Type, mode exprMode, flags flags) { 5782 switch mode { 5783 case exprValue: 5784 p.logicalOrExpressionValue(f, n, t, mode, flags) 5785 case exprVoid: 5786 p.logicalOrExpressionVoid(f, n, t, mode, flags) 5787 case exprAddrOf: 5788 p.logicalOrExpressionAddrOf(f, n, t, mode, flags) 5789 case exprBool: 5790 p.logicalOrExpressionBool(f, n, t, mode, flags) 5791 case exprLValue: 5792 p.logicalOrExpressionLValue(f, n, t, mode, flags) 5793 case exprPSelect: 5794 p.logicalOrExpressionPSelect(f, n, t, mode, flags) 5795 case exprFunc: 5796 p.logicalOrExpressionFunc(f, n, t, mode, flags) 5797 case exprSelect: 5798 p.logicalOrExpressionSelect(f, n, t, mode, flags) 5799 case exprDecay: 5800 p.logicalOrExpressionDecay(f, n, t, mode, flags) 5801 default: 5802 panic(todo("", n.Position(), mode)) 5803 } 5804 } 5805 5806 func (p *project) logicalOrExpressionDecay(f *function, n *cc.LogicalOrExpression, t cc.Type, mode exprMode, flags flags) { 5807 switch n.Case { 5808 case cc.LogicalOrExpressionLAnd: // LogicalAndExpression 5809 p.logicalAndExpression(f, n.LogicalAndExpression, t, mode, flags) 5810 case cc.LogicalOrExpressionLOr: // LogicalOrExpression "||" LogicalAndExpression 5811 panic(todo("", p.pos(n))) 5812 default: 5813 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 5814 } 5815 } 5816 5817 func (p *project) logicalOrExpressionSelect(f *function, n *cc.LogicalOrExpression, t cc.Type, mode exprMode, flags flags) { 5818 switch n.Case { 5819 case cc.LogicalOrExpressionLAnd: // LogicalAndExpression 5820 p.logicalAndExpression(f, n.LogicalAndExpression, t, mode, flags) 5821 case cc.LogicalOrExpressionLOr: // LogicalOrExpression "||" LogicalAndExpression 5822 panic(todo("", p.pos(n))) 5823 default: 5824 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 5825 } 5826 } 5827 5828 func (p *project) logicalOrExpressionFunc(f *function, n *cc.LogicalOrExpression, t cc.Type, mode exprMode, flags flags) { 5829 switch n.Case { 5830 case cc.LogicalOrExpressionLAnd: // LogicalAndExpression 5831 p.logicalAndExpression(f, n.LogicalAndExpression, t, mode, flags) 5832 case cc.LogicalOrExpressionLOr: // LogicalOrExpression "||" LogicalAndExpression 5833 panic(todo("", p.pos(n))) 5834 default: 5835 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 5836 } 5837 } 5838 5839 func (p *project) logicalOrExpressionPSelect(f *function, n *cc.LogicalOrExpression, t cc.Type, mode exprMode, flags flags) { 5840 switch n.Case { 5841 case cc.LogicalOrExpressionLAnd: // LogicalAndExpression 5842 p.logicalAndExpression(f, n.LogicalAndExpression, t, mode, flags) 5843 case cc.LogicalOrExpressionLOr: // LogicalOrExpression "||" LogicalAndExpression 5844 panic(todo("", p.pos(n))) 5845 default: 5846 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 5847 } 5848 } 5849 5850 func (p *project) logicalOrExpressionLValue(f *function, n *cc.LogicalOrExpression, t cc.Type, mode exprMode, flags flags) { 5851 switch n.Case { 5852 case cc.LogicalOrExpressionLAnd: // LogicalAndExpression 5853 p.logicalAndExpression(f, n.LogicalAndExpression, t, mode, flags) 5854 case cc.LogicalOrExpressionLOr: // LogicalOrExpression "||" LogicalAndExpression 5855 panic(todo("", p.pos(n))) 5856 default: 5857 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 5858 } 5859 } 5860 5861 func (p *project) logicalOrExpressionBool(f *function, n *cc.LogicalOrExpression, t cc.Type, mode exprMode, flags flags) { 5862 switch n.Case { 5863 case cc.LogicalOrExpressionLAnd: // LogicalAndExpression 5864 p.logicalAndExpression(f, n.LogicalAndExpression, t, mode, flags) 5865 case cc.LogicalOrExpressionLOr: // LogicalOrExpression "||" LogicalAndExpression 5866 p.binaryLogicalOrExpression(f, n, t, mode, flags) 5867 default: 5868 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 5869 } 5870 } 5871 5872 func (p *project) logicalOrExpressionAddrOf(f *function, n *cc.LogicalOrExpression, t cc.Type, mode exprMode, flags flags) { 5873 switch n.Case { 5874 case cc.LogicalOrExpressionLAnd: // LogicalAndExpression 5875 p.logicalAndExpression(f, n.LogicalAndExpression, t, mode, flags) 5876 case cc.LogicalOrExpressionLOr: // LogicalOrExpression "||" LogicalAndExpression 5877 panic(todo("", p.pos(n))) 5878 default: 5879 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 5880 } 5881 } 5882 5883 func (p *project) logicalOrExpressionVoid(f *function, n *cc.LogicalOrExpression, t cc.Type, mode exprMode, flags flags) { 5884 switch n.Case { 5885 case cc.LogicalOrExpressionLAnd: // LogicalAndExpression 5886 p.logicalAndExpression(f, n.LogicalAndExpression, t, mode, flags) 5887 case cc.LogicalOrExpressionLOr: // LogicalOrExpression "||" LogicalAndExpression 5888 p.w("_ = ") 5889 p.logicalOrExpression(f, n, n.Operand.Type(), exprValue, flags) 5890 default: 5891 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 5892 } 5893 } 5894 5895 func (p *project) logicalOrExpressionValue(f *function, n *cc.LogicalOrExpression, t cc.Type, mode exprMode, flags flags) { 5896 switch n.Case { 5897 case cc.LogicalOrExpressionLAnd: // LogicalAndExpression 5898 p.logicalAndExpression(f, n.LogicalAndExpression, t, mode, flags) 5899 case cc.LogicalOrExpressionLOr: // LogicalOrExpression "||" LogicalAndExpression 5900 p.binaryLogicalOrExpression(f, n, t, mode, flags) 5901 default: 5902 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 5903 } 5904 } 5905 5906 func (p *project) binaryLogicalOrExpression(f *function, n *cc.LogicalOrExpression, t cc.Type, mode exprMode, flags flags) { 5907 switch mode { 5908 case exprValue: 5909 p.binaryLogicalOrExpressionValue(f, n, t, mode, flags) 5910 case exprBool: 5911 p.binaryLogicalOrExpressionBool(f, n, t, mode, flags) 5912 default: 5913 panic(todo("", n.Position(), mode)) 5914 } 5915 } 5916 5917 func (p *project) binaryLogicalOrExpressionBool(f *function, n *cc.LogicalOrExpression, t cc.Type, mode exprMode, flags flags) { 5918 defer p.w("%s", p.booleanBinaryExpression(n, n.Operand, n.Operand.Type(), &mode, flags)) 5919 p.logicalOrExpression(f, n.LogicalOrExpression, n.LogicalOrExpression.Operand.Type(), exprBool, flags) 5920 p.w(" ||%s", tidyComment(" ", &n.Token)) 5921 p.logicalAndExpression(f, n.LogicalAndExpression, n.LogicalAndExpression.Operand.Type(), exprBool, flags) 5922 } 5923 5924 func (p *project) binaryLogicalOrExpressionValue(f *function, n *cc.LogicalOrExpression, t cc.Type, mode exprMode, flags flags) { 5925 defer p.w("%s", p.booleanBinaryExpression(n, n.Operand, t, &mode, flags)) 5926 p.logicalOrExpression(f, n.LogicalOrExpression, n.LogicalOrExpression.Operand.Type(), exprBool, flags) 5927 p.w(" ||%s", tidyComment(" ", &n.Token)) 5928 p.logicalAndExpression(f, n.LogicalAndExpression, n.LogicalAndExpression.Operand.Type(), exprBool, flags) 5929 } 5930 5931 func (p *project) booleanBinaryExpression(n cc.Node, from cc.Operand, to cc.Type, mode *exprMode, flags flags) (r string) { 5932 p.w("(") 5933 r = ")" 5934 switch *mode { 5935 case exprBool: 5936 *mode = exprValue 5937 default: 5938 r = p.convert(n, from, to, flags) + r 5939 p.w("%sBool32(", p.task.crt) 5940 r = ")" + r 5941 } 5942 return r 5943 } 5944 5945 func (p *project) logicalAndExpression(f *function, n *cc.LogicalAndExpression, t cc.Type, mode exprMode, flags flags) { 5946 switch mode { 5947 case exprValue: 5948 p.logicalAndExpressionValue(f, n, t, mode, flags) 5949 case exprVoid: 5950 p.logicalAndExpressionVoid(f, n, t, mode, flags) 5951 case exprAddrOf: 5952 p.logicalAndExpressionAddrOf(f, n, t, mode, flags) 5953 case exprBool: 5954 p.logicalAndExpressionBool(f, n, t, mode, flags) 5955 case exprLValue: 5956 p.logicalAndExpressionLValue(f, n, t, mode, flags) 5957 case exprPSelect: 5958 p.logicalAndExpressionPSelect(f, n, t, mode, flags) 5959 case exprFunc: 5960 p.logicalAndExpressionFunc(f, n, t, mode, flags) 5961 case exprSelect: 5962 p.logicalAndExpressionSelect(f, n, t, mode, flags) 5963 case exprDecay: 5964 p.logicalAndExpressionDecay(f, n, t, mode, flags) 5965 default: 5966 panic(todo("", n.Position(), mode)) 5967 } 5968 } 5969 5970 func (p *project) logicalAndExpressionDecay(f *function, n *cc.LogicalAndExpression, t cc.Type, mode exprMode, flags flags) { 5971 switch n.Case { 5972 case cc.LogicalAndExpressionOr: // InclusiveOrExpression 5973 p.inclusiveOrExpression(f, n.InclusiveOrExpression, t, mode, flags) 5974 case cc.LogicalAndExpressionLAnd: // LogicalAndExpression "&&" InclusiveOrExpression 5975 panic(todo("", p.pos(n))) 5976 default: 5977 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 5978 } 5979 } 5980 5981 func (p *project) logicalAndExpressionSelect(f *function, n *cc.LogicalAndExpression, t cc.Type, mode exprMode, flags flags) { 5982 switch n.Case { 5983 case cc.LogicalAndExpressionOr: // InclusiveOrExpression 5984 p.inclusiveOrExpression(f, n.InclusiveOrExpression, t, mode, flags) 5985 case cc.LogicalAndExpressionLAnd: // LogicalAndExpression "&&" InclusiveOrExpression 5986 panic(todo("", p.pos(n))) 5987 default: 5988 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 5989 } 5990 } 5991 5992 func (p *project) logicalAndExpressionFunc(f *function, n *cc.LogicalAndExpression, t cc.Type, mode exprMode, flags flags) { 5993 switch n.Case { 5994 case cc.LogicalAndExpressionOr: // InclusiveOrExpression 5995 p.inclusiveOrExpression(f, n.InclusiveOrExpression, t, mode, flags) 5996 case cc.LogicalAndExpressionLAnd: // LogicalAndExpression "&&" InclusiveOrExpression 5997 panic(todo("", p.pos(n))) 5998 default: 5999 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 6000 } 6001 } 6002 6003 func (p *project) logicalAndExpressionPSelect(f *function, n *cc.LogicalAndExpression, t cc.Type, mode exprMode, flags flags) { 6004 switch n.Case { 6005 case cc.LogicalAndExpressionOr: // InclusiveOrExpression 6006 p.inclusiveOrExpression(f, n.InclusiveOrExpression, t, mode, flags) 6007 case cc.LogicalAndExpressionLAnd: // LogicalAndExpression "&&" InclusiveOrExpression 6008 panic(todo("", p.pos(n))) 6009 default: 6010 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 6011 } 6012 } 6013 6014 func (p *project) logicalAndExpressionLValue(f *function, n *cc.LogicalAndExpression, t cc.Type, mode exprMode, flags flags) { 6015 switch n.Case { 6016 case cc.LogicalAndExpressionOr: // InclusiveOrExpression 6017 p.inclusiveOrExpression(f, n.InclusiveOrExpression, t, mode, flags) 6018 case cc.LogicalAndExpressionLAnd: // LogicalAndExpression "&&" InclusiveOrExpression 6019 panic(todo("", p.pos(n))) 6020 default: 6021 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 6022 } 6023 } 6024 6025 func (p *project) logicalAndExpressionBool(f *function, n *cc.LogicalAndExpression, t cc.Type, mode exprMode, flags flags) { 6026 switch n.Case { 6027 case cc.LogicalAndExpressionOr: // InclusiveOrExpression 6028 p.inclusiveOrExpression(f, n.InclusiveOrExpression, t, mode, flags) 6029 case cc.LogicalAndExpressionLAnd: // LogicalAndExpression "&&" InclusiveOrExpression 6030 p.binaryLogicalAndExpression(f, n, t, mode, flags) 6031 default: 6032 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 6033 } 6034 } 6035 6036 func (p *project) logicalAndExpressionAddrOf(f *function, n *cc.LogicalAndExpression, t cc.Type, mode exprMode, flags flags) { 6037 switch n.Case { 6038 case cc.LogicalAndExpressionOr: // InclusiveOrExpression 6039 p.inclusiveOrExpression(f, n.InclusiveOrExpression, t, mode, flags) 6040 case cc.LogicalAndExpressionLAnd: // LogicalAndExpression "&&" InclusiveOrExpression 6041 panic(todo("", p.pos(n))) 6042 default: 6043 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 6044 } 6045 } 6046 6047 func (p *project) logicalAndExpressionVoid(f *function, n *cc.LogicalAndExpression, t cc.Type, mode exprMode, flags flags) { 6048 switch n.Case { 6049 case cc.LogicalAndExpressionOr: // InclusiveOrExpression 6050 p.inclusiveOrExpression(f, n.InclusiveOrExpression, t, mode, flags) 6051 case cc.LogicalAndExpressionLAnd: // LogicalAndExpression "&&" InclusiveOrExpression 6052 p.binaryLogicalAndExpressionValue(f, n, t, mode, flags) 6053 default: 6054 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 6055 } 6056 } 6057 6058 func (p *project) logicalAndExpressionValue(f *function, n *cc.LogicalAndExpression, t cc.Type, mode exprMode, flags flags) { 6059 switch n.Case { 6060 case cc.LogicalAndExpressionOr: // InclusiveOrExpression 6061 p.inclusiveOrExpression(f, n.InclusiveOrExpression, t, mode, flags) 6062 case cc.LogicalAndExpressionLAnd: // LogicalAndExpression "&&" InclusiveOrExpression 6063 p.binaryLogicalAndExpression(f, n, t, mode, flags) 6064 default: 6065 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 6066 } 6067 } 6068 6069 func (p *project) binaryLogicalAndExpression(f *function, n *cc.LogicalAndExpression, t cc.Type, mode exprMode, flags flags) { 6070 switch mode { 6071 case exprBool: 6072 p.binaryLogicalAndExpressionBool(f, n, t, mode, flags) 6073 case exprValue: 6074 p.binaryLogicalAndExpressionValue(f, n, t, mode, flags) 6075 default: 6076 panic(todo("", n.Position(), mode)) 6077 } 6078 } 6079 6080 func (p *project) binaryLogicalAndExpressionValue(f *function, n *cc.LogicalAndExpression, t cc.Type, mode exprMode, flags flags) { 6081 defer p.w("%s", p.booleanBinaryExpression(n, n.Operand, t, &mode, flags)) 6082 p.logicalAndExpression(f, n.LogicalAndExpression, n.LogicalAndExpression.Operand.Type(), exprBool, flags) 6083 p.w(" &&%s", tidyComment(" ", &n.Token)) 6084 p.inclusiveOrExpression(f, n.InclusiveOrExpression, n.InclusiveOrExpression.Operand.Type(), exprBool, flags) 6085 } 6086 6087 func (p *project) binaryLogicalAndExpressionBool(f *function, n *cc.LogicalAndExpression, t cc.Type, mode exprMode, flags flags) { 6088 defer p.w("%s", p.booleanBinaryExpression(n, n.Operand, t, &mode, flags)) 6089 p.logicalAndExpression(f, n.LogicalAndExpression, n.LogicalAndExpression.Operand.Type(), exprBool, flags) 6090 p.w(" &&%s", tidyComment(" ", &n.Token)) 6091 p.inclusiveOrExpression(f, n.InclusiveOrExpression, n.InclusiveOrExpression.Operand.Type(), exprBool, flags) 6092 } 6093 6094 func (p *project) inclusiveOrExpression(f *function, n *cc.InclusiveOrExpression, t cc.Type, mode exprMode, flags flags) { 6095 switch mode { 6096 case exprValue: 6097 p.inclusiveOrExpressionValue(f, n, t, mode, flags) 6098 case exprVoid: 6099 p.inclusiveOrExpressionVoid(f, n, t, mode, flags) 6100 case exprAddrOf: 6101 p.inclusiveOrExpressionAddrof(f, n, t, mode, flags) 6102 case exprBool: 6103 p.inclusiveOrExpressionBool(f, n, t, mode, flags) 6104 case exprLValue: 6105 p.inclusiveOrExpressionLValue(f, n, t, mode, flags) 6106 case exprPSelect: 6107 p.inclusiveOrExpressionPSelect(f, n, t, mode, flags) 6108 case exprFunc: 6109 p.inclusiveOrExpressionFunc(f, n, t, mode, flags) 6110 case exprSelect: 6111 p.inclusiveOrExpressionSelect(f, n, t, mode, flags) 6112 case exprDecay: 6113 p.inclusiveOrExpressionDecay(f, n, t, mode, flags) 6114 default: 6115 panic(todo("", n.Position(), mode)) 6116 } 6117 } 6118 6119 func (p *project) inclusiveOrExpressionDecay(f *function, n *cc.InclusiveOrExpression, t cc.Type, mode exprMode, flags flags) { 6120 switch n.Case { 6121 case cc.InclusiveOrExpressionXor: // ExclusiveOrExpression 6122 p.exclusiveOrExpression(f, n.ExclusiveOrExpression, t, mode, flags) 6123 case cc.InclusiveOrExpressionOr: // InclusiveOrExpression '|' ExclusiveOrExpression 6124 panic(todo("", p.pos(n))) 6125 default: 6126 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 6127 } 6128 } 6129 6130 func (p *project) inclusiveOrExpressionSelect(f *function, n *cc.InclusiveOrExpression, t cc.Type, mode exprMode, flags flags) { 6131 switch n.Case { 6132 case cc.InclusiveOrExpressionXor: // ExclusiveOrExpression 6133 p.exclusiveOrExpression(f, n.ExclusiveOrExpression, t, mode, flags) 6134 case cc.InclusiveOrExpressionOr: // InclusiveOrExpression '|' ExclusiveOrExpression 6135 panic(todo("", p.pos(n))) 6136 default: 6137 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 6138 } 6139 } 6140 6141 func (p *project) inclusiveOrExpressionFunc(f *function, n *cc.InclusiveOrExpression, t cc.Type, mode exprMode, flags flags) { 6142 switch n.Case { 6143 case cc.InclusiveOrExpressionXor: // ExclusiveOrExpression 6144 p.exclusiveOrExpression(f, n.ExclusiveOrExpression, t, mode, flags) 6145 case cc.InclusiveOrExpressionOr: // InclusiveOrExpression '|' ExclusiveOrExpression 6146 panic(todo("", p.pos(n))) 6147 default: 6148 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 6149 } 6150 } 6151 6152 func (p *project) inclusiveOrExpressionPSelect(f *function, n *cc.InclusiveOrExpression, t cc.Type, mode exprMode, flags flags) { 6153 switch n.Case { 6154 case cc.InclusiveOrExpressionXor: // ExclusiveOrExpression 6155 p.exclusiveOrExpression(f, n.ExclusiveOrExpression, t, mode, flags) 6156 case cc.InclusiveOrExpressionOr: // InclusiveOrExpression '|' ExclusiveOrExpression 6157 panic(todo("", p.pos(n))) 6158 default: 6159 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 6160 } 6161 } 6162 6163 func (p *project) inclusiveOrExpressionLValue(f *function, n *cc.InclusiveOrExpression, t cc.Type, mode exprMode, flags flags) { 6164 switch n.Case { 6165 case cc.InclusiveOrExpressionXor: // ExclusiveOrExpression 6166 p.exclusiveOrExpression(f, n.ExclusiveOrExpression, t, mode, flags) 6167 case cc.InclusiveOrExpressionOr: // InclusiveOrExpression '|' ExclusiveOrExpression 6168 panic(todo("", p.pos(n))) 6169 default: 6170 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 6171 } 6172 } 6173 6174 func (p *project) inclusiveOrExpressionBool(f *function, n *cc.InclusiveOrExpression, t cc.Type, mode exprMode, flags flags) { 6175 switch n.Case { 6176 case cc.InclusiveOrExpressionXor: // ExclusiveOrExpression 6177 p.exclusiveOrExpression(f, n.ExclusiveOrExpression, t, mode, flags) 6178 case cc.InclusiveOrExpressionOr: // InclusiveOrExpression '|' ExclusiveOrExpression 6179 p.binaryInclusiveOrExpression(f, n, t, mode, flags) 6180 default: 6181 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 6182 } 6183 } 6184 6185 func (p *project) inclusiveOrExpressionAddrof(f *function, n *cc.InclusiveOrExpression, t cc.Type, mode exprMode, flags flags) { 6186 switch n.Case { 6187 case cc.InclusiveOrExpressionXor: // ExclusiveOrExpression 6188 p.exclusiveOrExpression(f, n.ExclusiveOrExpression, t, mode, flags) 6189 case cc.InclusiveOrExpressionOr: // InclusiveOrExpression '|' ExclusiveOrExpression 6190 panic(todo("", p.pos(n))) 6191 default: 6192 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 6193 } 6194 } 6195 6196 func (p *project) inclusiveOrExpressionVoid(f *function, n *cc.InclusiveOrExpression, t cc.Type, mode exprMode, flags flags) { 6197 switch n.Case { 6198 case cc.InclusiveOrExpressionXor: // ExclusiveOrExpression 6199 p.exclusiveOrExpression(f, n.ExclusiveOrExpression, t, mode, flags) 6200 case cc.InclusiveOrExpressionOr: // InclusiveOrExpression '|' ExclusiveOrExpression 6201 p.w("_ = ") 6202 p.inclusiveOrExpression(f, n, n.Operand.Type(), exprValue, flags) 6203 default: 6204 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 6205 } 6206 } 6207 6208 func (p *project) inclusiveOrExpressionValue(f *function, n *cc.InclusiveOrExpression, t cc.Type, mode exprMode, flags flags) { 6209 switch n.Case { 6210 case cc.InclusiveOrExpressionXor: // ExclusiveOrExpression 6211 p.exclusiveOrExpression(f, n.ExclusiveOrExpression, t, mode, flags) 6212 case cc.InclusiveOrExpressionOr: // InclusiveOrExpression '|' ExclusiveOrExpression 6213 p.binaryInclusiveOrExpression(f, n, t, mode, flags) 6214 default: 6215 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 6216 } 6217 } 6218 6219 func (p *project) binaryInclusiveOrExpression(f *function, n *cc.InclusiveOrExpression, t cc.Type, mode exprMode, flags flags) { 6220 // InclusiveOrExpression '|' ExclusiveOrExpression 6221 switch mode { 6222 case exprBool: 6223 p.binaryInclusiveOrExpressionBool(f, n, t, mode, flags) 6224 case exprValue: 6225 p.binaryInclusiveOrExpressionValue(f, n, t, mode, flags) 6226 default: 6227 panic(todo("", n.Position(), mode)) 6228 } 6229 } 6230 6231 func (p *project) binaryInclusiveOrExpressionValue(f *function, n *cc.InclusiveOrExpression, t cc.Type, mode exprMode, flags flags) { 6232 // InclusiveOrExpression '|' ExclusiveOrExpression 6233 6234 lt := n.InclusiveOrExpression.Operand.Type() 6235 rt := n.ExclusiveOrExpression.Operand.Type() 6236 switch lk, rk := lt.Kind(), rt.Kind(); { 6237 case 6238 lk == cc.UInt128 || rk == cc.UInt128, 6239 lk == cc.Int128 || rk == cc.Int128: 6240 6241 p.binaryOrExpressionUint128(f, n, t, mode, flags) 6242 return 6243 } 6244 6245 defer p.w("%s", p.artithmeticBinaryExpression(n, n.Operand, t, &mode, flags)) 6246 switch { 6247 case orOverflows(n.InclusiveOrExpression.Operand, n.ExclusiveOrExpression.Operand, n.Promote()): 6248 p.inclusiveOrExpression(f, n.InclusiveOrExpression, n.Promote(), exprValue, flags) 6249 p.w(" |%s", tidyComment(" ", &n.Token)) 6250 p.exclusiveOrExpression(f, n.ExclusiveOrExpression, n.Promote(), exprValue, flags|fForceRuntimeConv) 6251 default: 6252 p.inclusiveOrExpression(f, n.InclusiveOrExpression, n.Promote(), exprValue, flags) 6253 p.w(" |%s", tidyComment(" ", &n.Token)) 6254 p.exclusiveOrExpression(f, n.ExclusiveOrExpression, n.Promote(), exprValue, flags) 6255 } 6256 } 6257 6258 func (p *project) binaryOrExpressionUint128(f *function, n *cc.InclusiveOrExpression, t cc.Type, mode exprMode, flags flags) { 6259 // InclusiveOrExpression '|' ExclusiveOrExpression 6260 defer p.w("%s", p.artithmeticBinaryExpression(n, n.Operand, t, &mode, flags)) 6261 p.inclusiveOrExpression(f, n.InclusiveOrExpression, n.Promote(), exprValue, flags) 6262 p.w(".Or(") 6263 p.exclusiveOrExpression(f, n.ExclusiveOrExpression, n.Promote(), exprValue, flags) 6264 p.w(")") 6265 } 6266 6267 func (p *project) binaryInclusiveOrExpressionBool(f *function, n *cc.InclusiveOrExpression, t cc.Type, mode exprMode, flags flags) { 6268 defer p.w("%s", p.artithmeticBinaryExpression(n, n.Operand, t, &mode, flags)) 6269 switch { 6270 case orOverflows(n.InclusiveOrExpression.Operand, n.ExclusiveOrExpression.Operand, n.Promote()): 6271 p.inclusiveOrExpression(f, n.InclusiveOrExpression, n.Promote(), exprValue, flags) 6272 p.w(" |%s", tidyComment(" ", &n.Token)) 6273 p.exclusiveOrExpression(f, n.ExclusiveOrExpression, n.Promote(), exprValue, flags|fForceRuntimeConv) 6274 default: 6275 p.inclusiveOrExpression(f, n.InclusiveOrExpression, n.Promote(), exprValue, flags) 6276 p.w(" |%s", tidyComment(" ", &n.Token)) 6277 p.exclusiveOrExpression(f, n.ExclusiveOrExpression, n.Promote(), exprValue, flags) 6278 } 6279 } 6280 6281 func orOverflows(lo, ro cc.Operand, promote cc.Type) bool { 6282 a, b, ok := getIntOperands(lo, ro) 6283 if !ok { 6284 return false 6285 } 6286 6287 return overflows(a.Or(a, b), promote) 6288 } 6289 6290 func (p *project) artithmeticBinaryExpression(n cc.Node, from cc.Operand, to cc.Type, mode *exprMode, flags flags) (r string) { 6291 p.w("(") 6292 r = ")" 6293 switch *mode { 6294 case exprBool: 6295 p.w("(") 6296 r = ") != 0" + r 6297 *mode = exprValue 6298 default: 6299 switch fk, tk := from.Type().Kind(), to.Kind(); { 6300 case fk != tk && fk == cc.Int128: 6301 return fmt.Sprintf(".%s()%s", p.helperType(n, to), r) 6302 case fk != tk && fk == cc.UInt128: 6303 return fmt.Sprintf(".%s()%s", p.helperType(n, to), r) 6304 default: 6305 r = p.convert(n, from, to, flags) + r 6306 } 6307 } 6308 return r 6309 } 6310 6311 func (p *project) exclusiveOrExpression(f *function, n *cc.ExclusiveOrExpression, t cc.Type, mode exprMode, flags flags) { 6312 switch mode { 6313 case exprValue: 6314 p.exclusiveOrExpressionValue(f, n, t, mode, flags) 6315 case exprVoid: 6316 p.exclusiveOrExpressionVoid(f, n, t, mode, flags) 6317 case exprAddrOf: 6318 p.exclusiveOrExpressionAddrOf(f, n, t, mode, flags) 6319 case exprBool: 6320 p.exclusiveOrExpressionBool(f, n, t, mode, flags) 6321 case exprLValue: 6322 p.exclusiveOrExpressionLValue(f, n, t, mode, flags) 6323 case exprPSelect: 6324 p.exclusiveOrExpressionPSelect(f, n, t, mode, flags) 6325 case exprFunc: 6326 p.exclusiveOrExpressionFunc(f, n, t, mode, flags) 6327 case exprSelect: 6328 p.exclusiveOrExpressionSelect(f, n, t, mode, flags) 6329 case exprDecay: 6330 p.exclusiveOrExpressionDecay(f, n, t, mode, flags) 6331 default: 6332 panic(todo("", n.Position(), mode)) 6333 } 6334 } 6335 6336 func (p *project) exclusiveOrExpressionDecay(f *function, n *cc.ExclusiveOrExpression, t cc.Type, mode exprMode, flags flags) { 6337 switch n.Case { 6338 case cc.ExclusiveOrExpressionAnd: // AndExpression 6339 p.andExpression(f, n.AndExpression, t, mode, flags) 6340 case cc.ExclusiveOrExpressionXor: // ExclusiveOrExpression '^' AndExpression 6341 panic(todo("", p.pos(n))) 6342 default: 6343 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 6344 } 6345 } 6346 6347 func (p *project) exclusiveOrExpressionSelect(f *function, n *cc.ExclusiveOrExpression, t cc.Type, mode exprMode, flags flags) { 6348 switch n.Case { 6349 case cc.ExclusiveOrExpressionAnd: // AndExpression 6350 p.andExpression(f, n.AndExpression, t, mode, flags) 6351 case cc.ExclusiveOrExpressionXor: // ExclusiveOrExpression '^' AndExpression 6352 panic(todo("", p.pos(n))) 6353 default: 6354 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 6355 } 6356 } 6357 6358 func (p *project) exclusiveOrExpressionFunc(f *function, n *cc.ExclusiveOrExpression, t cc.Type, mode exprMode, flags flags) { 6359 switch n.Case { 6360 case cc.ExclusiveOrExpressionAnd: // AndExpression 6361 p.andExpression(f, n.AndExpression, t, mode, flags) 6362 case cc.ExclusiveOrExpressionXor: // ExclusiveOrExpression '^' AndExpression 6363 panic(todo("", p.pos(n))) 6364 default: 6365 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 6366 } 6367 } 6368 6369 func (p *project) exclusiveOrExpressionPSelect(f *function, n *cc.ExclusiveOrExpression, t cc.Type, mode exprMode, flags flags) { 6370 switch n.Case { 6371 case cc.ExclusiveOrExpressionAnd: // AndExpression 6372 p.andExpression(f, n.AndExpression, t, mode, flags) 6373 case cc.ExclusiveOrExpressionXor: // ExclusiveOrExpression '^' AndExpression 6374 panic(todo("", p.pos(n))) 6375 default: 6376 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 6377 } 6378 } 6379 6380 func (p *project) exclusiveOrExpressionLValue(f *function, n *cc.ExclusiveOrExpression, t cc.Type, mode exprMode, flags flags) { 6381 switch n.Case { 6382 case cc.ExclusiveOrExpressionAnd: // AndExpression 6383 p.andExpression(f, n.AndExpression, t, mode, flags) 6384 case cc.ExclusiveOrExpressionXor: // ExclusiveOrExpression '^' AndExpression 6385 panic(todo("", p.pos(n))) 6386 default: 6387 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 6388 } 6389 } 6390 6391 func (p *project) exclusiveOrExpressionBool(f *function, n *cc.ExclusiveOrExpression, t cc.Type, mode exprMode, flags flags) { 6392 switch n.Case { 6393 case cc.ExclusiveOrExpressionAnd: // AndExpression 6394 p.andExpression(f, n.AndExpression, t, mode, flags) 6395 case cc.ExclusiveOrExpressionXor: // ExclusiveOrExpression '^' AndExpression 6396 p.binaryExclusiveOrExpression(f, n, t, mode, flags) 6397 default: 6398 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 6399 } 6400 } 6401 6402 func (p *project) exclusiveOrExpressionAddrOf(f *function, n *cc.ExclusiveOrExpression, t cc.Type, mode exprMode, flags flags) { 6403 switch n.Case { 6404 case cc.ExclusiveOrExpressionAnd: // AndExpression 6405 p.andExpression(f, n.AndExpression, t, mode, flags) 6406 case cc.ExclusiveOrExpressionXor: // ExclusiveOrExpression '^' AndExpression 6407 panic(todo("", p.pos(n))) 6408 default: 6409 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 6410 } 6411 } 6412 6413 func (p *project) exclusiveOrExpressionVoid(f *function, n *cc.ExclusiveOrExpression, t cc.Type, mode exprMode, flags flags) { 6414 switch n.Case { 6415 case cc.ExclusiveOrExpressionAnd: // AndExpression 6416 p.andExpression(f, n.AndExpression, t, mode, flags) 6417 case cc.ExclusiveOrExpressionXor: // ExclusiveOrExpression '^' AndExpression 6418 p.w("_ = ") 6419 p.exclusiveOrExpression(f, n, n.Operand.Type(), exprValue, flags) 6420 default: 6421 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 6422 } 6423 } 6424 6425 func (p *project) exclusiveOrExpressionValue(f *function, n *cc.ExclusiveOrExpression, t cc.Type, mode exprMode, flags flags) { 6426 switch n.Case { 6427 case cc.ExclusiveOrExpressionAnd: // AndExpression 6428 p.andExpression(f, n.AndExpression, t, mode, flags) 6429 case cc.ExclusiveOrExpressionXor: // ExclusiveOrExpression '^' AndExpression 6430 p.binaryExclusiveOrExpression(f, n, t, mode, flags) 6431 default: 6432 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 6433 } 6434 } 6435 6436 func (p *project) binaryExclusiveOrExpression(f *function, n *cc.ExclusiveOrExpression, t cc.Type, mode exprMode, flags flags) { 6437 // ExclusiveOrExpression '^' AndExpression 6438 switch mode { 6439 case exprValue, exprBool: 6440 p.binaryExclusiveOrExpressionValue(f, n, t, mode, flags) 6441 default: 6442 panic(todo("", n.Position(), mode)) 6443 } 6444 } 6445 6446 func (p *project) binaryExclusiveOrExpressionValue(f *function, n *cc.ExclusiveOrExpression, t cc.Type, mode exprMode, flags flags) { 6447 // ExclusiveOrExpression '^' AndExpression 6448 6449 lt := n.ExclusiveOrExpression.Operand.Type() 6450 rt := n.AndExpression.Operand.Type() 6451 switch lk, rk := lt.Kind(), rt.Kind(); { 6452 case 6453 lk == cc.UInt128 || rk == cc.UInt128, 6454 lk == cc.Int128 || rk == cc.Int128: 6455 6456 p.binaryExclusiveOrExpressionUint128(f, n, t, mode, flags) 6457 return 6458 } 6459 6460 defer p.w("%s", p.artithmeticBinaryExpression(n, n.Operand, t, &mode, flags)) 6461 switch { 6462 case xorOverflows(n.ExclusiveOrExpression.Operand, n.AndExpression.Operand, n.Promote()): 6463 p.exclusiveOrExpression(f, n.ExclusiveOrExpression, n.Promote(), exprValue, flags) 6464 p.w(" ^%s", tidyComment(" ", &n.Token)) 6465 p.andExpression(f, n.AndExpression, n.Promote(), exprValue, flags|fForceRuntimeConv) 6466 default: 6467 p.exclusiveOrExpression(f, n.ExclusiveOrExpression, n.Promote(), exprValue, flags) 6468 p.w(" ^%s", tidyComment(" ", &n.Token)) 6469 p.andExpression(f, n.AndExpression, n.Promote(), exprValue, flags) 6470 } 6471 } 6472 6473 func (p *project) binaryExclusiveOrExpressionUint128(f *function, n *cc.ExclusiveOrExpression, t cc.Type, mode exprMode, flags flags) { 6474 // ExclusiveOrExpression '^' AndExpression 6475 defer p.w("%s", p.artithmeticBinaryExpression(n, n.Operand, t, &mode, flags)) 6476 p.exclusiveOrExpression(f, n.ExclusiveOrExpression, n.Promote(), exprValue, flags) 6477 p.w(".Xor(") 6478 p.andExpression(f, n.AndExpression, n.Promote(), exprValue, flags) 6479 p.w(")") 6480 } 6481 6482 func xorOverflows(lo, ro cc.Operand, promote cc.Type) bool { 6483 a, b, ok := getIntOperands(lo, ro) 6484 if !ok { 6485 return false 6486 } 6487 6488 return !lo.Type().IsSignedType() && a.Sign() == 0 || 6489 !ro.Type().IsSignedType() && b.Sign() == 0 || 6490 overflows(a.Xor(a, b), promote) 6491 } 6492 6493 func (p *project) andExpression(f *function, n *cc.AndExpression, t cc.Type, mode exprMode, flags flags) { 6494 switch mode { 6495 case exprValue: 6496 p.andExpressionValue(f, n, t, mode, flags) 6497 case exprVoid: 6498 p.andExpressionVoid(f, n, t, mode, flags) 6499 case exprAddrOf: 6500 p.andExpressionAddrof(f, n, t, mode, flags) 6501 case exprBool: 6502 p.andExpressionBool(f, n, t, mode, flags) 6503 case exprLValue: 6504 p.andExpressionLValue(f, n, t, mode, flags) 6505 case exprPSelect: 6506 p.andExpressionPSelect(f, n, t, mode, flags) 6507 case exprFunc: 6508 p.andExpressionFunc(f, n, t, mode, flags) 6509 case exprSelect: 6510 p.andExpressionSelect(f, n, t, mode, flags) 6511 case exprDecay: 6512 p.andExpressionDecay(f, n, t, mode, flags) 6513 default: 6514 panic(todo("", n.Position(), mode)) 6515 } 6516 } 6517 6518 func (p *project) andExpressionDecay(f *function, n *cc.AndExpression, t cc.Type, mode exprMode, flags flags) { 6519 switch n.Case { 6520 case cc.AndExpressionEq: // EqualityExpression 6521 p.equalityExpression(f, n.EqualityExpression, t, mode, flags) 6522 case cc.AndExpressionAnd: // AndExpression '&' EqualityExpression 6523 panic(todo("", p.pos(n))) 6524 default: 6525 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 6526 } 6527 } 6528 6529 func (p *project) andExpressionSelect(f *function, n *cc.AndExpression, t cc.Type, mode exprMode, flags flags) { 6530 switch n.Case { 6531 case cc.AndExpressionEq: // EqualityExpression 6532 p.equalityExpression(f, n.EqualityExpression, t, mode, flags) 6533 case cc.AndExpressionAnd: // AndExpression '&' EqualityExpression 6534 panic(todo("", p.pos(n))) 6535 default: 6536 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 6537 } 6538 } 6539 6540 func (p *project) andExpressionFunc(f *function, n *cc.AndExpression, t cc.Type, mode exprMode, flags flags) { 6541 switch n.Case { 6542 case cc.AndExpressionEq: // EqualityExpression 6543 p.equalityExpression(f, n.EqualityExpression, t, mode, flags) 6544 case cc.AndExpressionAnd: // AndExpression '&' EqualityExpression 6545 panic(todo("", p.pos(n))) 6546 default: 6547 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 6548 } 6549 } 6550 6551 func (p *project) andExpressionPSelect(f *function, n *cc.AndExpression, t cc.Type, mode exprMode, flags flags) { 6552 switch n.Case { 6553 case cc.AndExpressionEq: // EqualityExpression 6554 p.equalityExpression(f, n.EqualityExpression, t, mode, flags) 6555 case cc.AndExpressionAnd: // AndExpression '&' EqualityExpression 6556 panic(todo("", p.pos(n))) 6557 default: 6558 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 6559 } 6560 } 6561 6562 func (p *project) andExpressionLValue(f *function, n *cc.AndExpression, t cc.Type, mode exprMode, flags flags) { 6563 switch n.Case { 6564 case cc.AndExpressionEq: // EqualityExpression 6565 p.equalityExpression(f, n.EqualityExpression, t, mode, flags) 6566 case cc.AndExpressionAnd: // AndExpression '&' EqualityExpression 6567 panic(todo("", p.pos(n))) 6568 default: 6569 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 6570 } 6571 } 6572 6573 func (p *project) andExpressionBool(f *function, n *cc.AndExpression, t cc.Type, mode exprMode, flags flags) { 6574 switch n.Case { 6575 case cc.AndExpressionEq: // EqualityExpression 6576 p.equalityExpression(f, n.EqualityExpression, t, mode, flags) 6577 case cc.AndExpressionAnd: // AndExpression '&' EqualityExpression 6578 p.binaryAndExpression(f, n, t, mode, flags) 6579 default: 6580 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 6581 } 6582 } 6583 6584 func (p *project) andExpressionAddrof(f *function, n *cc.AndExpression, t cc.Type, mode exprMode, flags flags) { 6585 switch n.Case { 6586 case cc.AndExpressionEq: // EqualityExpression 6587 p.equalityExpression(f, n.EqualityExpression, t, mode, flags) 6588 case cc.AndExpressionAnd: // AndExpression '&' EqualityExpression 6589 panic(todo("", p.pos(n))) 6590 default: 6591 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 6592 } 6593 } 6594 6595 func (p *project) andExpressionVoid(f *function, n *cc.AndExpression, t cc.Type, mode exprMode, flags flags) { 6596 switch n.Case { 6597 case cc.AndExpressionEq: // EqualityExpression 6598 p.equalityExpression(f, n.EqualityExpression, t, mode, flags) 6599 case cc.AndExpressionAnd: // AndExpression '&' EqualityExpression 6600 p.w("_ = ") 6601 p.andExpression(f, n, n.Operand.Type(), exprValue, flags) 6602 default: 6603 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 6604 } 6605 } 6606 6607 func (p *project) andExpressionValue(f *function, n *cc.AndExpression, t cc.Type, mode exprMode, flags flags) { 6608 switch n.Case { 6609 case cc.AndExpressionEq: // EqualityExpression 6610 p.equalityExpression(f, n.EqualityExpression, t, mode, flags) 6611 case cc.AndExpressionAnd: // AndExpression '&' EqualityExpression 6612 p.binaryAndExpression(f, n, t, mode, flags) 6613 default: 6614 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 6615 } 6616 } 6617 6618 func (p *project) binaryAndExpression(f *function, n *cc.AndExpression, t cc.Type, mode exprMode, flags flags) { 6619 // AndExpression '&' EqualityExpression 6620 switch mode { 6621 case exprValue: 6622 p.binaryAndExpressionValue(f, n, t, mode, flags) 6623 case exprBool: 6624 p.binaryAndExpressionBool(f, n, t, mode, flags) 6625 default: 6626 panic(todo("", n.Position(), mode)) 6627 } 6628 } 6629 6630 func (p *project) binaryAndExpressionBool(f *function, n *cc.AndExpression, t cc.Type, mode exprMode, flags flags) { 6631 defer p.w("%s", p.artithmeticBinaryExpression(n, n.Operand, n.Operand.Type(), &mode, flags)) 6632 switch { 6633 case andOverflows(n.AndExpression.Operand, n.EqualityExpression.Operand, n.Promote()): 6634 p.andExpression(f, n.AndExpression, n.Promote(), exprValue, flags) 6635 p.w(" &%s", tidyComment(" ", &n.Token)) 6636 p.equalityExpression(f, n.EqualityExpression, n.Promote(), exprValue, flags|fForceRuntimeConv) 6637 default: 6638 p.andExpression(f, n.AndExpression, n.Promote(), exprValue, flags) 6639 p.w(" &%s", tidyComment(" ", &n.Token)) 6640 p.equalityExpression(f, n.EqualityExpression, n.Promote(), exprValue, flags) 6641 } 6642 } 6643 6644 func (p *project) binaryAndExpressionValue(f *function, n *cc.AndExpression, t cc.Type, mode exprMode, flags flags) { 6645 // AndExpression '&' EqualityExpression 6646 6647 lt := n.AndExpression.Operand.Type() 6648 rt := n.EqualityExpression.Operand.Type() 6649 switch lk, rk := lt.Kind(), rt.Kind(); { 6650 case 6651 lk == cc.UInt128 || rk == cc.UInt128, 6652 lk == cc.Int128 || rk == cc.Int128: 6653 6654 p.binaryAndExpressionUint128(f, n, t, mode, flags) 6655 return 6656 } 6657 6658 defer p.w("%s", p.artithmeticBinaryExpression(n, n.Operand, t, &mode, flags)) 6659 switch { 6660 case andOverflows(n.AndExpression.Operand, n.EqualityExpression.Operand, n.Promote()): 6661 p.andExpression(f, n.AndExpression, n.Promote(), exprValue, flags) 6662 p.w(" &%s", tidyComment(" ", &n.Token)) 6663 p.equalityExpression(f, n.EqualityExpression, n.Promote(), exprValue, flags|fForceRuntimeConv) 6664 default: 6665 p.andExpression(f, n.AndExpression, n.Promote(), exprValue, flags) 6666 p.w(" &%s", tidyComment(" ", &n.Token)) 6667 p.equalityExpression(f, n.EqualityExpression, n.Promote(), exprValue, flags) 6668 } 6669 } 6670 6671 func (p *project) binaryAndExpressionUint128(f *function, n *cc.AndExpression, t cc.Type, mode exprMode, flags flags) { 6672 // AndExpression '&' EqualityExpression 6673 defer p.w("%s", p.artithmeticBinaryExpression(n, n.Operand, t, &mode, flags)) 6674 p.andExpression(f, n.AndExpression, n.Promote(), exprValue, flags) 6675 p.w(".And(") 6676 p.equalityExpression(f, n.EqualityExpression, n.Promote(), exprValue, flags) 6677 p.w(")") 6678 } 6679 6680 func andOverflows(lo, ro cc.Operand, promote cc.Type) bool { 6681 a, b, ok := getIntOperands(lo, ro) 6682 if !ok { 6683 return false 6684 } 6685 6686 return overflows(a.And(a, b), promote) 6687 } 6688 6689 func (p *project) equalityExpression(f *function, n *cc.EqualityExpression, t cc.Type, mode exprMode, flags flags) { 6690 switch mode { 6691 case exprValue: 6692 p.equalityExpressionValue(f, n, t, mode, flags) 6693 case exprVoid: 6694 p.equalityExpressionVoid(f, n, t, mode, flags) 6695 case exprAddrOf: 6696 p.equalityExpressionAddrOf(f, n, t, mode, flags) 6697 case exprBool: 6698 p.equalityExpressionBool(f, n, t, mode, flags) 6699 case exprLValue: 6700 p.equalityExpressionLValue(f, n, t, mode, flags) 6701 case exprPSelect: 6702 p.equalityExpressionPSelect(f, n, t, mode, flags) 6703 case exprFunc: 6704 p.equalityExpressionFunc(f, n, t, mode, flags) 6705 case exprSelect: 6706 p.equalityExpressionSelect(f, n, t, mode, flags) 6707 case exprDecay: 6708 p.equalityExpressionDecay(f, n, t, mode, flags) 6709 default: 6710 panic(todo("", n.Position(), mode)) 6711 } 6712 } 6713 6714 func (p *project) equalityExpressionDecay(f *function, n *cc.EqualityExpression, t cc.Type, mode exprMode, flags flags) { 6715 switch n.Case { 6716 case cc.EqualityExpressionRel: // RelationalExpression 6717 p.relationalExpression(f, n.RelationalExpression, t, mode, flags) 6718 case cc.EqualityExpressionEq: // EqualityExpression "==" RelationalExpression 6719 panic(todo("", p.pos(n))) 6720 case cc.EqualityExpressionNeq: // EqualityExpression "!=" RelationalExpression 6721 panic(todo("", p.pos(n))) 6722 default: 6723 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 6724 } 6725 } 6726 6727 func (p *project) equalityExpressionSelect(f *function, n *cc.EqualityExpression, t cc.Type, mode exprMode, flags flags) { 6728 switch n.Case { 6729 case cc.EqualityExpressionRel: // RelationalExpression 6730 p.relationalExpression(f, n.RelationalExpression, t, mode, flags) 6731 case cc.EqualityExpressionEq: // EqualityExpression "==" RelationalExpression 6732 panic(todo("", p.pos(n))) 6733 case cc.EqualityExpressionNeq: // EqualityExpression "!=" RelationalExpression 6734 panic(todo("", p.pos(n))) 6735 default: 6736 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 6737 } 6738 } 6739 6740 func (p *project) equalityExpressionFunc(f *function, n *cc.EqualityExpression, t cc.Type, mode exprMode, flags flags) { 6741 switch n.Case { 6742 case cc.EqualityExpressionRel: // RelationalExpression 6743 p.relationalExpression(f, n.RelationalExpression, t, mode, flags) 6744 case cc.EqualityExpressionEq: // EqualityExpression "==" RelationalExpression 6745 panic(todo("", p.pos(n))) 6746 case cc.EqualityExpressionNeq: // EqualityExpression "!=" RelationalExpression 6747 panic(todo("", p.pos(n))) 6748 default: 6749 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 6750 } 6751 } 6752 6753 func (p *project) equalityExpressionPSelect(f *function, n *cc.EqualityExpression, t cc.Type, mode exprMode, flags flags) { 6754 switch n.Case { 6755 case cc.EqualityExpressionRel: // RelationalExpression 6756 p.relationalExpression(f, n.RelationalExpression, t, mode, flags) 6757 case cc.EqualityExpressionEq: // EqualityExpression "==" RelationalExpression 6758 panic(todo("", p.pos(n))) 6759 case cc.EqualityExpressionNeq: // EqualityExpression "!=" RelationalExpression 6760 panic(todo("", p.pos(n))) 6761 default: 6762 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 6763 } 6764 } 6765 6766 func (p *project) equalityExpressionLValue(f *function, n *cc.EqualityExpression, t cc.Type, mode exprMode, flags flags) { 6767 switch n.Case { 6768 case cc.EqualityExpressionRel: // RelationalExpression 6769 p.relationalExpression(f, n.RelationalExpression, t, mode, flags) 6770 case cc.EqualityExpressionEq: // EqualityExpression "==" RelationalExpression 6771 panic(todo("", p.pos(n))) 6772 case cc.EqualityExpressionNeq: // EqualityExpression "!=" RelationalExpression 6773 panic(todo("", p.pos(n))) 6774 default: 6775 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 6776 } 6777 } 6778 6779 func (p *project) equalityExpressionBool(f *function, n *cc.EqualityExpression, t cc.Type, mode exprMode, flags flags) { 6780 switch n.Case { 6781 case cc.EqualityExpressionRel: // RelationalExpression 6782 p.relationalExpression(f, n.RelationalExpression, t, mode, flags) 6783 case cc.EqualityExpressionEq: // EqualityExpression "==" RelationalExpression 6784 p.binaryEqualityExpression(f, n, " == ", t, mode, flags) 6785 case cc.EqualityExpressionNeq: // EqualityExpression "!=" RelationalExpression 6786 p.binaryEqualityExpression(f, n, " != ", t, mode, flags) 6787 default: 6788 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 6789 } 6790 } 6791 6792 func (p *project) equalityExpressionAddrOf(f *function, n *cc.EqualityExpression, t cc.Type, mode exprMode, flags flags) { 6793 switch n.Case { 6794 case cc.EqualityExpressionRel: // RelationalExpression 6795 p.relationalExpression(f, n.RelationalExpression, t, mode, flags) 6796 case cc.EqualityExpressionEq: // EqualityExpression "==" RelationalExpression 6797 panic(todo("", p.pos(n))) 6798 case cc.EqualityExpressionNeq: // EqualityExpression "!=" RelationalExpression 6799 panic(todo("", p.pos(n))) 6800 default: 6801 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 6802 } 6803 } 6804 6805 func (p *project) equalityExpressionVoid(f *function, n *cc.EqualityExpression, t cc.Type, mode exprMode, flags flags) { 6806 switch n.Case { 6807 case cc.EqualityExpressionRel: // RelationalExpression 6808 p.relationalExpression(f, n.RelationalExpression, t, mode, flags) 6809 default: 6810 // case cc.EqualityExpressionEq: // EqualityExpression "==" RelationalExpression 6811 // case cc.EqualityExpressionNeq: // EqualityExpression "!=" RelationalExpression 6812 p.w("_ = ") 6813 p.equalityExpression(f, n, n.Operand.Type(), exprValue, flags) 6814 } 6815 } 6816 6817 func (p *project) equalityExpressionValue(f *function, n *cc.EqualityExpression, t cc.Type, mode exprMode, flags flags) { 6818 switch n.Case { 6819 case cc.EqualityExpressionRel: // RelationalExpression 6820 p.relationalExpression(f, n.RelationalExpression, t, mode, flags) 6821 case cc.EqualityExpressionEq: // EqualityExpression "==" RelationalExpression 6822 p.binaryEqualityExpression(f, n, " == ", t, mode, flags) 6823 case cc.EqualityExpressionNeq: // EqualityExpression "!=" RelationalExpression 6824 p.binaryEqualityExpression(f, n, " != ", t, mode, flags) 6825 default: 6826 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 6827 } 6828 } 6829 6830 func (p *project) binaryEqualityExpression(f *function, n *cc.EqualityExpression, oper string, t cc.Type, mode exprMode, flags flags) { 6831 switch mode { 6832 case exprValue: 6833 p.binaryEqualityExpressionValue(f, n, oper, t, mode, flags) 6834 case exprBool: 6835 p.binaryEqualityExpressionBool(f, n, oper, t, mode, flags) 6836 default: 6837 panic(todo("", n.Position(), mode)) 6838 } 6839 } 6840 6841 func (p *project) binaryEqualityExpressionBool(f *function, n *cc.EqualityExpression, oper string, t cc.Type, mode exprMode, flags flags) { 6842 defer p.w("%s", p.booleanBinaryExpression(n, n.Operand, t, &mode, flags)) 6843 p.equalityExpression(f, n.EqualityExpression, n.Promote(), exprValue, flags) 6844 p.w(" %s%s", oper, tidyComment(" ", &n.Token)) 6845 p.relationalExpression(f, n.RelationalExpression, n.Promote(), exprValue, flags) 6846 } 6847 6848 func (p *project) binaryEqualityExpressionValue(f *function, n *cc.EqualityExpression, oper string, t cc.Type, mode exprMode, flags flags) { 6849 defer p.w("%s", p.booleanBinaryExpression(n, n.Operand, t, &mode, flags)) 6850 p.equalityExpression(f, n.EqualityExpression, n.Promote(), exprValue, flags) 6851 p.w(" %s%s", oper, tidyComment(" ", &n.Token)) 6852 p.relationalExpression(f, n.RelationalExpression, n.Promote(), exprValue, flags) 6853 } 6854 6855 func (p *project) relationalExpression(f *function, n *cc.RelationalExpression, t cc.Type, mode exprMode, flags flags) { 6856 switch mode { 6857 case exprValue: 6858 p.relationalExpressionValue(f, n, t, mode, flags) 6859 case exprVoid: 6860 p.relationalExpressionVoid(f, n, t, mode, flags) 6861 case exprAddrOf: 6862 p.relationalExpressionAddrOf(f, n, t, mode, flags) 6863 case exprBool: 6864 p.relationalExpressionBool(f, n, t, mode, flags) 6865 case exprLValue: 6866 p.relationalExpressionLValue(f, n, t, mode, flags) 6867 case exprPSelect: 6868 p.relationalExpressionPSelect(f, n, t, mode, flags) 6869 case exprFunc: 6870 p.relationalExpressionFunc(f, n, t, mode, flags) 6871 case exprSelect: 6872 p.relationalExpressionSelect(f, n, t, mode, flags) 6873 case exprDecay: 6874 p.relationalExpressionDecay(f, n, t, mode, flags) 6875 default: 6876 panic(todo("", n.Position(), mode)) 6877 } 6878 } 6879 6880 func (p *project) relationalExpressionDecay(f *function, n *cc.RelationalExpression, t cc.Type, mode exprMode, flags flags) { 6881 switch n.Case { 6882 case cc.RelationalExpressionShift: // ShiftExpression 6883 p.shiftExpression(f, n.ShiftExpression, t, mode, flags) 6884 case cc.RelationalExpressionLt: // RelationalExpression '<' ShiftExpression 6885 panic(todo("", p.pos(n))) 6886 case cc.RelationalExpressionGt: // RelationalExpression '>' ShiftExpression 6887 panic(todo("", p.pos(n))) 6888 case cc.RelationalExpressionLeq: // RelationalExpression "<=" ShiftExpression 6889 panic(todo("", p.pos(n))) 6890 case cc.RelationalExpressionGeq: // RelationalExpression ">=" ShiftExpression 6891 panic(todo("", p.pos(n))) 6892 default: 6893 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 6894 } 6895 } 6896 6897 func (p *project) relationalExpressionSelect(f *function, n *cc.RelationalExpression, t cc.Type, mode exprMode, flags flags) { 6898 switch n.Case { 6899 case cc.RelationalExpressionShift: // ShiftExpression 6900 p.shiftExpression(f, n.ShiftExpression, t, mode, flags) 6901 case cc.RelationalExpressionLt: // RelationalExpression '<' ShiftExpression 6902 panic(todo("", p.pos(n))) 6903 case cc.RelationalExpressionGt: // RelationalExpression '>' ShiftExpression 6904 panic(todo("", p.pos(n))) 6905 case cc.RelationalExpressionLeq: // RelationalExpression "<=" ShiftExpression 6906 panic(todo("", p.pos(n))) 6907 case cc.RelationalExpressionGeq: // RelationalExpression ">=" ShiftExpression 6908 panic(todo("", p.pos(n))) 6909 default: 6910 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 6911 } 6912 } 6913 6914 func (p *project) relationalExpressionFunc(f *function, n *cc.RelationalExpression, t cc.Type, mode exprMode, flags flags) { 6915 switch n.Case { 6916 case cc.RelationalExpressionShift: // ShiftExpression 6917 p.shiftExpression(f, n.ShiftExpression, t, mode, flags) 6918 case cc.RelationalExpressionLt: // RelationalExpression '<' ShiftExpression 6919 panic(todo("", p.pos(n))) 6920 case cc.RelationalExpressionGt: // RelationalExpression '>' ShiftExpression 6921 panic(todo("", p.pos(n))) 6922 case cc.RelationalExpressionLeq: // RelationalExpression "<=" ShiftExpression 6923 panic(todo("", p.pos(n))) 6924 case cc.RelationalExpressionGeq: // RelationalExpression ">=" ShiftExpression 6925 panic(todo("", p.pos(n))) 6926 default: 6927 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 6928 } 6929 } 6930 6931 func (p *project) relationalExpressionPSelect(f *function, n *cc.RelationalExpression, t cc.Type, mode exprMode, flags flags) { 6932 switch n.Case { 6933 case cc.RelationalExpressionShift: // ShiftExpression 6934 p.shiftExpression(f, n.ShiftExpression, t, mode, flags) 6935 case cc.RelationalExpressionLt: // RelationalExpression '<' ShiftExpression 6936 panic(todo("", p.pos(n))) 6937 case cc.RelationalExpressionGt: // RelationalExpression '>' ShiftExpression 6938 panic(todo("", p.pos(n))) 6939 case cc.RelationalExpressionLeq: // RelationalExpression "<=" ShiftExpression 6940 panic(todo("", p.pos(n))) 6941 case cc.RelationalExpressionGeq: // RelationalExpression ">=" ShiftExpression 6942 panic(todo("", p.pos(n))) 6943 default: 6944 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 6945 } 6946 } 6947 6948 func (p *project) relationalExpressionLValue(f *function, n *cc.RelationalExpression, t cc.Type, mode exprMode, flags flags) { 6949 switch n.Case { 6950 case cc.RelationalExpressionShift: // ShiftExpression 6951 p.shiftExpression(f, n.ShiftExpression, t, mode, flags) 6952 case cc.RelationalExpressionLt: // RelationalExpression '<' ShiftExpression 6953 panic(todo("", p.pos(n))) 6954 case cc.RelationalExpressionGt: // RelationalExpression '>' ShiftExpression 6955 panic(todo("", p.pos(n))) 6956 case cc.RelationalExpressionLeq: // RelationalExpression "<=" ShiftExpression 6957 panic(todo("", p.pos(n))) 6958 case cc.RelationalExpressionGeq: // RelationalExpression ">=" ShiftExpression 6959 panic(todo("", p.pos(n))) 6960 default: 6961 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 6962 } 6963 } 6964 6965 func (p *project) relationalExpressionBool(f *function, n *cc.RelationalExpression, t cc.Type, mode exprMode, flags flags) { 6966 switch n.Case { 6967 case cc.RelationalExpressionShift: // ShiftExpression 6968 p.shiftExpression(f, n.ShiftExpression, t, mode, flags) 6969 case cc.RelationalExpressionLt: // RelationalExpression '<' ShiftExpression 6970 p.binaryRelationalExpression(f, n, " < ", t, mode, flags) 6971 case cc.RelationalExpressionGt: // RelationalExpression '>' ShiftExpression 6972 p.binaryRelationalExpression(f, n, " > ", t, mode, flags) 6973 case cc.RelationalExpressionLeq: // RelationalExpression "<=" ShiftExpression 6974 p.binaryRelationalExpression(f, n, " <= ", t, mode, flags) 6975 case cc.RelationalExpressionGeq: // RelationalExpression ">=" ShiftExpression 6976 p.binaryRelationalExpression(f, n, " >= ", t, mode, flags) 6977 default: 6978 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 6979 } 6980 } 6981 6982 func (p *project) relationalExpressionAddrOf(f *function, n *cc.RelationalExpression, t cc.Type, mode exprMode, flags flags) { 6983 switch n.Case { 6984 case cc.RelationalExpressionShift: // ShiftExpression 6985 p.shiftExpression(f, n.ShiftExpression, t, mode, flags) 6986 case cc.RelationalExpressionLt: // RelationalExpression '<' ShiftExpression 6987 panic(todo("", p.pos(n))) 6988 case cc.RelationalExpressionGt: // RelationalExpression '>' ShiftExpression 6989 panic(todo("", p.pos(n))) 6990 case cc.RelationalExpressionLeq: // RelationalExpression "<=" ShiftExpression 6991 panic(todo("", p.pos(n))) 6992 case cc.RelationalExpressionGeq: // RelationalExpression ">=" ShiftExpression 6993 panic(todo("", p.pos(n))) 6994 default: 6995 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 6996 } 6997 } 6998 6999 func (p *project) relationalExpressionVoid(f *function, n *cc.RelationalExpression, t cc.Type, mode exprMode, flags flags) { 7000 switch n.Case { 7001 case cc.RelationalExpressionShift: // ShiftExpression 7002 p.shiftExpression(f, n.ShiftExpression, t, mode, flags) 7003 default: 7004 // case cc.RelationalExpressionLt: // RelationalExpression '<' ShiftExpression 7005 // case cc.RelationalExpressionGt: // RelationalExpression '>' ShiftExpression 7006 // case cc.RelationalExpressionLeq: // RelationalExpression "<=" ShiftExpression 7007 // case cc.RelationalExpressionGeq: // RelationalExpression ">=" ShiftExpression 7008 p.w("_ = ") 7009 p.relationalExpression(f, n, n.Operand.Type(), exprValue, flags) 7010 } 7011 } 7012 7013 func (p *project) relationalExpressionValue(f *function, n *cc.RelationalExpression, t cc.Type, mode exprMode, flags flags) { 7014 switch n.Case { 7015 case cc.RelationalExpressionShift: // ShiftExpression 7016 p.shiftExpression(f, n.ShiftExpression, t, mode, flags) 7017 case cc.RelationalExpressionLt: // RelationalExpression '<' ShiftExpression 7018 p.binaryRelationalExpression(f, n, " < ", t, mode, flags) 7019 case cc.RelationalExpressionGt: // RelationalExpression '>' ShiftExpression 7020 p.binaryRelationalExpression(f, n, " > ", t, mode, flags) 7021 case cc.RelationalExpressionLeq: // RelationalExpression "<=" ShiftExpression 7022 p.binaryRelationalExpression(f, n, " <= ", t, mode, flags) 7023 case cc.RelationalExpressionGeq: // RelationalExpression ">=" ShiftExpression 7024 p.binaryRelationalExpression(f, n, " >= ", t, mode, flags) 7025 default: 7026 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 7027 } 7028 } 7029 7030 func (p *project) binaryRelationalExpression(f *function, n *cc.RelationalExpression, oper string, t cc.Type, mode exprMode, flags flags) { 7031 // RelationalExpression "<=" ShiftExpression 7032 lt := n.RelationalExpression.Operand.Type() 7033 rt := n.ShiftExpression.Operand.Type() 7034 switch lk, rk := lt.Kind(), rt.Kind(); { 7035 case 7036 lk == cc.UInt128 || rk == cc.UInt128, 7037 lk == cc.Int128 || rk == cc.Int128: 7038 7039 p.binaryRelationalExpressionInt128(f, n, oper, t, mode, flags) 7040 return 7041 } 7042 7043 defer p.w("%s", p.booleanBinaryExpression(n, n.Operand, t, &mode, flags)) 7044 p.relationalExpression(f, n.RelationalExpression, n.Promote(), exprValue, flags) 7045 p.w(" %s%s", oper, tidyComment(" ", &n.Token)) 7046 p.shiftExpression(f, n.ShiftExpression, n.Promote(), exprValue, flags) 7047 } 7048 7049 func (p *project) binaryRelationalExpressionInt128(f *function, n *cc.RelationalExpression, oper string, t cc.Type, mode exprMode, flags flags) { 7050 // RelationalExpression "<=" ShiftExpression 7051 defer p.w("%s", p.booleanBinaryExpression(n, n.Operand, t, &mode, flags)) 7052 p.relationalExpression(f, n.RelationalExpression, n.Promote(), exprValue, flags) 7053 p.w(".Cmp(") 7054 p.shiftExpression(f, n.ShiftExpression, n.Promote(), exprValue, flags) 7055 p.w(") %s 0", oper) 7056 } 7057 7058 func (p *project) shiftExpression(f *function, n *cc.ShiftExpression, t cc.Type, mode exprMode, flags flags) { 7059 switch mode { 7060 case exprValue: 7061 p.shiftExpressionValue(f, n, t, mode, flags) 7062 case exprVoid: 7063 p.shiftExpressionVoid(f, n, t, mode, flags) 7064 case exprAddrOf: 7065 p.shiftExpressionAddrOf(f, n, t, mode, flags) 7066 case exprBool: 7067 p.shiftExpressionBool(f, n, t, mode, flags) 7068 case exprLValue: 7069 p.shiftExpressionLValue(f, n, t, mode, flags) 7070 case exprPSelect: 7071 p.shiftExpressionPSelect(f, n, t, mode, flags) 7072 case exprFunc: 7073 p.shiftExpressionFunc(f, n, t, mode, flags) 7074 case exprSelect: 7075 p.shiftExpressionSelect(f, n, t, mode, flags) 7076 case exprDecay: 7077 p.shiftExpressionDecay(f, n, t, mode, flags) 7078 default: 7079 panic(todo("", n.Position(), mode)) 7080 } 7081 } 7082 7083 func (p *project) shiftExpressionDecay(f *function, n *cc.ShiftExpression, t cc.Type, mode exprMode, flags flags) { 7084 switch n.Case { 7085 case cc.ShiftExpressionAdd: // AdditiveExpression 7086 p.additiveExpression(f, n.AdditiveExpression, t, mode, flags) 7087 case cc.ShiftExpressionLsh: // ShiftExpression "<<" AdditiveExpression 7088 panic(todo("", p.pos(n))) 7089 case cc.ShiftExpressionRsh: // ShiftExpression ">>" AdditiveExpression 7090 panic(todo("", p.pos(n))) 7091 default: 7092 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 7093 } 7094 } 7095 7096 func (p *project) shiftExpressionSelect(f *function, n *cc.ShiftExpression, t cc.Type, mode exprMode, flags flags) { 7097 switch n.Case { 7098 case cc.ShiftExpressionAdd: // AdditiveExpression 7099 p.additiveExpression(f, n.AdditiveExpression, t, mode, flags) 7100 case cc.ShiftExpressionLsh: // ShiftExpression "<<" AdditiveExpression 7101 panic(todo("", p.pos(n))) 7102 case cc.ShiftExpressionRsh: // ShiftExpression ">>" AdditiveExpression 7103 panic(todo("", p.pos(n))) 7104 default: 7105 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 7106 } 7107 } 7108 7109 func (p *project) shiftExpressionFunc(f *function, n *cc.ShiftExpression, t cc.Type, mode exprMode, flags flags) { 7110 switch n.Case { 7111 case cc.ShiftExpressionAdd: // AdditiveExpression 7112 p.additiveExpression(f, n.AdditiveExpression, t, mode, flags) 7113 case cc.ShiftExpressionLsh: // ShiftExpression "<<" AdditiveExpression 7114 panic(todo("", p.pos(n))) 7115 case cc.ShiftExpressionRsh: // ShiftExpression ">>" AdditiveExpression 7116 panic(todo("", p.pos(n))) 7117 default: 7118 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 7119 } 7120 } 7121 7122 func (p *project) shiftExpressionPSelect(f *function, n *cc.ShiftExpression, t cc.Type, mode exprMode, flags flags) { 7123 switch n.Case { 7124 case cc.ShiftExpressionAdd: // AdditiveExpression 7125 p.additiveExpression(f, n.AdditiveExpression, t, mode, flags) 7126 case cc.ShiftExpressionLsh: // ShiftExpression "<<" AdditiveExpression 7127 panic(todo("", p.pos(n))) 7128 case cc.ShiftExpressionRsh: // ShiftExpression ">>" AdditiveExpression 7129 panic(todo("", p.pos(n))) 7130 default: 7131 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 7132 } 7133 } 7134 7135 func (p *project) shiftExpressionLValue(f *function, n *cc.ShiftExpression, t cc.Type, mode exprMode, flags flags) { 7136 switch n.Case { 7137 case cc.ShiftExpressionAdd: // AdditiveExpression 7138 p.additiveExpression(f, n.AdditiveExpression, t, mode, flags) 7139 case cc.ShiftExpressionLsh: // ShiftExpression "<<" AdditiveExpression 7140 panic(todo("", p.pos(n))) 7141 case cc.ShiftExpressionRsh: // ShiftExpression ">>" AdditiveExpression 7142 panic(todo("", p.pos(n))) 7143 default: 7144 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 7145 } 7146 } 7147 7148 func (p *project) shiftExpressionBool(f *function, n *cc.ShiftExpression, t cc.Type, mode exprMode, flags flags) { 7149 switch n.Case { 7150 case cc.ShiftExpressionAdd: // AdditiveExpression 7151 p.additiveExpression(f, n.AdditiveExpression, t, mode, flags) 7152 case cc.ShiftExpressionLsh: // ShiftExpression "<<" AdditiveExpression 7153 p.binaryShiftExpression(f, n, "<<", t, mode, flags) 7154 case cc.ShiftExpressionRsh: // ShiftExpression ">>" AdditiveExpression 7155 p.binaryShiftExpression(f, n, ">>", t, mode, flags) 7156 default: 7157 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 7158 } 7159 } 7160 7161 func (p *project) shiftExpressionAddrOf(f *function, n *cc.ShiftExpression, t cc.Type, mode exprMode, flags flags) { 7162 switch n.Case { 7163 case cc.ShiftExpressionAdd: // AdditiveExpression 7164 p.additiveExpression(f, n.AdditiveExpression, t, mode, flags) 7165 case cc.ShiftExpressionLsh: // ShiftExpression "<<" AdditiveExpression 7166 panic(todo("", p.pos(n))) 7167 case cc.ShiftExpressionRsh: // ShiftExpression ">>" AdditiveExpression 7168 panic(todo("", p.pos(n))) 7169 default: 7170 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 7171 } 7172 } 7173 7174 func (p *project) shiftExpressionVoid(f *function, n *cc.ShiftExpression, t cc.Type, mode exprMode, flags flags) { 7175 switch n.Case { 7176 case cc.ShiftExpressionAdd: // AdditiveExpression 7177 p.additiveExpression(f, n.AdditiveExpression, t, mode, flags) 7178 case cc.ShiftExpressionLsh: // ShiftExpression "<<" AdditiveExpression 7179 panic(todo("", p.pos(n))) 7180 case cc.ShiftExpressionRsh: // ShiftExpression ">>" AdditiveExpression 7181 panic(todo("", p.pos(n))) 7182 default: 7183 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 7184 } 7185 } 7186 7187 func (p *project) shiftExpressionValue(f *function, n *cc.ShiftExpression, t cc.Type, mode exprMode, flags flags) { 7188 switch n.Case { 7189 case cc.ShiftExpressionAdd: // AdditiveExpression 7190 p.additiveExpression(f, n.AdditiveExpression, t, mode, flags) 7191 case cc.ShiftExpressionLsh: // ShiftExpression "<<" AdditiveExpression 7192 p.binaryShiftExpression(f, n, "<<", t, mode, flags) 7193 case cc.ShiftExpressionRsh: // ShiftExpression ">>" AdditiveExpression 7194 p.binaryShiftExpression(f, n, ">>", t, mode, flags) 7195 default: 7196 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 7197 } 7198 } 7199 7200 func (p *project) binaryShiftExpression(f *function, n *cc.ShiftExpression, oper string, t cc.Type, mode exprMode, flags flags) { 7201 // ShiftExpression "<<" AdditiveExpression 7202 switch mode { 7203 case exprValue: 7204 p.binaryShiftExpressionValue(f, n, oper, t, mode, flags) 7205 case exprBool: 7206 p.binaryShiftExpressionBool(f, n, oper, t, mode, flags) 7207 default: 7208 panic(todo("", n.Position(), mode)) 7209 } 7210 } 7211 7212 func (p *project) todo(n cc.Node, t cc.Type) { 7213 p.w("func() %s { panic(`%v: TODO (%v)`)}()", p.typ(n, t), n.Position(), origin(2)) 7214 } 7215 7216 func (p *project) binaryShiftExpressionBool(f *function, n *cc.ShiftExpression, oper string, t cc.Type, mode exprMode, flags flags) { 7217 defer p.w("%s", p.artithmeticBinaryExpression(n, n.Operand, n.Operand.Type(), &mode, flags)) 7218 switch { 7219 case n.ShiftExpression.Operand.Type().IsBitFieldType(): 7220 p.w("(") 7221 p.shiftExpression(f, n.ShiftExpression, n.Operand.Type(), exprValue, flags) 7222 p.w(" %s%s", oper, tidyComment(" ", &n.Token)) 7223 p.additiveExpression(f, n.AdditiveExpression, n.Promote(), exprValue, flags) 7224 p.w(")&%#x", bfValueMask(n.ShiftExpression.Operand.Type().BitField())) 7225 case shiftOverflows(n, n.ShiftExpression.Operand, n.AdditiveExpression.Operand, oper, n.Operand.Type()): 7226 p.shiftExpression(f, n.ShiftExpression, n.Operand.Type(), exprValue, flags|fForceRuntimeConv) 7227 p.w(" %s%s", oper, tidyComment(" ", &n.Token)) 7228 p.additiveExpression(f, n.AdditiveExpression, n.Promote(), exprValue, flags) 7229 case isConstInteger(n.ShiftExpression.Operand): 7230 s := p.convertNil(n, n.Operand.Type(), 0) 7231 p.shiftExpression(f, n.ShiftExpression, n.Operand.Type(), exprValue, flags) 7232 p.w("%s %s%s", s, oper, tidyComment(" ", &n.Token)) 7233 p.additiveExpression(f, n.AdditiveExpression, n.Promote(), exprValue, flags) 7234 default: 7235 p.shiftExpression(f, n.ShiftExpression, n.Operand.Type(), exprValue, flags) 7236 p.w(" %s%s", oper, tidyComment(" ", &n.Token)) 7237 p.additiveExpression(f, n.AdditiveExpression, n.Promote(), exprValue, flags) 7238 } 7239 } 7240 7241 func shiftOp(s string) string { 7242 switch s { 7243 case "<<": 7244 return "Shl" 7245 case ">>": 7246 return "Shr" 7247 default: 7248 panic(todo("%q", s)) 7249 } 7250 } 7251 7252 func bfValueMask(bf cc.Field) uint64 { 7253 return uint64(1)<<bf.BitFieldWidth() - 1 7254 } 7255 7256 func (p *project) binaryShiftExpressionValue(f *function, n *cc.ShiftExpression, oper string, t cc.Type, mode exprMode, flags flags) { 7257 // ShiftExpression "<<" AdditiveExpression 7258 defer p.w("%s", p.artithmeticBinaryExpression(n, n.Operand, t, &mode, flags)) 7259 switch k := n.ShiftExpression.Operand.Type().Kind(); { 7260 case k == cc.Int128, k == cc.UInt128: 7261 p.w("(") 7262 p.shiftExpression(f, n.ShiftExpression, n.Operand.Type(), exprValue, flags) 7263 p.w(").%s(", shiftOp(oper)) 7264 p.additiveExpression(f, n.AdditiveExpression, p.intType, exprValue, flags) 7265 p.w(")") 7266 case n.ShiftExpression.Operand.Type().IsBitFieldType(): 7267 p.w("(") 7268 p.shiftExpression(f, n.ShiftExpression, n.Operand.Type(), exprValue, flags) 7269 p.w(" %s%s", oper, tidyComment(" ", &n.Token)) 7270 p.additiveExpression(f, n.AdditiveExpression, n.Promote(), exprValue, flags) 7271 p.w(")&%#x", bfValueMask(n.ShiftExpression.Operand.Type().BitField())) 7272 case shiftOverflows(n, n.ShiftExpression.Operand, n.AdditiveExpression.Operand, oper, n.Operand.Type()): 7273 p.shiftExpression(f, n.ShiftExpression, n.Operand.Type(), exprValue, flags|fForceRuntimeConv) 7274 p.w(" %s%s", oper, tidyComment(" ", &n.Token)) 7275 p.additiveExpression(f, n.AdditiveExpression, n.Promote(), exprValue, flags) 7276 case isConstInteger(n.ShiftExpression.Operand): 7277 s := p.convertNil(n, n.Operand.Type(), 0) 7278 p.shiftExpression(f, n.ShiftExpression, n.Operand.Type(), exprValue, flags) 7279 p.w("%s %s%s", s, oper, tidyComment(" ", &n.Token)) 7280 p.additiveExpression(f, n.AdditiveExpression, n.Promote(), exprValue, flags) 7281 default: 7282 p.shiftExpression(f, n.ShiftExpression, n.Operand.Type(), exprValue, flags) 7283 p.w(" %s%s", oper, tidyComment(" ", &n.Token)) 7284 p.additiveExpression(f, n.AdditiveExpression, n.Promote(), exprValue, flags) 7285 } 7286 } 7287 7288 func shiftOverflows(n cc.Node, lo, ro cc.Operand, oper string, result cc.Type) bool { 7289 a, b, ok := getIntOperands(lo, ro) 7290 if !ok { 7291 return false 7292 } 7293 7294 if !b.IsUint64() { 7295 return true 7296 } 7297 7298 bits := b.Uint64() 7299 if bits > mathutil.MaxUint { 7300 return true 7301 } 7302 7303 switch oper { 7304 case "<<": 7305 return overflows(a.Lsh(a, uint(bits)), result) 7306 case ">>": 7307 return overflows(a.Rsh(a, uint(bits)), result) 7308 default: 7309 panic(todo("", pos(n))) 7310 } 7311 } 7312 7313 func (p *project) additiveExpression(f *function, n *cc.AdditiveExpression, t cc.Type, mode exprMode, flags flags) { 7314 switch mode { 7315 case exprValue: 7316 p.additiveExpressionValue(f, n, t, mode, flags) 7317 case exprVoid: 7318 p.additiveExpressionVoid(f, n, t, mode, flags) 7319 case exprAddrOf: 7320 p.additiveExpressionAddrOf(f, n, t, mode, flags) 7321 case exprBool: 7322 p.additiveExpressionBool(f, n, t, mode, flags) 7323 case exprLValue: 7324 p.additiveExpressionLValue(f, n, t, mode, flags) 7325 case exprPSelect: 7326 p.additiveExpressionPSelect(f, n, t, mode, flags) 7327 case exprFunc: 7328 p.additiveExpressionFunc(f, n, t, mode, flags) 7329 case exprSelect: 7330 p.additiveExpressionSelect(f, n, t, mode, flags) 7331 case exprDecay: 7332 p.additiveExpressionDecay(f, n, t, mode, flags) 7333 default: 7334 panic(todo("", n.Position(), mode)) 7335 } 7336 } 7337 7338 func (p *project) additiveExpressionDecay(f *function, n *cc.AdditiveExpression, t cc.Type, mode exprMode, flags flags) { 7339 switch n.Case { 7340 case cc.AdditiveExpressionMul: // MultiplicativeExpression 7341 p.multiplicativeExpression(f, n.MultiplicativeExpression, t, mode, flags) 7342 case cc.AdditiveExpressionAdd: // AdditiveExpression '+' MultiplicativeExpression 7343 panic(todo("", p.pos(n))) 7344 case cc.AdditiveExpressionSub: // AdditiveExpression '-' MultiplicativeExpression 7345 panic(todo("", p.pos(n))) 7346 default: 7347 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 7348 } 7349 } 7350 7351 func (p *project) additiveExpressionSelect(f *function, n *cc.AdditiveExpression, t cc.Type, mode exprMode, flags flags) { 7352 switch n.Case { 7353 case cc.AdditiveExpressionMul: // MultiplicativeExpression 7354 p.multiplicativeExpression(f, n.MultiplicativeExpression, t, mode, flags) 7355 case cc.AdditiveExpressionAdd: // AdditiveExpression '+' MultiplicativeExpression 7356 panic(todo("", p.pos(n))) 7357 case cc.AdditiveExpressionSub: // AdditiveExpression '-' MultiplicativeExpression 7358 panic(todo("", p.pos(n))) 7359 default: 7360 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 7361 } 7362 } 7363 7364 func (p *project) additiveExpressionFunc(f *function, n *cc.AdditiveExpression, t cc.Type, mode exprMode, flags flags) { 7365 switch n.Case { 7366 case cc.AdditiveExpressionMul: // MultiplicativeExpression 7367 p.multiplicativeExpression(f, n.MultiplicativeExpression, t, mode, flags) 7368 case cc.AdditiveExpressionAdd: // AdditiveExpression '+' MultiplicativeExpression 7369 panic(todo("", p.pos(n))) 7370 case cc.AdditiveExpressionSub: // AdditiveExpression '-' MultiplicativeExpression 7371 panic(todo("", p.pos(n))) 7372 default: 7373 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 7374 } 7375 } 7376 7377 func (p *project) additiveExpressionPSelect(f *function, n *cc.AdditiveExpression, t cc.Type, mode exprMode, flags flags) { 7378 switch n.Case { 7379 case cc.AdditiveExpressionMul: // MultiplicativeExpression 7380 p.multiplicativeExpression(f, n.MultiplicativeExpression, t, mode, flags) 7381 case cc.AdditiveExpressionAdd: // AdditiveExpression '+' MultiplicativeExpression 7382 p.w("(*%s)(unsafe.Pointer(", p.typ(n, t.Elem())) 7383 p.additiveExpression(f, n, t, exprValue, flags) 7384 p.w("))") 7385 case cc.AdditiveExpressionSub: // AdditiveExpression '-' MultiplicativeExpression 7386 p.w("(*%s)(unsafe.Pointer(", p.typ(n, t.Elem())) 7387 p.additiveExpression(f, n, t, exprValue, flags) 7388 7389 default: 7390 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 7391 } 7392 } 7393 7394 func (p *project) additiveExpressionLValue(f *function, n *cc.AdditiveExpression, t cc.Type, mode exprMode, flags flags) { 7395 switch n.Case { 7396 case cc.AdditiveExpressionMul: // MultiplicativeExpression 7397 p.multiplicativeExpression(f, n.MultiplicativeExpression, t, mode, flags) 7398 case cc.AdditiveExpressionAdd: // AdditiveExpression '+' MultiplicativeExpression 7399 panic(todo("", p.pos(n))) 7400 case cc.AdditiveExpressionSub: // AdditiveExpression '-' MultiplicativeExpression 7401 panic(todo("", p.pos(n))) 7402 default: 7403 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 7404 } 7405 } 7406 7407 func (p *project) additiveExpressionBool(f *function, n *cc.AdditiveExpression, t cc.Type, mode exprMode, flags flags) { 7408 switch n.Case { 7409 case cc.AdditiveExpressionMul: // MultiplicativeExpression 7410 p.multiplicativeExpression(f, n.MultiplicativeExpression, t, mode, flags) 7411 case cc.AdditiveExpressionAdd: // AdditiveExpression '+' MultiplicativeExpression 7412 p.binaryAdditiveExpression(f, n, "+", t, mode, flags) 7413 case cc.AdditiveExpressionSub: // AdditiveExpression '-' MultiplicativeExpression 7414 p.binaryAdditiveExpression(f, n, "-", t, mode, flags) 7415 default: 7416 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 7417 } 7418 } 7419 7420 func (p *project) additiveExpressionAddrOf(f *function, n *cc.AdditiveExpression, t cc.Type, mode exprMode, flags flags) { 7421 switch n.Case { 7422 case cc.AdditiveExpressionMul: // MultiplicativeExpression 7423 p.multiplicativeExpression(f, n.MultiplicativeExpression, t, mode, flags) 7424 case cc.AdditiveExpressionAdd: // AdditiveExpression '+' MultiplicativeExpression 7425 panic(todo("", p.pos(n))) 7426 case cc.AdditiveExpressionSub: // AdditiveExpression '-' MultiplicativeExpression 7427 panic(todo("", p.pos(n))) 7428 default: 7429 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 7430 } 7431 } 7432 7433 func (p *project) additiveExpressionVoid(f *function, n *cc.AdditiveExpression, t cc.Type, mode exprMode, flags flags) { 7434 switch n.Case { 7435 case cc.AdditiveExpressionMul: // MultiplicativeExpression 7436 p.multiplicativeExpression(f, n.MultiplicativeExpression, t, mode, flags) 7437 case 7438 cc.AdditiveExpressionAdd, // AdditiveExpression '+' MultiplicativeExpression 7439 cc.AdditiveExpressionSub: // AdditiveExpression '-' MultiplicativeExpression 7440 7441 p.w("_ = ") 7442 p.additiveExpression(f, n, n.Operand.Type(), exprValue, flags) 7443 default: 7444 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 7445 } 7446 } 7447 7448 func (p *project) additiveExpressionValue(f *function, n *cc.AdditiveExpression, t cc.Type, mode exprMode, flags flags) { 7449 switch n.Case { 7450 case cc.AdditiveExpressionMul: // MultiplicativeExpression 7451 p.multiplicativeExpression(f, n.MultiplicativeExpression, t, mode, flags) 7452 case cc.AdditiveExpressionAdd: // AdditiveExpression '+' MultiplicativeExpression 7453 p.binaryAdditiveExpression(f, n, "+", t, mode, flags) 7454 case cc.AdditiveExpressionSub: // AdditiveExpression '-' MultiplicativeExpression 7455 p.binaryAdditiveExpression(f, n, "-", t, mode, flags) 7456 default: 7457 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 7458 } 7459 } 7460 7461 func (p *project) binaryAdditiveExpression(f *function, n *cc.AdditiveExpression, oper string, t cc.Type, mode exprMode, flags flags) { 7462 // AdditiveExpression '+' MultiplicativeExpression 7463 switch mode { 7464 case exprValue: 7465 p.binaryAdditiveExpressionValue(f, n, oper, t, mode, flags) 7466 case exprBool: 7467 p.binaryAdditiveExpressionBool(f, n, oper, t, mode, flags) 7468 default: 7469 panic(todo("", mode)) 7470 } 7471 } 7472 7473 func (p *project) binaryAdditiveExpressionBool(f *function, n *cc.AdditiveExpression, oper string, t cc.Type, mode exprMode, flags flags) { 7474 // AdditiveExpression '+' MultiplicativeExpression 7475 defer p.w("%s", p.artithmeticBinaryExpression(n, n.Operand, n.Operand.Type(), &mode, flags)) 7476 lo := n.AdditiveExpression.Operand 7477 ro := n.MultiplicativeExpression.Operand 7478 lt := lo.Type() 7479 rt := ro.Type() 7480 switch { 7481 case lt.Kind() == cc.Ptr && rt.Kind() == cc.Ptr && oper == "-": 7482 p.additiveExpression(f, n.AdditiveExpression, n.Promote(), exprValue, flags) 7483 p.w(" %s%s", oper, tidyComment(" ", &n.Token)) 7484 p.multiplicativeExpression(f, n.MultiplicativeExpression, n.Promote(), exprValue, flags) 7485 case lt.IsArithmeticType() && rt.IsArithmeticType(): // x +- y 7486 defer p.w("%s", p.bitFieldPatch2(n, lo, ro, n.Promote())) //TODO bit field big endian 7487 switch { 7488 case intAddOverflows(n, lo, ro, oper, n.Promote()): // i +- j 7489 p.additiveExpression(f, n.AdditiveExpression, n.Promote(), exprValue, flags) 7490 p.w(" %s%s", oper, tidyComment(" ", &n.Token)) 7491 p.multiplicativeExpression(f, n.MultiplicativeExpression, n.Promote(), exprValue, flags|fForceRuntimeConv) 7492 default: 7493 var s string 7494 if isRealType(n.Operand) && n.Operand.Value() != nil { 7495 s = p.convertNil(n, n.Promote(), flags) 7496 } 7497 p.additiveExpression(f, n.AdditiveExpression, n.Promote(), exprValue, flags) 7498 p.w("%s %s%s", s, oper, tidyComment(" ", &n.Token)) 7499 p.multiplicativeExpression(f, n.MultiplicativeExpression, n.Promote(), exprValue, flags) 7500 } 7501 default: 7502 panic(todo("", n.Position(), lt, rt, oper)) 7503 } 7504 } 7505 7506 func (p *project) binaryAdditiveExpressionValue(f *function, n *cc.AdditiveExpression, oper string, t cc.Type, mode exprMode, flags flags) { 7507 // AdditiveExpression '+' MultiplicativeExpression 7508 7509 lt := n.AdditiveExpression.Operand.Type() 7510 rt := n.MultiplicativeExpression.Operand.Type() 7511 switch lk, rk := lt.Kind(), rt.Kind(); { 7512 case 7513 lk == cc.UInt128 || rk == cc.UInt128, 7514 lk == cc.Int128 || rk == cc.Int128: 7515 7516 p.binaryAdditiveExpressionUint128(f, n, oper, t, mode, flags) 7517 return 7518 } 7519 7520 defer p.w("%s", p.artithmeticBinaryExpression(n, n.Operand, t, &mode, flags)) 7521 lo := n.AdditiveExpression.Operand 7522 ro := n.MultiplicativeExpression.Operand 7523 switch { 7524 case lt.IsArithmeticType() && rt.IsArithmeticType(): // x +- y 7525 defer p.w("%s", p.bitFieldPatch2(n, lo, ro, n.Promote())) //TODO bit field big endian 7526 switch { 7527 case intAddOverflows(n, lo, ro, oper, n.Promote()): // i +- j 7528 p.additiveExpression(f, n.AdditiveExpression, n.Promote(), exprValue, flags) 7529 p.w(" %s%s", oper, tidyComment(" ", &n.Token)) 7530 p.multiplicativeExpression(f, n.MultiplicativeExpression, n.Promote(), exprValue, flags|fForceRuntimeConv) 7531 default: 7532 var s string 7533 if isRealType(n.Operand) && n.Operand.Value() != nil { 7534 s = p.convertNil(n, n.Promote(), flags) 7535 } 7536 p.additiveExpression(f, n.AdditiveExpression, n.Promote(), exprValue, flags) 7537 p.w("%s %s%s", s, oper, tidyComment(" ", &n.Token)) 7538 p.multiplicativeExpression(f, n.MultiplicativeExpression, n.Promote(), exprValue, flags) 7539 } 7540 case lt.Kind() == cc.Ptr && rt.IsIntegerType(): // p +- i 7541 p.additiveExpression(f, n.AdditiveExpression, lt, exprValue, flags) 7542 p.w(" %s%s uintptr(", oper, tidyComment(" ", &n.Token)) 7543 p.multiplicativeExpression(f, n.MultiplicativeExpression, rt, exprValue, flags) 7544 p.w(")") 7545 if sz := lt.Elem().Size(); sz != 1 { 7546 p.w("*%d", sz) 7547 } 7548 case lt.Kind() == cc.Array && rt.IsIntegerType(): // p +- i 7549 p.additiveExpression(f, n.AdditiveExpression, lt, exprDecay, flags) 7550 p.w(" %s%s uintptr(", oper, tidyComment(" ", &n.Token)) 7551 p.multiplicativeExpression(f, n.MultiplicativeExpression, rt, exprValue, flags) 7552 p.w(")") 7553 if sz := lt.Elem().Size(); sz != 1 { 7554 p.w("*%d", sz) 7555 } 7556 case lt.IsIntegerType() && rt.Kind() == cc.Ptr: // i +- p 7557 p.w("uintptr(") 7558 p.additiveExpression(f, n.AdditiveExpression, lt, exprValue, flags) 7559 p.w(")") 7560 if sz := rt.Elem().Size(); sz != 1 { 7561 p.w("*%d", sz) 7562 } 7563 p.w(" %s%s ", oper, tidyComment(" ", &n.Token)) 7564 p.multiplicativeExpression(f, n.MultiplicativeExpression, rt, exprValue, flags) 7565 case lt.IsIntegerType() && rt.Kind() == cc.Array: // i +- p 7566 panic(todo("", p.pos(n))) 7567 case lt.Kind() == cc.Ptr && rt.Kind() == cc.Ptr && oper == "-": // p - q 7568 p.w("(") 7569 p.additiveExpression(f, n.AdditiveExpression, n.Operand.Type(), exprValue, flags) 7570 p.w(" %s%s", oper, tidyComment(" ", &n.Token)) 7571 p.multiplicativeExpression(f, n.MultiplicativeExpression, n.Operand.Type(), exprValue, flags) 7572 p.w(")/%d", lt.Elem().Size()) 7573 case lt.Kind() == cc.Ptr && rt.Kind() == cc.Array && oper == "-": // p - q 7574 defer p.w("%s", p.convertType(n, nil, n.Operand.Type(), 0)) 7575 p.w("(") 7576 p.additiveExpression(f, n.AdditiveExpression, lt, exprValue, flags) 7577 p.w(" %s%s", oper, tidyComment(" ", &n.Token)) 7578 p.multiplicativeExpression(f, n.MultiplicativeExpression, rt.Decay(), exprDecay, flags) 7579 p.w(")/%d", lt.Elem().Size()) 7580 case lt.Kind() == cc.Array && rt.Kind() == cc.Ptr && oper == "-": // p - q 7581 panic(todo("", p.pos(n))) 7582 case lt.Kind() == cc.Array && rt.Kind() == cc.Array && oper == "-": // p - q 7583 panic(todo("", p.pos(n))) 7584 default: 7585 panic(todo("", n.Position(), lt, rt, oper)) 7586 } 7587 } 7588 7589 func (p *project) binaryAdditiveExpressionUint128(f *function, n *cc.AdditiveExpression, oper string, t cc.Type, mode exprMode, flags flags) { 7590 // AdditiveExpression '+' MultiplicativeExpression 7591 defer p.w("%s", p.artithmeticBinaryExpression(n, n.Operand, t, &mode, flags)) 7592 p.additiveExpression(f, n.AdditiveExpression, n.Promote(), exprValue, flags) 7593 switch oper { 7594 case "+": 7595 p.w(".Add(") 7596 case "-": 7597 p.w(".Sub(") 7598 default: 7599 panic(todo("%q", oper)) 7600 } 7601 p.multiplicativeExpression(f, n.MultiplicativeExpression, n.Promote(), exprValue, flags) 7602 p.w(")") 7603 } 7604 7605 func (p *project) bitFieldPatch2(n cc.Node, a, b cc.Operand, promote cc.Type) string { 7606 //TODO bit field big endian 7607 var m uint64 7608 var w int 7609 switch { 7610 case a.Type().IsBitFieldType(): 7611 bf := a.Type().BitField() 7612 w = bf.BitFieldWidth() 7613 m = bf.Mask() >> bf.BitFieldOffset() 7614 if b.Type().IsBitFieldType() { 7615 bf = b.Type().BitField() 7616 w2 := bf.BitFieldWidth() 7617 if w2 != w { 7618 panic(todo("", p.pos(n))) 7619 } 7620 } 7621 case b.Type().IsBitFieldType(): 7622 bf := b.Type().BitField() 7623 w = bf.BitFieldWidth() 7624 m = bf.Mask() >> bf.BitFieldOffset() 7625 default: 7626 return "" 7627 } 7628 7629 p.w("((") 7630 switch { 7631 case promote.IsSignedType(): 7632 n := int(promote.Size())*8 - w 7633 var s string 7634 switch promote.Size() { 7635 case 4: 7636 s = fmt.Sprintf(")&%#x", int32(m)) 7637 default: 7638 s = fmt.Sprintf(")&%#x", m) 7639 } 7640 if n != 0 { 7641 s += fmt.Sprintf("<<%d>>%[1]d", n) 7642 } 7643 return ")" + s 7644 default: 7645 return fmt.Sprintf(")&%#x)", m) 7646 } 7647 } 7648 7649 func intAddOverflows(n cc.Node, lo, ro cc.Operand, oper string, promote cc.Type) bool { 7650 a, b, ok := getIntOperands(lo, ro) 7651 if !ok { 7652 return false 7653 } 7654 7655 switch oper { 7656 case "+": 7657 return overflows(a.Add(a, b), promote) 7658 case "-": 7659 return overflows(a.Sub(a, b), promote) 7660 default: 7661 panic(todo("", pos(n))) 7662 } 7663 } 7664 7665 func getIntOperands(a, b cc.Operand) (x, y *big.Int, ok bool) { 7666 switch n := a.Value().(type) { 7667 case cc.Int64Value: 7668 x = big.NewInt(int64(n)) 7669 case cc.Uint64Value: 7670 x = big.NewInt(0).SetUint64(uint64(n)) 7671 default: 7672 return nil, nil, false 7673 } 7674 7675 switch n := b.Value().(type) { 7676 case cc.Int64Value: 7677 return x, big.NewInt(int64(n)), true 7678 case cc.Uint64Value: 7679 return x, big.NewInt(0).SetUint64(uint64(n)), true 7680 default: 7681 return nil, nil, false 7682 } 7683 } 7684 7685 func overflows(n *big.Int, promote cc.Type) bool { 7686 switch k := promote.Kind(); { 7687 case k == cc.Int128, k == cc.UInt128: 7688 return false 7689 case isSigned(promote): 7690 switch promote.Size() { 7691 case 4: 7692 return n.Cmp(minInt32) < 0 || n.Cmp(maxInt32) > 0 7693 case 8: 7694 return n.Cmp(minInt64) < 0 || n.Cmp(maxInt64) > 0 7695 } 7696 default: 7697 switch promote.Size() { 7698 case 4: 7699 return n.Sign() < 0 || n.Cmp(maxUint32) > 0 7700 case 8: 7701 return n.Sign() < 0 || n.Cmp(maxUint64) > 0 7702 } 7703 } 7704 panic(todo("", promote.Size(), promote)) 7705 } 7706 7707 func (p *project) multiplicativeExpression(f *function, n *cc.MultiplicativeExpression, t cc.Type, mode exprMode, flags flags) { 7708 switch mode { 7709 case exprValue: 7710 p.multiplicativeExpressionValue(f, n, t, mode, flags) 7711 case exprVoid: 7712 p.multiplicativeExpressionVoid(f, n, t, mode, flags) 7713 case exprAddrOf: 7714 p.multiplicativeExpressionAddrOf(f, n, t, mode, flags) 7715 case exprBool: 7716 p.multiplicativeExpressionBool(f, n, t, mode, flags) 7717 case exprLValue: 7718 p.multiplicativeExpressionLValue(f, n, t, mode, flags) 7719 case exprPSelect: 7720 p.multiplicativeExpressionPSelect(f, n, t, mode, flags) 7721 case exprFunc: 7722 p.multiplicativeExpressionFunc(f, n, t, mode, flags) 7723 case exprSelect: 7724 p.multiplicativeExpressionSelect(f, n, t, mode, flags) 7725 case exprDecay: 7726 p.multiplicativeExpressionDecay(f, n, t, mode, flags) 7727 default: 7728 panic(todo("", n.Position(), mode)) 7729 } 7730 } 7731 7732 func (p *project) multiplicativeExpressionDecay(f *function, n *cc.MultiplicativeExpression, t cc.Type, mode exprMode, flags flags) { 7733 switch n.Case { 7734 case cc.MultiplicativeExpressionCast: // CastExpression 7735 p.castExpression(f, n.CastExpression, t, mode, flags) 7736 case cc.MultiplicativeExpressionMul: // MultiplicativeExpression '*' CastExpression 7737 panic(todo("", p.pos(n))) 7738 case cc.MultiplicativeExpressionDiv: // MultiplicativeExpression '/' CastExpression 7739 panic(todo("", p.pos(n))) 7740 case cc.MultiplicativeExpressionMod: // MultiplicativeExpression '%' CastExpression 7741 panic(todo("", p.pos(n))) 7742 default: 7743 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 7744 } 7745 } 7746 7747 func (p *project) multiplicativeExpressionSelect(f *function, n *cc.MultiplicativeExpression, t cc.Type, mode exprMode, flags flags) { 7748 switch n.Case { 7749 case cc.MultiplicativeExpressionCast: // CastExpression 7750 p.castExpression(f, n.CastExpression, t, mode, flags) 7751 case cc.MultiplicativeExpressionMul: // MultiplicativeExpression '*' CastExpression 7752 panic(todo("", p.pos(n))) 7753 case cc.MultiplicativeExpressionDiv: // MultiplicativeExpression '/' CastExpression 7754 panic(todo("", p.pos(n))) 7755 case cc.MultiplicativeExpressionMod: // MultiplicativeExpression '%' CastExpression 7756 panic(todo("", p.pos(n))) 7757 default: 7758 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 7759 } 7760 } 7761 7762 func (p *project) multiplicativeExpressionFunc(f *function, n *cc.MultiplicativeExpression, t cc.Type, mode exprMode, flags flags) { 7763 switch n.Case { 7764 case cc.MultiplicativeExpressionCast: // CastExpression 7765 p.castExpression(f, n.CastExpression, t, mode, flags) 7766 case cc.MultiplicativeExpressionMul: // MultiplicativeExpression '*' CastExpression 7767 panic(todo("", p.pos(n))) 7768 case cc.MultiplicativeExpressionDiv: // MultiplicativeExpression '/' CastExpression 7769 panic(todo("", p.pos(n))) 7770 case cc.MultiplicativeExpressionMod: // MultiplicativeExpression '%' CastExpression 7771 panic(todo("", p.pos(n))) 7772 default: 7773 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 7774 } 7775 } 7776 7777 func (p *project) multiplicativeExpressionPSelect(f *function, n *cc.MultiplicativeExpression, t cc.Type, mode exprMode, flags flags) { 7778 switch n.Case { 7779 case cc.MultiplicativeExpressionCast: // CastExpression 7780 p.castExpression(f, n.CastExpression, t, mode, flags) 7781 case cc.MultiplicativeExpressionMul: // MultiplicativeExpression '*' CastExpression 7782 panic(todo("", p.pos(n))) 7783 case cc.MultiplicativeExpressionDiv: // MultiplicativeExpression '/' CastExpression 7784 panic(todo("", p.pos(n))) 7785 case cc.MultiplicativeExpressionMod: // MultiplicativeExpression '%' CastExpression 7786 panic(todo("", p.pos(n))) 7787 default: 7788 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 7789 } 7790 } 7791 7792 func (p *project) multiplicativeExpressionLValue(f *function, n *cc.MultiplicativeExpression, t cc.Type, mode exprMode, flags flags) { 7793 switch n.Case { 7794 case cc.MultiplicativeExpressionCast: // CastExpression 7795 p.castExpression(f, n.CastExpression, t, mode, flags) 7796 case cc.MultiplicativeExpressionMul: // MultiplicativeExpression '*' CastExpression 7797 panic(todo("", p.pos(n))) 7798 case cc.MultiplicativeExpressionDiv: // MultiplicativeExpression '/' CastExpression 7799 panic(todo("", p.pos(n))) 7800 case cc.MultiplicativeExpressionMod: // MultiplicativeExpression '%' CastExpression 7801 panic(todo("", p.pos(n))) 7802 default: 7803 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 7804 } 7805 } 7806 7807 func (p *project) multiplicativeExpressionBool(f *function, n *cc.MultiplicativeExpression, t cc.Type, mode exprMode, flags flags) { 7808 switch n.Case { 7809 case cc.MultiplicativeExpressionCast: // CastExpression 7810 p.castExpression(f, n.CastExpression, t, mode, flags) 7811 case 7812 cc.MultiplicativeExpressionMul, // MultiplicativeExpression '*' CastExpression 7813 cc.MultiplicativeExpressionDiv, // MultiplicativeExpression '/' CastExpression 7814 cc.MultiplicativeExpressionMod: // MultiplicativeExpression '%' CastExpression 7815 7816 p.w("(") 7817 defer p.w(")") 7818 defer p.w(" != 0 ") 7819 p.multiplicativeExpression(f, n, t, exprValue, flags) 7820 default: 7821 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 7822 } 7823 } 7824 7825 func (p *project) multiplicativeExpressionAddrOf(f *function, n *cc.MultiplicativeExpression, t cc.Type, mode exprMode, flags flags) { 7826 switch n.Case { 7827 case cc.MultiplicativeExpressionCast: // CastExpression 7828 p.castExpression(f, n.CastExpression, t, mode, flags) 7829 case cc.MultiplicativeExpressionMul: // MultiplicativeExpression '*' CastExpression 7830 panic(todo("", p.pos(n))) 7831 case cc.MultiplicativeExpressionDiv: // MultiplicativeExpression '/' CastExpression 7832 panic(todo("", p.pos(n))) 7833 case cc.MultiplicativeExpressionMod: // MultiplicativeExpression '%' CastExpression 7834 panic(todo("", p.pos(n))) 7835 default: 7836 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 7837 } 7838 } 7839 7840 func (p *project) multiplicativeExpressionVoid(f *function, n *cc.MultiplicativeExpression, t cc.Type, mode exprMode, flags flags) { 7841 switch n.Case { 7842 case cc.MultiplicativeExpressionCast: // CastExpression 7843 p.castExpression(f, n.CastExpression, t, mode, flags) 7844 case cc.MultiplicativeExpressionMul: // MultiplicativeExpression '*' CastExpression 7845 panic(todo("", p.pos(n))) 7846 case cc.MultiplicativeExpressionDiv: // MultiplicativeExpression '/' CastExpression 7847 panic(todo("", p.pos(n))) 7848 case cc.MultiplicativeExpressionMod: // MultiplicativeExpression '%' CastExpression 7849 panic(todo("", p.pos(n))) 7850 default: 7851 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 7852 } 7853 } 7854 7855 func (p *project) multiplicativeExpressionValue(f *function, n *cc.MultiplicativeExpression, t cc.Type, mode exprMode, flags flags) { 7856 switch n.Case { 7857 case cc.MultiplicativeExpressionCast: // CastExpression 7858 p.castExpression(f, n.CastExpression, t, mode, flags) 7859 case cc.MultiplicativeExpressionMul: // MultiplicativeExpression '*' CastExpression 7860 p.binaryMultiplicativeExpression(f, n, "*", t, mode, flags) 7861 case cc.MultiplicativeExpressionDiv: // MultiplicativeExpression '/' CastExpression 7862 p.binaryMultiplicativeExpression(f, n, "/", t, mode, flags) 7863 case cc.MultiplicativeExpressionMod: // MultiplicativeExpression '%' CastExpression 7864 p.binaryMultiplicativeExpression(f, n, "%", t, mode, flags) 7865 default: 7866 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 7867 } 7868 } 7869 7870 func (p *project) binaryMultiplicativeExpression(f *function, n *cc.MultiplicativeExpression, oper string, t cc.Type, mode exprMode, flags flags) { 7871 // MultiplicativeExpression '*' CastExpression 7872 switch mode { 7873 case exprValue: 7874 p.binaryMultiplicativeExpressionValue(f, n, oper, t, mode, flags) 7875 default: 7876 panic(todo("", n.Position(), mode)) 7877 } 7878 } 7879 7880 func (p *project) binaryMultiplicativeExpressionValue(f *function, n *cc.MultiplicativeExpression, oper string, t cc.Type, mode exprMode, flags flags) { 7881 // MultiplicativeExpression '*' CastExpression 7882 7883 lt := n.MultiplicativeExpression.Operand.Type() 7884 rt := n.CastExpression.Operand.Type() 7885 switch lk, rk := lt.Kind(), rt.Kind(); { 7886 case 7887 lk == cc.UInt128 || rk == cc.UInt128, 7888 lk == cc.Int128 || rk == cc.Int128: 7889 7890 p.binaryMultiplicativeExpressionUint128(f, n, oper, t, mode, flags) 7891 return 7892 } 7893 7894 defer p.w("%s", p.artithmeticBinaryExpression(n, n.Operand, t, &mode, flags)) 7895 switch { 7896 case intMulOverflows(n, n.Operand, n.MultiplicativeExpression.Operand, n.CastExpression.Operand, oper, n.Promote()): 7897 p.multiplicativeExpression(f, n.MultiplicativeExpression, n.Promote(), exprValue, flags|fForceRuntimeConv) 7898 p.w(" %s%s", oper, tidyComment(" ", &n.Token)) 7899 p.castExpression(f, n.CastExpression, n.Promote(), exprValue, flags|fForceRuntimeConv) 7900 default: 7901 defer p.w("%s", p.bitFieldPatch2(n, n.MultiplicativeExpression.Operand, n.CastExpression.Operand, n.Promote())) //TODO bit field big endian 7902 var s string 7903 if isRealType(n.Operand) && n.Operand.Value() != nil { 7904 s = p.convertNil(n, n.Promote(), flags) 7905 } 7906 p.multiplicativeExpression(f, n.MultiplicativeExpression, n.Promote(), exprValue, flags) 7907 p.w("%s %s%s", s, oper, tidyComment(" ", &n.Token)) 7908 if (oper == "/" || oper == "%") && (isZeroReal(n.MultiplicativeExpression.Operand) || isZeroReal(n.CastExpression.Operand)) { 7909 p.w("%s%sFrom%[2]s(", p.task.crt, p.helperType(n, n.Promote())) 7910 defer p.w(")") 7911 } 7912 p.castExpression(f, n.CastExpression, n.Promote(), exprValue, flags) 7913 } 7914 } 7915 7916 func (p *project) binaryMultiplicativeExpressionUint128(f *function, n *cc.MultiplicativeExpression, oper string, t cc.Type, mode exprMode, flags flags) { 7917 // MultiplicativeExpression '*' CastExpression 7918 defer p.w("%s", p.artithmeticBinaryExpression(n, n.Operand, t, &mode, flags)) 7919 p.multiplicativeExpression(f, n.MultiplicativeExpression, n.Promote(), exprValue, flags) 7920 switch oper { 7921 case "*": 7922 p.w(".Mul(") 7923 case "/": 7924 p.w(".Div(") 7925 case "%": 7926 p.w(".Mod(") 7927 default: 7928 panic(todo("%q", oper)) 7929 } 7930 p.castExpression(f, n.CastExpression, n.Promote(), exprValue, flags) 7931 p.w(")") 7932 } 7933 7934 func isZeroReal(op cc.Operand) bool { 7935 switch x := op.Value().(type) { 7936 case cc.Float32Value: 7937 return x == 0 7938 case cc.Float64Value: 7939 return x == 0 7940 default: 7941 return false 7942 } 7943 } 7944 7945 func intMulOverflows(n cc.Node, r, lo, ro cc.Operand, oper string, promote cc.Type) bool { 7946 if (isReal(lo) && !isInf(lo) || isReal(ro) && !isInf(ro)) && isInf(r) { 7947 return true 7948 } 7949 7950 a, b, ok := getIntOperands(lo, ro) 7951 if !ok { 7952 return false 7953 } 7954 7955 switch oper { 7956 case "*": 7957 return overflows(a.Mul(a, b), promote) 7958 case "/": 7959 if b.Sign() == 0 { 7960 return true 7961 } 7962 7963 return overflows(a.Div(a, b), promote) 7964 case "%": 7965 if b.Sign() == 0 { 7966 return true 7967 } 7968 7969 return overflows(a.Mod(a, b), promote) 7970 default: 7971 panic(todo("", pos(n))) 7972 } 7973 } 7974 7975 func isReal(op cc.Operand) bool { 7976 switch op.Value().(type) { 7977 case cc.Float32Value, cc.Float64Value: 7978 return true 7979 default: 7980 return false 7981 } 7982 } 7983 7984 func isInf(op cc.Operand) bool { 7985 switch x := op.Value().(type) { 7986 case cc.Float32Value: 7987 return math.IsInf(float64(x), 0) 7988 case cc.Float64Value: 7989 return math.IsInf(float64(x), 0) 7990 default: 7991 return false 7992 } 7993 } 7994 7995 func (p *project) castExpression(f *function, n *cc.CastExpression, t cc.Type, mode exprMode, flags flags) { 7996 if n.Case == cc.CastExpressionCast { 7997 if f != nil && n.CastExpression.Operand.Type().Kind() == cc.Ptr { // void *__ccgo_va_arg(__builtin_va_list ap); 7998 sv := f.vaType 7999 f.vaType = n.TypeName.Type() 8000 defer func() { f.vaType = sv }() 8001 } 8002 } 8003 switch mode { 8004 case exprValue: 8005 p.castExpressionValue(f, n, t, mode, flags) 8006 case exprVoid: 8007 p.castExpressionVoid(f, n, t, mode, flags) 8008 case exprAddrOf: 8009 p.castExpressionAddrOf(f, n, t, mode, flags) 8010 case exprBool: 8011 p.castExpressionBool(f, n, t, mode, flags) 8012 case exprLValue: 8013 p.castExpressionLValue(f, n, t, mode, flags) 8014 case exprPSelect: 8015 p.castExpressionPSelect(f, n, t, mode, flags) 8016 case exprFunc: 8017 p.castExpressionFunc(f, n, t, mode, flags) 8018 case exprSelect: 8019 p.castExpressionSelect(f, n, t, mode, flags) 8020 case exprDecay: 8021 p.castExpressionDecay(f, n, t, mode, flags) 8022 default: 8023 panic(todo("", n.Position(), mode)) 8024 } 8025 } 8026 8027 func (p *project) castExpressionDecay(f *function, n *cc.CastExpression, t cc.Type, mode exprMode, flags flags) { 8028 switch n.Case { 8029 case cc.CastExpressionUnary: // UnaryExpression 8030 p.unaryExpression(f, n.UnaryExpression, t, mode, flags) 8031 case cc.CastExpressionCast: // '(' TypeName ')' CastExpression 8032 panic(todo("", p.pos(n))) 8033 default: 8034 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 8035 } 8036 } 8037 8038 func (p *project) castExpressionSelect(f *function, n *cc.CastExpression, t cc.Type, mode exprMode, flags flags) { 8039 switch n.Case { 8040 case cc.CastExpressionUnary: // UnaryExpression 8041 p.unaryExpression(f, n.UnaryExpression, t, mode, flags) 8042 case cc.CastExpressionCast: // '(' TypeName ')' CastExpression 8043 p.castExpression(f, n.CastExpression, n.TypeName.Type(), mode, flags) 8044 default: 8045 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 8046 } 8047 } 8048 8049 func (p *project) castExpressionFunc(f *function, n *cc.CastExpression, t cc.Type, mode exprMode, flags flags) { 8050 switch n.Case { 8051 case cc.CastExpressionUnary: // UnaryExpression 8052 p.unaryExpression(f, n.UnaryExpression, t, mode, flags) 8053 case cc.CastExpressionCast: // '(' TypeName ')' CastExpression 8054 ot := n.CastExpression.Operand.Type() 8055 tn := n.TypeName.Type() 8056 var ft cc.Type 8057 switch tn.Kind() { 8058 case cc.Ptr: 8059 switch et := ot.Elem(); et.Kind() { 8060 case cc.Function, cc.Void: 8061 // ok 8062 default: 8063 panic(todo("", p.pos(n), et, et.Kind())) 8064 } 8065 default: 8066 panic(todo("%v: %v, %v -> %v, %v -> %v, %v", p.pos(n), ot, ot.Kind(), tn, tn.Kind(), t, t.Kind())) 8067 } 8068 switch t.Kind() { 8069 case cc.Ptr: 8070 switch et := t.Elem(); et.Kind() { 8071 case cc.Function: 8072 ft = et 8073 default: 8074 panic(todo("", p.pos(n), et, et.Kind())) 8075 } 8076 default: 8077 panic(todo("%v: %v, %v -> %v, %v -> %v, %v", p.pos(n), ot, ot.Kind(), tn, tn.Kind(), t, t.Kind())) 8078 } 8079 switch ot.Kind() { 8080 case cc.Ptr: 8081 switch et := ot.Elem(); et.Kind() { 8082 case cc.Function, cc.Void: 8083 p.w("(*(*") 8084 p.functionSignature(n, f, ft, "") 8085 p.w(")(unsafe.Pointer(") 8086 p.castExpression(f, n.CastExpression, ot, exprAddrOf, flags) 8087 p.w(")))") 8088 default: 8089 panic(todo("", p.pos(n), et, et.Kind())) 8090 } 8091 default: 8092 panic(todo("%v: %v, %v -> %v, %v -> %v, %v", p.pos(n), ot, ot.Kind(), tn, tn.Kind(), t, t.Kind())) 8093 } 8094 default: 8095 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 8096 } 8097 } 8098 8099 func (p *project) castExpressionPSelect(f *function, n *cc.CastExpression, t cc.Type, mode exprMode, flags flags) { 8100 switch n.Case { 8101 case cc.CastExpressionUnary: // UnaryExpression 8102 p.unaryExpression(f, n.UnaryExpression, t, mode, flags) 8103 case cc.CastExpressionCast: // '(' TypeName ')' CastExpression 8104 p.castExpression(f, n.CastExpression, n.TypeName.Type(), mode, flags) 8105 default: 8106 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 8107 } 8108 } 8109 8110 func (p *project) castExpressionLValue(f *function, n *cc.CastExpression, t cc.Type, mode exprMode, flags flags) { 8111 switch n.Case { 8112 case cc.CastExpressionUnary: // UnaryExpression 8113 p.unaryExpression(f, n.UnaryExpression, t, mode, flags) 8114 case cc.CastExpressionCast: // '(' TypeName ')' CastExpression 8115 panic(todo("", p.pos(n))) 8116 default: 8117 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 8118 } 8119 } 8120 8121 func (p *project) castExpressionBool(f *function, n *cc.CastExpression, t cc.Type, mode exprMode, flags flags) { 8122 switch n.Case { 8123 case cc.CastExpressionUnary: // UnaryExpression 8124 p.unaryExpression(f, n.UnaryExpression, t, mode, flags) 8125 case cc.CastExpressionCast: // '(' TypeName ')' CastExpression 8126 p.w("(") 8127 defer p.w(")") 8128 defer p.w(" != 0 ") 8129 p.castExpression(f, n, n.Operand.Type(), exprValue, flags) 8130 default: 8131 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 8132 } 8133 } 8134 8135 func (p *project) castExpressionAddrOf(f *function, n *cc.CastExpression, t cc.Type, mode exprMode, flags flags) { 8136 switch n.Case { 8137 case cc.CastExpressionUnary: // UnaryExpression 8138 p.unaryExpression(f, n.UnaryExpression, t, mode, flags) 8139 case cc.CastExpressionCast: // '(' TypeName ')' CastExpression 8140 p.castExpressionAddrOf(f, n.CastExpression, t, mode, flags) 8141 default: 8142 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 8143 } 8144 } 8145 8146 func (p *project) castExpressionVoid(f *function, n *cc.CastExpression, t cc.Type, mode exprMode, flags flags) { 8147 switch n.Case { 8148 case cc.CastExpressionUnary: // UnaryExpression 8149 p.unaryExpression(f, n.UnaryExpression, t, mode, flags) 8150 case cc.CastExpressionCast: // '(' TypeName ')' CastExpression 8151 p.castExpression(f, n.CastExpression, t, mode, flags) 8152 default: 8153 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 8154 } 8155 } 8156 8157 func (p *project) castExpressionValue(f *function, n *cc.CastExpression, t cc.Type, mode exprMode, flags flags) { 8158 switch n.Case { 8159 case cc.CastExpressionUnary: // UnaryExpression 8160 p.unaryExpression(f, n.UnaryExpression, t, mode, flags) 8161 case cc.CastExpressionCast: // '(' TypeName ')' CastExpression 8162 if f != nil && p.pass1 && n.TypeName.Type().IsIntegerType() && n.CastExpression.Operand.Type().Kind() == cc.Array { 8163 if d := n.CastExpression.Declarator(); d != nil { 8164 f.pin(n, d) 8165 } 8166 } 8167 switch k := p.opKind(f, n.CastExpression, n.CastExpression.Operand.Type()); k { 8168 case opNormal, opBitfield: 8169 p.castExpressionValueNormal(f, n, t, mode, flags) 8170 case opArray: 8171 p.castExpressionValueArray(f, n, t, mode, flags) 8172 case opFunction: 8173 p.castExpressionValueFunction(f, n, t, mode, flags) 8174 case opArrayParameter: 8175 p.castExpressionValueNormal(f, n, t, mode, flags) 8176 default: 8177 panic(todo("", n.Position(), k)) 8178 } 8179 default: 8180 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 8181 } 8182 } 8183 8184 func (p *project) castExpressionValueArrayParameter(f *function, n *cc.CastExpression, t cc.Type, mode exprMode, flags flags) { 8185 // '(' TypeName ')' CastExpression 8186 tn := n.TypeName.Type() 8187 defer p.w("%s", p.convertType(n, tn, t, flags)) 8188 p.castExpression(f, n.CastExpression, tn, mode, flags) 8189 } 8190 8191 func (p *project) castExpressionValueFunction(f *function, n *cc.CastExpression, t cc.Type, mode exprMode, flags flags) { 8192 // '(' TypeName ')' CastExpression 8193 op := n.CastExpression.Operand 8194 tn := n.TypeName.Type() 8195 switch { 8196 case op.Type().Kind() == cc.Function: 8197 switch { 8198 case tn.Kind() == cc.Ptr && t.Kind() == cc.Ptr: 8199 p.castExpression(f, n.CastExpression, op.Type(), exprValue, flags) 8200 case tn.IsIntegerType(): 8201 p.w("%s(", p.typ(n, tn)) 8202 p.castExpression(f, n.CastExpression, op.Type(), exprValue, flags) 8203 p.w(")") 8204 default: 8205 panic(todo("%v: tn %v expr %v", n.Position(), tn, op.Type())) 8206 } 8207 default: 8208 panic(todo("%v: %v -> %v -> %v", p.pos(n), op.Type(), tn, t)) 8209 } 8210 } 8211 8212 func (p *project) castExpressionValueArray(f *function, n *cc.CastExpression, t cc.Type, mode exprMode, flags flags) { 8213 // '(' TypeName ')' CastExpression 8214 tn := n.TypeName.Type() 8215 switch { 8216 case tn.IsScalarType(): 8217 defer p.w("%s", p.convertType(n, nil, t, flags)) 8218 p.castExpression(f, n.CastExpression, tn, exprDecay, flags) 8219 default: 8220 panic(todo("", p.pos(n))) 8221 } 8222 } 8223 8224 func (p *project) castExpressionValueNormal(f *function, n *cc.CastExpression, t cc.Type, mode exprMode, flags flags) { 8225 // '(' TypeName ')' CastExpression 8226 op := n.CastExpression.Operand 8227 tn := n.TypeName.Type() 8228 switch { 8229 case op.Type().Kind() == cc.Ptr && tn.IsArithmeticType(): 8230 defer p.w("%s", p.convertType(n, nil, t, flags|fForceConv)) 8231 p.castExpression(f, n.CastExpression, op.Type(), mode, flags) 8232 case tn.IsArithmeticType(): 8233 switch { 8234 case (tn.Kind() == cc.Float || tn.Kind() == cc.Double) && op.Type().IsIntegerType() && op.Value() != nil && t.IsIntegerType(): 8235 panic(todo("", p.pos(n))) 8236 case isNegativeInt(op) && isUnsigned(t): 8237 defer p.w("%s", p.convertType(n, tn, t, flags|fForceConv)) 8238 p.castExpression(f, n.CastExpression, tn, exprValue, flags) 8239 default: 8240 defer p.w("%s", p.convertType(n, tn, t, flags)) 8241 p.castExpression(f, n.CastExpression, tn, exprValue, flags) 8242 } 8243 default: 8244 switch tn.Kind() { 8245 case cc.Ptr: 8246 switch { 8247 case t.Kind() == cc.Ptr && isNegativeInt(op): 8248 p.w("%s(", p.helperType2(n, op.Type(), tn)) 8249 defer p.w(")") 8250 p.castExpression(f, n.CastExpression, op.Type(), mode, flags) 8251 default: 8252 defer p.w("%s", p.convertType(n, tn, t, flags)) 8253 p.castExpression(f, n.CastExpression, tn, mode, flags) 8254 } 8255 case cc.Void: 8256 p.castExpression(f, n.CastExpression, tn, exprVoid, flags) 8257 default: 8258 panic(todo("%s: %s %s -> %s %s -> %s %s", n.Position(), op.Type(), op.Type().Kind(), tn, tn.Kind(), t, t.Kind())) 8259 } 8260 } 8261 } 8262 8263 func (p *project) unaryExpression(f *function, n *cc.UnaryExpression, t cc.Type, mode exprMode, flags flags) { 8264 switch mode { 8265 case exprLValue: 8266 p.unaryExpressionLValue(f, n, t, mode, flags) 8267 case exprValue: 8268 p.unaryExpressionValue(f, n, t, mode, flags) 8269 case exprVoid: 8270 p.unaryExpressionVoid(f, n, t, mode, flags) 8271 case exprAddrOf: 8272 p.unaryExpressionAddrOf(f, n, t, mode, flags) 8273 case exprBool: 8274 p.unaryExpressionBool(f, n, t, mode, flags) 8275 case exprPSelect: 8276 p.unaryExpressionPSelect(f, n, t, mode, flags) 8277 case exprFunc: 8278 p.unaryExpressionFunc(f, n, t, mode, flags) 8279 case exprSelect: 8280 p.unaryExpressionSelect(f, n, t, mode, flags) 8281 case exprDecay: 8282 p.unaryExpressionDecay(f, n, t, mode, flags) 8283 default: 8284 panic(todo("", n.Position(), mode)) 8285 } 8286 } 8287 8288 func (p *project) unaryExpressionDecay(f *function, n *cc.UnaryExpression, t cc.Type, mode exprMode, flags flags) { 8289 switch n.Case { 8290 case cc.UnaryExpressionPostfix: // PostfixExpression 8291 p.postfixExpression(f, n.PostfixExpression, t, mode, flags) 8292 case cc.UnaryExpressionInc: // "++" UnaryExpression 8293 panic(todo("", p.pos(n))) 8294 case cc.UnaryExpressionDec: // "--" UnaryExpression 8295 panic(todo("", p.pos(n))) 8296 case cc.UnaryExpressionAddrof: // '&' CastExpression 8297 panic(todo("", p.pos(n))) 8298 case cc.UnaryExpressionDeref: // '*' CastExpression 8299 p.castExpression(f, n.CastExpression, n.CastExpression.Operand.Type(), exprValue, flags) 8300 case cc.UnaryExpressionPlus: // '+' CastExpression 8301 panic(todo("", p.pos(n))) 8302 case cc.UnaryExpressionMinus: // '-' CastExpression 8303 panic(todo("", p.pos(n))) 8304 case cc.UnaryExpressionCpl: // '~' CastExpression 8305 panic(todo("", p.pos(n))) 8306 case cc.UnaryExpressionNot: // '!' CastExpression 8307 panic(todo("", p.pos(n))) 8308 case cc.UnaryExpressionSizeofExpr: // "sizeof" UnaryExpression 8309 panic(todo("", p.pos(n))) 8310 case cc.UnaryExpressionSizeofType: // "sizeof" '(' TypeName ')' 8311 panic(todo("", p.pos(n))) 8312 case cc.UnaryExpressionLabelAddr: // "&&" IDENTIFIER 8313 panic(todo("", p.pos(n))) 8314 case cc.UnaryExpressionAlignofExpr: // "_Alignof" UnaryExpression 8315 panic(todo("", p.pos(n))) 8316 case cc.UnaryExpressionAlignofType: // "_Alignof" '(' TypeName ')' 8317 panic(todo("", p.pos(n))) 8318 case cc.UnaryExpressionImag: // "__imag__" UnaryExpression 8319 panic(todo("", p.pos(n))) 8320 case cc.UnaryExpressionReal: // "__real__" UnaryExpression 8321 panic(todo("", p.pos(n))) 8322 default: 8323 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 8324 } 8325 } 8326 8327 func (p *project) unaryExpressionSelect(f *function, n *cc.UnaryExpression, t cc.Type, mode exprMode, flags flags) { 8328 switch n.Case { 8329 case cc.UnaryExpressionPostfix: // PostfixExpression 8330 p.postfixExpression(f, n.PostfixExpression, t, mode, flags) 8331 case cc.UnaryExpressionInc: // "++" UnaryExpression 8332 panic(todo("", n.Position())) 8333 case cc.UnaryExpressionDec: // "--" UnaryExpression 8334 panic(todo("", n.Position())) 8335 case cc.UnaryExpressionAddrof: // '&' CastExpression 8336 panic(todo("", p.pos(n))) 8337 case cc.UnaryExpressionDeref: // '*' CastExpression 8338 ot := n.CastExpression.Operand.Type() 8339 switch ot.Kind() { 8340 case cc.Ptr: 8341 switch et := ot.Elem(); et.Kind() { 8342 case 8343 cc.Struct, 8344 cc.Union: 8345 8346 p.w("(*(*%s)(unsafe.Pointer(", p.typ(n, n.Operand.Type())) 8347 p.castExpression(f, n.CastExpression, n.CastExpression.Operand.Type(), exprValue, flags) 8348 p.w(")))") 8349 default: 8350 panic(todo("", p.pos(n), et, et.Kind())) 8351 } 8352 case cc.Array: 8353 p.w("(*(*%s)(unsafe.Pointer(", p.typ(n, n.Operand.Type())) 8354 p.castExpression(f, n.CastExpression, n.CastExpression.Operand.Type(), exprAddrOf, flags) 8355 p.w(")))") 8356 default: 8357 panic(todo("", p.pos(n), ot, ot.Kind())) 8358 } 8359 case cc.UnaryExpressionPlus: // '+' CastExpression 8360 panic(todo("", p.pos(n))) 8361 case cc.UnaryExpressionMinus: // '-' CastExpression 8362 panic(todo("", p.pos(n))) 8363 case cc.UnaryExpressionCpl: // '~' CastExpression 8364 panic(todo("", p.pos(n))) 8365 case cc.UnaryExpressionNot: // '!' CastExpression 8366 panic(todo("", p.pos(n))) 8367 case cc.UnaryExpressionSizeofExpr: // "sizeof" UnaryExpression 8368 panic(todo("", p.pos(n))) 8369 case cc.UnaryExpressionSizeofType: // "sizeof" '(' TypeName ')' 8370 panic(todo("", p.pos(n))) 8371 case cc.UnaryExpressionLabelAddr: // "&&" IDENTIFIER 8372 panic(todo("", p.pos(n))) 8373 case cc.UnaryExpressionAlignofExpr: // "_Alignof" UnaryExpression 8374 panic(todo("", p.pos(n))) 8375 case cc.UnaryExpressionAlignofType: // "_Alignof" '(' TypeName ')' 8376 panic(todo("", p.pos(n))) 8377 case cc.UnaryExpressionImag: // "__imag__" UnaryExpression 8378 panic(todo("", p.pos(n))) 8379 case cc.UnaryExpressionReal: // "__real__" UnaryExpression 8380 panic(todo("", p.pos(n))) 8381 default: 8382 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 8383 } 8384 } 8385 8386 func (p *project) unaryExpressionFunc(f *function, n *cc.UnaryExpression, t cc.Type, mode exprMode, flags flags) { 8387 switch n.Case { 8388 case cc.UnaryExpressionPostfix: // PostfixExpression 8389 p.postfixExpression(f, n.PostfixExpression, t, mode, flags) 8390 case cc.UnaryExpressionInc: // "++" UnaryExpression 8391 panic(todo("", p.pos(n))) 8392 case cc.UnaryExpressionDec: // "--" UnaryExpression 8393 panic(todo("", p.pos(n))) 8394 case cc.UnaryExpressionAddrof: // '&' CastExpression 8395 panic(todo("", p.pos(n))) 8396 case cc.UnaryExpressionDeref: // '*' CastExpression 8397 ot := n.CastExpression.Operand.Type() 8398 switch ot.Kind() { 8399 case cc.Ptr: 8400 switch et := ot.Elem(); et.Kind() { 8401 case cc.Function: 8402 p.castExpression(f, n.CastExpression, ot, mode, flags|fAddrOfFuncPtrOk) 8403 case cc.Ptr: 8404 switch et2 := et.Elem(); et2.Kind() { 8405 case cc.Function: 8406 // C: (**)() 8407 p.fnVal(n, f, func() { p.castExpression(f, n.CastExpression, p.ptrType, exprValue, flags|fAddrOfFuncPtrOk) }, n.CastExpression.Declarator(), n.CastExpression.Operand.Type(), 1, mode, flags) 8408 default: 8409 panic(todo("", p.pos(n), et2, et2.Kind())) 8410 } 8411 default: 8412 panic(todo("", p.pos(n), et, et.Kind())) 8413 } 8414 case cc.Function: 8415 p.castExpression(f, n.CastExpression, ot, mode, flags|fAddrOfFuncPtrOk) 8416 default: 8417 panic(todo("", p.pos(n), ot, ot.Kind(), mode)) 8418 } 8419 case cc.UnaryExpressionPlus: // '+' CastExpression 8420 panic(todo("", p.pos(n))) 8421 case cc.UnaryExpressionMinus: // '-' CastExpression 8422 panic(todo("", p.pos(n))) 8423 case cc.UnaryExpressionCpl: // '~' CastExpression 8424 panic(todo("", p.pos(n))) 8425 case cc.UnaryExpressionNot: // '!' CastExpression 8426 panic(todo("", p.pos(n))) 8427 case cc.UnaryExpressionSizeofExpr: // "sizeof" UnaryExpression 8428 panic(todo("", p.pos(n))) 8429 case cc.UnaryExpressionSizeofType: // "sizeof" '(' TypeName ')' 8430 panic(todo("", p.pos(n))) 8431 case cc.UnaryExpressionLabelAddr: // "&&" IDENTIFIER 8432 panic(todo("", p.pos(n))) 8433 case cc.UnaryExpressionAlignofExpr: // "_Alignof" UnaryExpression 8434 panic(todo("", p.pos(n))) 8435 case cc.UnaryExpressionAlignofType: // "_Alignof" '(' TypeName ')' 8436 panic(todo("", p.pos(n))) 8437 case cc.UnaryExpressionImag: // "__imag__" UnaryExpression 8438 panic(todo("", p.pos(n))) 8439 case cc.UnaryExpressionReal: // "__real__" UnaryExpression 8440 panic(todo("", p.pos(n))) 8441 default: 8442 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 8443 } 8444 } 8445 8446 func (p *project) unaryExpressionPSelect(f *function, n *cc.UnaryExpression, t cc.Type, mode exprMode, flags flags) { 8447 switch n.Case { 8448 case cc.UnaryExpressionPostfix: // PostfixExpression 8449 p.postfixExpression(f, n.PostfixExpression, t, mode, flags) 8450 case cc.UnaryExpressionInc: // "++" UnaryExpression 8451 panic(todo("", n.Position())) 8452 case cc.UnaryExpressionDec: // "--" UnaryExpression 8453 panic(todo("", n.Position())) 8454 case cc.UnaryExpressionAddrof: // '&' CastExpression 8455 panic(todo("", n.Position())) 8456 //TODO- p.w("(*%s)(unsafe.Pointer(", p.typ(n, n.Operand.Type().Elem())) 8457 //TODO- p.unaryExpression(f, n, t, exprValue, flags) 8458 //TODO- p.w("))") 8459 case cc.UnaryExpressionDeref: // '*' CastExpression 8460 panic(todo("", n.Position())) 8461 //TODO- ot := n.CastExpression.Operand.Type() 8462 //TODO- switch ot.Kind() { 8463 //TODO- case cc.Ptr: 8464 //TODO- switch et := ot.Elem(); { 8465 //TODO- case et.Kind() == cc.Ptr: 8466 //TODO- switch et2 := et.Elem(); et2.Kind() { 8467 //TODO- case cc.Struct: 8468 //TODO- if et2.IsIncomplete() { 8469 //TODO- p.w("(*(**uintptr)(unsafe.Pointer(") 8470 //TODO- p.castExpression(f, n.CastExpression, t, exprValue, flags) 8471 //TODO- p.w(")))") 8472 //TODO- break 8473 //TODO- } 8474 8475 //TODO- p.w("(*(**%s)(unsafe.Pointer(", p.typ(n, n.Operand.Type().Elem())) 8476 //TODO- p.castExpression(f, n.CastExpression, t, exprValue, flags) 8477 //TODO- p.w(")))") 8478 //TODO- default: 8479 //TODO- panic(todo("", p.pos(n), et2, et2.Kind())) 8480 //TODO- } 8481 //TODO- default: 8482 //TODO- panic(todo("", p.pos(n), et, et.Kind())) 8483 //TODO- } 8484 //TODO- default: 8485 //TODO- panic(todo("", p.pos(n), ot, ot.Kind())) 8486 //TODO- } 8487 case cc.UnaryExpressionPlus: // '+' CastExpression 8488 panic(todo("", p.pos(n))) 8489 case cc.UnaryExpressionMinus: // '-' CastExpression 8490 panic(todo("", p.pos(n))) 8491 case cc.UnaryExpressionCpl: // '~' CastExpression 8492 panic(todo("", p.pos(n))) 8493 case cc.UnaryExpressionNot: // '!' CastExpression 8494 panic(todo("", p.pos(n))) 8495 case cc.UnaryExpressionSizeofExpr: // "sizeof" UnaryExpression 8496 panic(todo("", p.pos(n))) 8497 case cc.UnaryExpressionSizeofType: // "sizeof" '(' TypeName ')' 8498 panic(todo("", p.pos(n))) 8499 case cc.UnaryExpressionLabelAddr: // "&&" IDENTIFIER 8500 panic(todo("", p.pos(n))) 8501 case cc.UnaryExpressionAlignofExpr: // "_Alignof" UnaryExpression 8502 panic(todo("", p.pos(n))) 8503 case cc.UnaryExpressionAlignofType: // "_Alignof" '(' TypeName ')' 8504 panic(todo("", p.pos(n))) 8505 case cc.UnaryExpressionImag: // "__imag__" UnaryExpression 8506 panic(todo("", p.pos(n))) 8507 case cc.UnaryExpressionReal: // "__real__" UnaryExpression 8508 panic(todo("", p.pos(n))) 8509 default: 8510 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 8511 } 8512 } 8513 8514 func (p *project) unaryExpressionBool(f *function, n *cc.UnaryExpression, t cc.Type, mode exprMode, flags flags) { 8515 switch n.Case { 8516 case cc.UnaryExpressionPostfix: // PostfixExpression 8517 p.postfixExpression(f, n.PostfixExpression, t, mode, flags) 8518 case cc.UnaryExpressionNot: // '!' CastExpression 8519 p.w("!(") 8520 p.castExpression(f, n.CastExpression, t, mode, flags) 8521 p.w(")") 8522 default: 8523 p.w("(") 8524 defer p.w(")") 8525 defer p.w(" != 0 ") 8526 p.unaryExpression(f, n, t, exprValue, flags) 8527 } 8528 } 8529 8530 func (p *project) unaryExpressionAddrOf(f *function, n *cc.UnaryExpression, t cc.Type, mode exprMode, flags flags) { 8531 switch n.Case { 8532 case cc.UnaryExpressionPostfix: // PostfixExpression 8533 p.postfixExpression(f, n.PostfixExpression, t, mode, flags) 8534 case cc.UnaryExpressionInc: // "++" UnaryExpression 8535 panic(todo("", n.Position())) 8536 case cc.UnaryExpressionDec: // "--" UnaryExpression 8537 panic(todo("", n.Position())) 8538 case cc.UnaryExpressionAddrof: // '&' CastExpression 8539 panic(todo("", n.Position())) 8540 case cc.UnaryExpressionDeref: // '*' CastExpression 8541 ot := n.CastExpression.Operand.Type() 8542 switch ot.Kind() { 8543 case cc.Ptr: 8544 switch et := ot.Elem(); { 8545 case 8546 et.IsScalarType(), 8547 et.Kind() == cc.Struct, 8548 et.Kind() == cc.Union, 8549 et.Kind() == cc.Array: 8550 8551 p.unaryExpressionDeref(f, n, t, mode, flags) 8552 default: 8553 panic(todo("", p.pos(n), et, et.Kind())) 8554 } 8555 default: 8556 panic(todo("", p.pos(n), ot, ot.Kind())) 8557 } 8558 case cc.UnaryExpressionPlus: // '+' CastExpression 8559 panic(todo("", n.Position())) 8560 case cc.UnaryExpressionMinus: // '-' CastExpression 8561 panic(todo("", n.Position())) 8562 case cc.UnaryExpressionCpl: // '~' CastExpression 8563 panic(todo("", n.Position())) 8564 case cc.UnaryExpressionNot: // '!' CastExpression 8565 panic(todo("", n.Position())) 8566 case cc.UnaryExpressionSizeofExpr: // "sizeof" UnaryExpression 8567 panic(todo("", n.Position())) 8568 case cc.UnaryExpressionSizeofType: // "sizeof" '(' TypeName ')' 8569 panic(todo("", n.Position())) 8570 case cc.UnaryExpressionLabelAddr: // "&&" IDENTIFIER 8571 panic(todo("", n.Position())) 8572 case cc.UnaryExpressionAlignofExpr: // "_Alignof" UnaryExpression 8573 panic(todo("", n.Position())) 8574 case cc.UnaryExpressionAlignofType: // "_Alignof" '(' TypeName ')' 8575 panic(todo("", n.Position())) 8576 case cc.UnaryExpressionImag: // "__imag__" UnaryExpression 8577 panic(todo("", n.Position())) 8578 case cc.UnaryExpressionReal: // "__real__" UnaryExpression 8579 panic(todo("", n.Position())) 8580 default: 8581 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 8582 } 8583 } 8584 8585 func (p *project) unaryExpressionVoid(f *function, n *cc.UnaryExpression, t cc.Type, mode exprMode, flags flags) { 8586 switch n.Case { 8587 case cc.UnaryExpressionPostfix: // PostfixExpression 8588 p.postfixExpression(f, n.PostfixExpression, t, mode, flags) 8589 case cc.UnaryExpressionInc: // "++" UnaryExpression 8590 p.unaryExpressionPreIncDec(f, n, "++", "+=", t, mode, flags) 8591 case cc.UnaryExpressionDec: // "--" UnaryExpression 8592 p.unaryExpressionPreIncDec(f, n, "--", "-=", t, mode, flags) 8593 case cc.UnaryExpressionAddrof: // '&' CastExpression 8594 p.w("_ = ") 8595 switch { 8596 case n.CastExpression.Operand.Type().Kind() == cc.Array: 8597 panic(todo("", p.pos(n))) 8598 default: 8599 p.castExpression(f, n.CastExpression, n.CastExpression.Operand.Type(), exprAddrOf, flags) 8600 } 8601 case cc.UnaryExpressionDeref: // '*' CastExpression 8602 p.w("_ = *(*byte)(unsafe.Pointer(") 8603 p.castExpression(f, n.CastExpression, n.CastExpression.Operand.Type(), exprValue, flags) 8604 p.w("))") 8605 case 8606 cc.UnaryExpressionPlus, // '+' CastExpression 8607 cc.UnaryExpressionMinus, // '-' CastExpression 8608 cc.UnaryExpressionNot, // '!' CastExpression 8609 cc.UnaryExpressionCpl: // '~' CastExpression 8610 8611 p.w("_ = ") 8612 defer p.w("%s", p.convert(n, n.CastExpression.Operand, p.intType, flags)) 8613 p.castExpression(f, n.CastExpression, n.CastExpression.Operand.Type(), exprValue, flags) 8614 case cc.UnaryExpressionSizeofExpr: // "sizeof" UnaryExpression 8615 // nop 8616 case cc.UnaryExpressionSizeofType: // "sizeof" '(' TypeName ')' 8617 // nop 8618 case cc.UnaryExpressionLabelAddr: // "&&" IDENTIFIER 8619 panic(todo("", n.Position())) 8620 case cc.UnaryExpressionAlignofExpr: // "_Alignof" UnaryExpression 8621 panic(todo("", n.Position())) 8622 case cc.UnaryExpressionAlignofType: // "_Alignof" '(' TypeName ')' 8623 panic(todo("", n.Position())) 8624 case cc.UnaryExpressionImag: // "__imag__" UnaryExpression 8625 panic(todo("", n.Position())) 8626 case cc.UnaryExpressionReal: // "__real__" UnaryExpression 8627 panic(todo("", n.Position())) 8628 default: 8629 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 8630 } 8631 } 8632 8633 func (p *project) unaryExpressionValue(f *function, n *cc.UnaryExpression, t cc.Type, mode exprMode, flags flags) { 8634 switch n.Case { 8635 case cc.UnaryExpressionPostfix: // PostfixExpression 8636 p.postfixExpression(f, n.PostfixExpression, t, mode, flags) 8637 case cc.UnaryExpressionInc: // "++" UnaryExpression 8638 p.unaryExpressionPreIncDec(f, n, "++", "+=", t, mode, flags) 8639 case cc.UnaryExpressionDec: // "--" UnaryExpression 8640 p.unaryExpressionPreIncDec(f, n, "--", "-=", t, mode, flags) 8641 case cc.UnaryExpressionAddrof: // '&' CastExpression 8642 if t.Kind() != cc.Ptr { 8643 defer p.w("%s", p.convert(n, n.Operand, t, flags)) 8644 } 8645 switch { 8646 case n.CastExpression.Operand.Type().Kind() == cc.Array: 8647 panic(todo("", p.pos(n))) 8648 default: 8649 p.castExpression(f, n.CastExpression, n.CastExpression.Operand.Type(), exprAddrOf, flags) 8650 } 8651 case cc.UnaryExpressionDeref: // '*' CastExpression 8652 ot := n.CastExpression.Operand.Type() 8653 switch ot.Kind() { 8654 case cc.Ptr, cc.Array: 8655 switch et := ot.Elem(); { 8656 case 8657 et.IsScalarType(), 8658 et.Kind() == cc.Array, 8659 et.Kind() == cc.Struct, 8660 et.Kind() == cc.Union: 8661 8662 p.unaryExpressionDeref(f, n, t, mode, flags) 8663 case et.Kind() == cc.Function: 8664 p.castExpression(f, n.CastExpression, t, mode, flags) 8665 default: 8666 panic(todo("", p.pos(n), et, et.Kind())) 8667 } 8668 default: 8669 panic(todo("", p.pos(n), ot, ot.Kind())) 8670 } 8671 case cc.UnaryExpressionPlus: // '+' CastExpression 8672 p.w(" +") 8673 p.castExpression(f, n.CastExpression, t, mode, flags) 8674 case cc.UnaryExpressionMinus: // '-' CastExpression 8675 switch { 8676 case isNonNegativeInt(n.CastExpression.Operand) && t.Kind() == cc.Ptr: 8677 p.w(" -%sUintptr(", p.task.crt) 8678 p.castExpression(f, n.CastExpression, n.CastExpression.Operand.Type(), exprValue, flags) 8679 p.w(")") 8680 case isZeroReal(n.CastExpression.Operand): 8681 p.w(" -") 8682 defer p.w("%s", p.convert(n, n.CastExpression.Operand, t, flags)) 8683 p.w("%s%sFrom%[2]s(", p.task.crt, p.helperType(n, n.CastExpression.Operand.Type())) 8684 p.castExpression(f, n.CastExpression, n.CastExpression.Operand.Type(), exprValue, flags) 8685 p.w(")") 8686 case isNonNegativeInt(n.CastExpression.Operand) && isUnsigned(n.Operand.Type()): 8687 defer p.w("%s", p.convert(n, n.CastExpression.Operand, t, flags)) 8688 p.w("%sNeg%s(", p.task.crt, p.helperType(n, n.CastExpression.Operand.Type())) 8689 p.castExpression(f, n.CastExpression, n.CastExpression.Operand.Type(), exprValue, flags) 8690 p.w(")") 8691 default: 8692 defer p.w("%s", p.convert(n, n.Operand, t, flags)) 8693 p.w(" -") 8694 p.castExpression(f, n.CastExpression, n.Operand.Type(), exprValue, flags) 8695 } 8696 case cc.UnaryExpressionCpl: // '~' CastExpression 8697 defer p.w("%s", p.convert(n, n.Operand, t, flags)) 8698 switch { 8699 case n.CastExpression.Operand.Value() != nil: 8700 switch { 8701 case !t.IsIntegerType(): 8702 p.w(" ^") 8703 p.castExpression(f, n.CastExpression, n.Operand.Type(), exprValue, flags|fForceRuntimeConv) 8704 default: 8705 p.w("%sCpl%s(", p.task.crt, p.helperType(n, n.Operand.Type())) 8706 p.castExpression(f, n.CastExpression, n.Operand.Type(), exprValue, flags) 8707 p.w(")") 8708 } 8709 default: 8710 p.w(" ^") 8711 p.castExpression(f, n.CastExpression, n.Operand.Type(), exprValue, flags) 8712 } 8713 case cc.UnaryExpressionNot: // '!' CastExpression 8714 p.w("%sBool%s(!(", p.task.crt, p.helperType(n, t)) 8715 p.castExpression(f, n.CastExpression, n.CastExpression.Operand.Type(), exprBool, flags) 8716 p.w("))") 8717 case cc.UnaryExpressionSizeofExpr: // "sizeof" UnaryExpression 8718 p.checkSizeof(n.UnaryExpression, n.UnaryExpression.Operand.Type()) 8719 defer p.w("%s", p.convertNil(n, t, flags)) 8720 if d := n.UnaryExpression.Declarator(); d != nil { 8721 var isLocal bool 8722 if f != nil { 8723 if local := f.locals[d]; local != nil { 8724 isLocal = true 8725 if !local.isPinned { 8726 p.w("unsafe.Sizeof(%s)", local.name) 8727 return 8728 } 8729 } 8730 } 8731 8732 if !isLocal { 8733 if tld := p.tlds[d]; tld != nil { 8734 p.w("unsafe.Sizeof(%s)", tld.name) 8735 break 8736 } 8737 8738 nm := d.Name().String() 8739 if imp := p.imports[nm]; imp != nil { 8740 imp.used = true 8741 p.w("unsafe.Sizeof(%sX%s)", imp.qualifier, nm) 8742 break 8743 } 8744 } 8745 } 8746 8747 t := n.UnaryExpression.Operand.Type() 8748 if p.isArray(f, n.UnaryExpression, t) { 8749 p.w("%d", t.Len()*t.Elem().Size()) 8750 break 8751 } 8752 8753 s := "(0)" 8754 if !t.IsArithmeticType() { 8755 switch t.Kind() { 8756 case cc.Ptr: 8757 // ok 8758 case cc.Struct, cc.Union, cc.Array: 8759 s = "{}" 8760 default: 8761 panic(todo("", t.Kind())) 8762 } 8763 } 8764 switch t.Kind() { 8765 case cc.Int128, cc.UInt128: 8766 s = "{}" 8767 } 8768 p.w("unsafe.Sizeof(%s%s)", p.typ(n, t), s) 8769 case cc.UnaryExpressionSizeofType: // "sizeof" '(' TypeName ')' 8770 defer p.w("%s", p.convertNil(n, t, flags)) 8771 t := n.TypeName.Type() 8772 p.checkSizeof(n.TypeName, t) 8773 if t.Kind() == cc.Array { 8774 p.w("%d", t.Len()*t.Elem().Size()) 8775 break 8776 } 8777 8778 s := "(0)" 8779 if !t.IsArithmeticType() { 8780 switch t.Kind() { 8781 case cc.Ptr: 8782 // ok 8783 case cc.Struct, cc.Union: 8784 s = "{}" 8785 default: 8786 panic(todo("", t.Kind())) 8787 } 8788 } 8789 switch t.Kind() { 8790 case cc.Int128, cc.UInt128: 8791 s = "{}" 8792 } 8793 p.w("unsafe.Sizeof(%s%s)", p.typ(n, t), s) 8794 case cc.UnaryExpressionLabelAddr: // "&&" IDENTIFIER 8795 panic(todo("", n.Position())) 8796 case cc.UnaryExpressionAlignofExpr: // "_Alignof" UnaryExpression 8797 if n.TypeName.Type().Kind() == cc.Void { 8798 p.intConst(n, "", n.Operand, t, flags) 8799 break 8800 } 8801 8802 defer p.w("%s", p.convertNil(n, t, flags)) 8803 t := n.UnaryExpression.Operand.Type() 8804 if p.isArray(f, n.UnaryExpression, t) { 8805 p.w("%d", t.Len()*t.Elem().Size()) 8806 break 8807 } 8808 8809 s := "(0)" 8810 if !t.IsArithmeticType() { 8811 switch t.Kind() { 8812 case cc.Ptr: 8813 // ok 8814 case cc.Struct, cc.Union: 8815 s = "{}" 8816 default: 8817 panic(todo("", t.Kind())) 8818 } 8819 } 8820 p.w("unsafe.Alignof(%s%s)", p.typ(n, t), s) 8821 case cc.UnaryExpressionAlignofType: // "_Alignof" '(' TypeName ')' 8822 if n.TypeName.Type().Kind() == cc.Void { 8823 p.intConst(n, "", n.Operand, t, flags) 8824 break 8825 } 8826 8827 defer p.w("%s", p.convertNil(n, t, flags)) 8828 t := n.TypeName.Type() 8829 if t.Kind() == cc.Array { 8830 p.w("%d", t.Len()*t.Elem().Size()) 8831 break 8832 } 8833 8834 s := "(0)" 8835 if !t.IsArithmeticType() { 8836 switch t.Kind() { 8837 case cc.Ptr: 8838 // ok 8839 case cc.Struct, cc.Union: 8840 s = "{}" 8841 default: 8842 panic(todo("", t.Kind())) 8843 } 8844 } 8845 p.w("unsafe.Alignof(%s%s)", p.typ(n, t), s) 8846 case cc.UnaryExpressionImag: // "__imag__" UnaryExpression 8847 panic(todo("", n.Position())) 8848 case cc.UnaryExpressionReal: // "__real__" UnaryExpression 8849 panic(todo("", n.Position())) 8850 default: 8851 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 8852 } 8853 } 8854 8855 func (p *project) checkSizeof(n cc.Node, t cc.Type) { 8856 if !p.checkSizeof0(n, t) { 8857 p.err(n, "sizeof type %s: not supported", t.Alias()) 8858 } 8859 } 8860 8861 func (p *project) checkSizeof0(n cc.Node, t cc.Type) (ok bool) { 8862 switch t.Kind() { 8863 case cc.Array: 8864 return !t.IsVLA() 8865 case cc.Struct, cc.Union: 8866 nf := t.NumField() 8867 for i := []int{0}; i[0] < nf; i[0]++ { 8868 if !p.checkSizeof0(n, t.FieldByIndex(i).Type()) { 8869 return false 8870 } 8871 } 8872 } 8873 return true 8874 } 8875 8876 func (p *project) unaryExpressionLValue(f *function, n *cc.UnaryExpression, t cc.Type, mode exprMode, flags flags) { 8877 switch n.Case { 8878 case cc.UnaryExpressionPostfix: // PostfixExpression 8879 p.postfixExpression(f, n.PostfixExpression, t, mode, flags) 8880 case cc.UnaryExpressionInc: // "++" UnaryExpression 8881 panic(todo("", p.pos(n))) 8882 case cc.UnaryExpressionDec: // "--" UnaryExpression 8883 panic(todo("", p.pos(n))) 8884 case cc.UnaryExpressionAddrof: // '&' CastExpression 8885 panic(todo("", n.Position())) 8886 case cc.UnaryExpressionDeref: // '*' CastExpression 8887 ot := n.CastExpression.Operand.Type() 8888 switch ot.Kind() { 8889 case cc.Ptr, cc.Array: 8890 switch et := ot.Elem(); { 8891 case 8892 et.IsScalarType(), 8893 et.Kind() == cc.Struct, 8894 et.Kind() == cc.Union: 8895 8896 p.unaryExpressionDeref(f, n, t, mode, flags) 8897 default: 8898 panic(todo("", p.pos(n), et, et.Kind())) 8899 } 8900 default: 8901 panic(todo("", p.pos(n), ot, ot.Kind())) 8902 } 8903 case cc.UnaryExpressionPlus: // '+' CastExpression 8904 panic(todo("", n.Position())) 8905 case cc.UnaryExpressionMinus: // '-' CastExpression 8906 panic(todo("", n.Position())) 8907 case cc.UnaryExpressionCpl: // '~' CastExpression 8908 panic(todo("", n.Position())) 8909 case cc.UnaryExpressionNot: // '!' CastExpression 8910 panic(todo("", n.Position())) 8911 case cc.UnaryExpressionSizeofExpr: // "sizeof" UnaryExpression 8912 panic(todo("", n.Position())) 8913 case cc.UnaryExpressionSizeofType: // "sizeof" '(' TypeName ')' 8914 panic(todo("", n.Position())) 8915 case cc.UnaryExpressionLabelAddr: // "&&" IDENTIFIER 8916 panic(todo("", n.Position())) 8917 case cc.UnaryExpressionAlignofExpr: // "_Alignof" UnaryExpression 8918 panic(todo("", n.Position())) 8919 case cc.UnaryExpressionAlignofType: // "_Alignof" '(' TypeName ')' 8920 panic(todo("", n.Position())) 8921 case cc.UnaryExpressionImag: // "__imag__" UnaryExpression 8922 panic(todo("", n.Position())) 8923 case cc.UnaryExpressionReal: // "__real__" UnaryExpression 8924 panic(todo("", n.Position())) 8925 default: 8926 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 8927 } 8928 } 8929 8930 func isSigned(t cc.Type) bool { return t.IsIntegerType() && t.IsSignedType() } 8931 func isUnsigned(t cc.Type) bool { return t.IsIntegerType() && !t.IsSignedType() } 8932 8933 func isConstInteger(op cc.Operand) bool { 8934 switch op.Value().(type) { 8935 case cc.Int64Value, cc.Uint64Value: 8936 return true 8937 default: 8938 return false 8939 } 8940 } 8941 8942 func isNegativeInt(op cc.Operand) bool { 8943 switch x := op.Value().(type) { 8944 case cc.Int64Value: 8945 return x < 0 8946 default: 8947 return false 8948 } 8949 } 8950 8951 func isNonNegativeInt(op cc.Operand) bool { 8952 switch x := op.Value().(type) { 8953 case cc.Int64Value: 8954 return x >= 0 8955 case cc.Uint64Value: 8956 return true 8957 default: 8958 return false 8959 } 8960 } 8961 8962 func (p *project) unaryExpressionPreIncDec(f *function, n *cc.UnaryExpression, oper, oper2 string, t cc.Type, mode exprMode, flags flags) { 8963 // "++" UnaryExpression etc. 8964 switch mode { 8965 case exprValue: 8966 p.unaryExpressionPreIncDecValue(f, n, oper, oper2, t, mode, flags) 8967 case exprVoid: 8968 p.unaryExpressionPreIncDecVoid(f, n, oper, oper2, t, mode, flags) 8969 default: 8970 panic(todo("", p.pos(n), mode)) 8971 } 8972 } 8973 8974 func (p *project) unaryExpressionPreIncDecVoid(f *function, n *cc.UnaryExpression, oper, oper2 string, t cc.Type, mode exprMode, flags flags) { 8975 // "++" UnaryExpression etc. 8976 switch n.UnaryExpression.Operand.Type().Kind() { 8977 case cc.Int128, cc.UInt128: 8978 p.unaryExpressionLValue(f, n.UnaryExpression, n.UnaryExpression.Operand.Type(), exprLValue, 0) 8979 switch oper { 8980 case "++": 8981 p.w(".LValueInc()") 8982 case "--": 8983 p.w(".LValueDec()") 8984 default: 8985 panic(todo("internal error: %q", oper)) 8986 } 8987 return 8988 } 8989 8990 // "++" UnaryExpression etc. 8991 switch k := p.opKind(f, n.UnaryExpression, n.UnaryExpression.Operand.Type()); k { 8992 case opNormal: 8993 p.unaryExpressionPreIncDecVoidNormal(f, n, oper, oper2, t, mode, flags) 8994 case opArrayParameter: 8995 p.unaryExpressionPreIncDecVoidArrayParameter(f, n, oper, oper2, t, mode, flags) 8996 default: 8997 panic(todo("", n.Position(), k)) 8998 } 8999 } 9000 9001 func (p *project) unaryExpressionPreIncDecVoidArrayParameter(f *function, n *cc.UnaryExpression, oper, oper2 string, t cc.Type, mode exprMode, flags flags) { 9002 // "++" UnaryExpression etc. 9003 ut := n.UnaryExpression.Operand.Type() 9004 p.unaryExpression(f, n.UnaryExpression, n.UnaryExpression.Operand.Type(), exprLValue, flags) 9005 switch d := p.incDelta(n, ut); d { 9006 case 1: 9007 p.w("%s", oper) 9008 default: 9009 p.w("%s %d", oper2, d) 9010 } 9011 } 9012 9013 func (p *project) unaryExpressionPreIncDecVoidNormal(f *function, n *cc.UnaryExpression, oper, oper2 string, t cc.Type, mode exprMode, flags flags) { 9014 // "++" UnaryExpression etc. 9015 ut := n.UnaryExpression.Operand.Type() 9016 if d := n.UnaryExpression.Declarator(); d != nil && p.isVolatileOrAtomic(d) { 9017 x := "Dec" 9018 if oper == "++" { 9019 x = "Inc" 9020 } 9021 p.w("%sPre%sAtomic%s(&", p.task.crt, x, p.helperType(n, d.Type())) 9022 switch local, tld := f.locals[d], p.tlds[d]; { 9023 case local != nil: 9024 p.w("%s", local.name) 9025 case tld != nil: 9026 p.w("%s", tld.name) 9027 default: 9028 panic(todo("")) 9029 } 9030 p.w(", %d)", p.incDelta(n.PostfixExpression, ut)) 9031 return 9032 } 9033 9034 p.unaryExpression(f, n.UnaryExpression, n.UnaryExpression.Operand.Type(), exprLValue, flags) 9035 if ut.IsIntegerType() || ut.Kind() == cc.Ptr && p.incDelta(n, ut) == 1 { 9036 p.w("%s", oper) 9037 return 9038 } 9039 9040 switch ut.Kind() { 9041 case cc.Ptr, cc.Double, cc.Float: 9042 p.w("%s %d", oper2, p.incDelta(n, ut)) 9043 return 9044 } 9045 9046 panic(todo("", p.pos(n))) 9047 } 9048 9049 func (p *project) unaryExpressionPreIncDecValue(f *function, n *cc.UnaryExpression, oper, oper2 string, t cc.Type, mode exprMode, flags flags) { 9050 // "++" UnaryExpression etc. 9051 switch k := p.opKind(f, n.UnaryExpression, n.UnaryExpression.Operand.Type()); k { 9052 case opNormal: 9053 p.unaryExpressionPreIncDecValueNormal(f, n, oper, oper2, t, mode, flags) 9054 default: 9055 panic(todo("", n.Position(), k)) 9056 } 9057 } 9058 9059 func (p *project) unaryExpressionPreIncDecValueNormal(f *function, n *cc.UnaryExpression, oper, oper2 string, t cc.Type, mode exprMode, flags flags) { 9060 // "++" UnaryExpression etc. 9061 defer p.w("%s", p.convert(n, n.UnaryExpression.Operand, t, flags)) 9062 x := "Dec" 9063 if oper == "++" { 9064 x = "Inc" 9065 } 9066 ut := n.UnaryExpression.Operand.Type() 9067 if d := n.UnaryExpression.Declarator(); d != nil && p.isVolatileOrAtomic(d) { 9068 if !ut.IsIntegerType() { 9069 panic(todo("", n.Position(), d.Position(), ut)) 9070 } 9071 9072 flags |= fVolatileOk 9073 switch ut.Size() { 9074 case 4: 9075 switch { 9076 case ut.IsSignedType(): 9077 p.w("%sPre%sInt32(&", p.task.crt, x) 9078 p.unaryExpression(f, n.UnaryExpression, ut, exprLValue, flags) 9079 p.w(", 1)") 9080 default: 9081 p.w("%sPre%sInt32((*int32)(unsafe.Pointer(&", p.task.crt, x) 9082 p.unaryExpression(f, n.UnaryExpression, ut, exprLValue, flags) 9083 p.w(")), 1)") 9084 } 9085 case 8: 9086 switch { 9087 case ut.IsSignedType(): 9088 p.w("%sPre%sInt64(&", p.task.crt, x) 9089 p.unaryExpression(f, n.UnaryExpression, ut, exprLValue, flags) 9090 p.w(", 1)") 9091 default: 9092 p.w("%sPre%sInt64((*int64)(unsafe.Pointer(&", p.task.crt, x) 9093 p.unaryExpression(f, n.UnaryExpression, ut, exprLValue, flags) 9094 p.w(")), 1)") 9095 } 9096 default: 9097 panic(todo("", n.Position(), d.Position(), ut)) 9098 } 9099 return 9100 } 9101 9102 p.w("%sPre%s%s(&", p.task.crt, x, p.helperType(n, ut)) 9103 p.unaryExpression(f, n.UnaryExpression, ut, exprLValue, flags) 9104 p.w(", %d)", p.incDelta(n.PostfixExpression, ut)) 9105 } 9106 9107 func (p *project) unaryExpressionDeref(f *function, n *cc.UnaryExpression, t cc.Type, mode exprMode, flags flags) { 9108 // '*' CastExpression 9109 switch mode { 9110 case exprValue: 9111 p.unaryExpressionDerefValue(f, n, t, mode, flags) 9112 case exprLValue: 9113 p.unaryExpressionDerefLValue(f, n, t, mode, flags) 9114 case exprAddrOf: 9115 p.unaryExpressionDerefAddrOf(f, n, t, mode, flags) 9116 case exprBool: 9117 p.unaryExpressionDerefBool(f, n, t, mode, flags) 9118 default: 9119 panic(todo("", n.Position(), mode)) 9120 } 9121 } 9122 9123 func (p *project) unaryExpressionDerefBool(f *function, n *cc.UnaryExpression, t cc.Type, mode exprMode, flags flags) { 9124 // '*' CastExpression 9125 p.w("(") 9126 defer p.w(")") 9127 p.w("*(*%s)(unsafe.Pointer(", p.typ(n, n.Operand.Type())) 9128 p.castExpression(f, n.CastExpression, n.CastExpression.Operand.Type(), exprValue, flags) 9129 p.w(")) != 0") 9130 } 9131 9132 func (p *project) unaryExpressionDerefAddrOf(f *function, n *cc.UnaryExpression, t cc.Type, mode exprMode, flags flags) { 9133 // '*' CastExpression 9134 p.castExpression(f, n.CastExpression, n.CastExpression.Operand.Type(), exprValue, flags) 9135 } 9136 9137 func (p *project) unaryExpressionDerefLValue(f *function, n *cc.UnaryExpression, t cc.Type, mode exprMode, flags flags) { 9138 // '*' CastExpression 9139 switch k := p.opKind(f, n.CastExpression, n.CastExpression.Operand.Type()); k { 9140 case opNormal: 9141 p.unaryExpressionDerefLValueNormal(f, n, t, mode, flags) 9142 case opArray: 9143 panic(todo("", p.pos(n))) 9144 p.unaryExpressionDerefLValueArray(f, n, t, mode, flags) 9145 case opArrayParameter: 9146 p.unaryExpressionDerefLValueNormal(f, n, t, mode, flags) 9147 default: 9148 panic(todo("", n.Position(), k)) 9149 } 9150 } 9151 9152 func (p *project) unaryExpressionDerefLValueArray(f *function, n *cc.UnaryExpression, t cc.Type, mode exprMode, flags flags) { 9153 defer p.w("))%s", p.convertType(n, n.CastExpression.Operand.Type().Elem(), t, flags)) 9154 p.w("*(*%s)(unsafe.Pointer(", p.typ(n, n.Operand.Type())) 9155 p.castExpression(f, n.CastExpression, n.CastExpression.Operand.Type(), exprValue, flags) 9156 } 9157 9158 func (p *project) unaryExpressionDerefLValueNormal(f *function, n *cc.UnaryExpression, t cc.Type, mode exprMode, flags flags) { 9159 defer p.w("))%s", p.convertType(n, n.CastExpression.Operand.Type().Elem(), t, flags)) 9160 p.w("*(*%s)(unsafe.Pointer(", p.typ(n, n.Operand.Type())) 9161 p.castExpression(f, n.CastExpression, n.CastExpression.Operand.Type(), exprValue, flags) 9162 } 9163 9164 func (p *project) unaryExpressionDerefValue(f *function, n *cc.UnaryExpression, t cc.Type, mode exprMode, flags flags) { 9165 // '*' CastExpression 9166 switch k := p.opKind(f, n.CastExpression, n.CastExpression.Operand.Type()); k { 9167 case opNormal, opArrayParameter: 9168 p.unaryExpressionDerefValueNormal(f, n, t, mode, flags) 9169 case opArray: 9170 p.unaryExpressionDerefValueArray(f, n, t, mode, flags) 9171 default: 9172 panic(todo("", n.Position(), k)) 9173 } 9174 } 9175 9176 func (p *project) unaryExpressionDerefValueArray(f *function, n *cc.UnaryExpression, t cc.Type, mode exprMode, flags flags) { 9177 defer p.w("%s", p.convertType(n, n.CastExpression.Operand.Type().Elem(), t, flags)) 9178 p.castExpression(f, n.CastExpression, n.CastExpression.Operand.Type(), exprValue, flags) 9179 p.w("[0]") 9180 } 9181 9182 func (p *project) unaryExpressionDerefValueNormal(f *function, n *cc.UnaryExpression, t cc.Type, mode exprMode, flags flags) { 9183 // '*' CastExpression 9184 switch op := n.Operand.Type(); { 9185 case op.Kind() == cc.Array: 9186 p.castExpression(f, n.CastExpression, n.CastExpression.Operand.Type(), mode, flags) 9187 default: 9188 defer p.w("))%s", p.convertType(n, n.CastExpression.Operand.Type().Elem(), t, flags)) 9189 p.w("*(*%s)(unsafe.Pointer(", p.typ(n, n.Operand.Type())) 9190 p.castExpression(f, n.CastExpression, n.CastExpression.Operand.Type(), mode, flags) 9191 } 9192 } 9193 9194 func (p *project) postfixExpression(f *function, n *cc.PostfixExpression, t cc.Type, mode exprMode, flags flags) { 9195 switch mode { 9196 case exprLValue: 9197 p.postfixExpressionLValue(f, n, t, mode, flags) 9198 case exprValue: 9199 p.postfixExpressionValue(f, n, t, mode, flags) 9200 case exprVoid: 9201 p.postfixExpressionVoid(f, n, t, mode, flags) 9202 case exprFunc: 9203 p.postfixExpressionFunc(f, n, t, mode, flags) 9204 case exprAddrOf: 9205 p.postfixExpressionAddrOf(f, n, t, mode, flags) 9206 case exprSelect: 9207 p.postfixExpressionSelect(f, n, t, mode, flags) 9208 case exprPSelect: 9209 p.postfixExpressionPSelect(f, n, t, mode, flags) 9210 case exprBool: 9211 p.postfixExpressionBool(f, n, t, mode, flags) 9212 case exprDecay: 9213 p.postfixExpressionDecay(f, n, t, mode, flags) 9214 default: 9215 panic(todo("", n.Position(), mode)) 9216 } 9217 } 9218 9219 func (p *project) postfixExpressionDecay(f *function, n *cc.PostfixExpression, t cc.Type, mode exprMode, flags flags) { 9220 switch n.Case { 9221 case cc.PostfixExpressionPrimary: // PrimaryExpression 9222 p.primaryExpression(f, n.PrimaryExpression, t, mode, flags) 9223 case cc.PostfixExpressionIndex: // PostfixExpression '[' Expression ']' 9224 defer p.w("%s", p.convert(n, n.Operand, t, flags)) 9225 pe := n.PostfixExpression.Operand.Type() 9226 p.w("(") 9227 switch { 9228 case pe.Kind() == cc.Array: 9229 p.postfixExpression(f, n.PostfixExpression, pe, exprDecay, flags) 9230 case pe.Kind() == cc.Ptr: 9231 p.postfixExpression(f, n.PostfixExpression, pe, exprValue, flags) 9232 default: 9233 panic(todo("", p.pos(n))) 9234 } 9235 if !n.Expression.Operand.IsZero() { 9236 p.nzUintptr(n, func() { p.expression(f, n.Expression, n.Expression.Operand.Type(), exprValue, flags) }, n.Expression.Operand) 9237 if sz := pe.Elem().Size(); sz != 1 { 9238 p.w("*%d", sz) 9239 } 9240 } 9241 p.w(")") 9242 case cc.PostfixExpressionCall: // PostfixExpression '(' ArgumentExpressionList ')' 9243 panic(todo("", p.pos(n))) 9244 case cc.PostfixExpressionSelect: // PostfixExpression '.' IDENTIFIER 9245 p.postfixExpression(f, n, t, exprAddrOf, flags) 9246 case cc.PostfixExpressionPSelect: // PostfixExpression "->" IDENTIFIER 9247 p.postfixExpression(f, n, t, exprAddrOf, flags) 9248 case cc.PostfixExpressionInc: // PostfixExpression "++" 9249 panic(todo("", p.pos(n))) 9250 case cc.PostfixExpressionDec: // PostfixExpression "--" 9251 panic(todo("", p.pos(n))) 9252 case cc.PostfixExpressionComplit: // '(' TypeName ')' '{' InitializerList ',' '}' 9253 panic(todo("", p.pos(n))) 9254 case cc.PostfixExpressionTypeCmp: // "__builtin_types_compatible_p" '(' TypeName ',' TypeName ')' 9255 panic(todo("", p.pos(n))) 9256 case cc.PostfixExpressionChooseExpr: 9257 panic(todo("", p.pos(n))) 9258 default: 9259 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 9260 } 9261 } 9262 9263 func (p *project) postfixExpressionBool(f *function, n *cc.PostfixExpression, t cc.Type, mode exprMode, flags flags) { 9264 switch n.Case { 9265 case cc.PostfixExpressionPrimary: // PrimaryExpression 9266 p.primaryExpression(f, n.PrimaryExpression, t, mode, flags) 9267 case cc.PostfixExpressionIndex: // PostfixExpression '[' Expression ']' 9268 p.w("(") 9269 defer p.w(")") 9270 defer p.w(" != 0") 9271 p.postfixExpression(f, n, t, exprValue, flags) 9272 case cc.PostfixExpressionCall: // PostfixExpression '(' ArgumentExpressionList ')' 9273 p.postfixExpressionCall(f, n, t, mode, flags) 9274 case cc.PostfixExpressionSelect: // PostfixExpression '.' IDENTIFIER 9275 p.w("(") 9276 defer p.w(")") 9277 defer p.w(" != 0") 9278 p.postfixExpression(f, n, t, exprValue, flags) 9279 case cc.PostfixExpressionPSelect: // PostfixExpression "->" IDENTIFIER 9280 p.w("(") 9281 defer p.w(")") 9282 defer p.w(" != 0") 9283 p.postfixExpression(f, n, t, exprValue, flags) 9284 case cc.PostfixExpressionInc: // PostfixExpression "++" 9285 p.w("(") 9286 defer p.w(")") 9287 defer p.w(" != 0") 9288 p.postfixExpression(f, n, t, exprValue, flags) 9289 case cc.PostfixExpressionDec: // PostfixExpression "--" 9290 p.w("(") 9291 defer p.w(")") 9292 defer p.w(" != 0") 9293 p.postfixExpression(f, n, t, exprValue, flags) 9294 case cc.PostfixExpressionComplit: // '(' TypeName ')' '{' InitializerList ',' '}' 9295 panic(todo("", p.pos(n))) 9296 case cc.PostfixExpressionTypeCmp: // "__builtin_types_compatible_p" '(' TypeName ',' TypeName ')' 9297 panic(todo("", p.pos(n))) 9298 case cc.PostfixExpressionChooseExpr: 9299 p.w("(") 9300 defer p.w(")") 9301 defer p.w(" != 0") 9302 p.postfixExpression(f, n, t, exprValue, flags) 9303 default: 9304 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 9305 } 9306 } 9307 9308 func (p *project) postfixExpressionPSelect(f *function, n *cc.PostfixExpression, t cc.Type, mode exprMode, flags flags) { 9309 // PostfixExpression "->" IDENTIFIER 9310 switch n.Case { 9311 case cc.PostfixExpressionPrimary: // PrimaryExpression 9312 p.primaryExpression(f, n.PrimaryExpression, t, mode, flags) 9313 case cc.PostfixExpressionIndex: // PostfixExpression '[' Expression ']' 9314 p.postfixExpressionPSelectIndex(f, n, t, mode, flags) 9315 case cc.PostfixExpressionCall: // PostfixExpression '(' ArgumentExpressionList ')' 9316 p.postfixExpressionPSelectCall(f, n, t, mode, flags) 9317 case cc.PostfixExpressionSelect: // PostfixExpression '.' IDENTIFIER 9318 p.postfixExpressionPSelectSelect(f, n, t, mode, flags) 9319 case cc.PostfixExpressionPSelect: // PostfixExpression "->" IDENTIFIER 9320 p.postfixExpressionPSelectPSelect(f, n, t, mode, flags) 9321 case cc.PostfixExpressionInc: // PostfixExpression "++" 9322 panic(todo("", p.pos(n))) 9323 case cc.PostfixExpressionDec: // PostfixExpression "--" 9324 panic(todo("", p.pos(n))) 9325 case cc.PostfixExpressionComplit: // '(' TypeName ')' '{' InitializerList ',' '}' 9326 panic(todo("", p.pos(n))) 9327 case cc.PostfixExpressionTypeCmp: // "__builtin_types_compatible_p" '(' TypeName ',' TypeName ')' 9328 panic(todo("", p.pos(n))) 9329 case cc.PostfixExpressionChooseExpr: 9330 panic(todo("", p.pos(n))) 9331 default: 9332 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 9333 } 9334 } 9335 9336 func (p *project) postfixExpressionPSelectSelect(f *function, n *cc.PostfixExpression, t cc.Type, mode exprMode, flags flags) { 9337 // PostfixExpression '.' IDENTIFIER 9338 switch k := p.opKind(f, n.PostfixExpression, n.PostfixExpression.Operand.Type()); k { 9339 case opStruct: 9340 p.postfixExpressionPSelectSelectStruct(f, n, t, mode, flags) 9341 case opUnion: 9342 p.postfixExpressionPSelectSelectUnion(f, n, t, mode, flags) 9343 default: 9344 panic(todo("", n.Position(), k)) 9345 } 9346 } 9347 9348 func (p *project) postfixExpressionPSelectSelectUnion(f *function, n *cc.PostfixExpression, t cc.Type, mode exprMode, flags flags) { 9349 // PostfixExpression '.' IDENTIFIER 9350 fld := n.Field 9351 if fld.Offset() != 0 { 9352 p.err(&n.Token2, "internal error, union field with non-zero offset: %s %v", n.Token2.Value, fld.Offset()) 9353 } 9354 switch { 9355 case n.Operand.Type().IsBitFieldType(): 9356 panic(todo("", p.pos(n))) 9357 default: 9358 if fld.IsBitField() { 9359 p.err(&n.Token2, "internal error, wrong function for accessing a bit field: %s", n.Token2.Value) 9360 } 9361 pe := n.PostfixExpression.Operand.Type() 9362 defer p.w("%s", p.convert(n, n.Operand, t, flags)) 9363 p.w("(*(**%s)(unsafe.Pointer(", p.typ(n, n.Operand.Type().Elem())) 9364 p.postfixExpression(f, n.PostfixExpression, pe, exprAddrOf, flags) 9365 p.w("/* .%s */", p.fieldName(n, n.Token2.Value)) 9366 p.w(")))") 9367 } 9368 } 9369 9370 func (p *project) postfixExpressionPSelectSelectStruct(f *function, n *cc.PostfixExpression, t cc.Type, mode exprMode, flags flags) { 9371 // PostfixExpression '.' IDENTIFIER 9372 fld := n.Field 9373 switch { 9374 case n.Operand.Type().IsBitFieldType(): 9375 panic(todo("", p.pos(n))) 9376 default: 9377 if fld.IsBitField() { 9378 p.err(&n.Token2, "internal error, wrong function for accessing a bit field: %s", n.Token2.Value) 9379 } 9380 pe := n.PostfixExpression.Operand.Type() 9381 p.w("(*%s)(unsafe.Pointer(", p.typ(n, t.Elem())) 9382 p.postfixExpression(f, n.PostfixExpression, pe, exprSelect, flags) 9383 p.w(".%s", p.fieldName(n, n.Token2.Value)) 9384 p.w("))") 9385 9386 } 9387 } 9388 9389 func (p *project) postfixExpressionPSelectCall(f *function, n *cc.PostfixExpression, t cc.Type, mode exprMode, flags flags) { 9390 p.w("(*%s)(unsafe.Pointer(", p.typ(n, n.Operand.Type().Elem())) 9391 p.postfixExpressionCall(f, n, t, exprValue, flags) 9392 p.w("))") 9393 } 9394 9395 func (p *project) postfixExpressionPSelectIndex(f *function, n *cc.PostfixExpression, t cc.Type, mode exprMode, flags flags) { 9396 // PostfixExpression '[' Expression ']' 9397 switch k := p.opKind(f, n.PostfixExpression, n.PostfixExpression.Operand.Type()); k { 9398 // case opArray: 9399 // p.postfixExpressionSelectIndexArray(f, n, t, mode, flags) 9400 case opNormal: 9401 p.postfixExpressionPSelectIndexNormal(f, n, t, mode, flags) 9402 case opArrayParameter: 9403 p.postfixExpressionSelectIndexArrayParamater(f, n, t, mode, flags) 9404 default: 9405 panic(todo("", n.Position(), k)) 9406 } 9407 } 9408 9409 func (p *project) postfixExpressionPSelectIndexNormal(f *function, n *cc.PostfixExpression, t cc.Type, mode exprMode, flags flags) { 9410 pe := n.PostfixExpression.Operand.Type() 9411 // PostfixExpression '[' Expression ']' 9412 switch { 9413 case n.Operand.Type().IsBitFieldType(): 9414 panic(todo("", p.pos(n))) 9415 case n.Operand.Type().Kind() == cc.Array: 9416 panic(todo("", p.pos(n))) 9417 case pe.Kind() == cc.Array: 9418 p.w("(") 9419 defer p.w(")") 9420 p.w("(*(**%s)(unsafe.Pointer(", p.typ(n, n.Operand.Type().Elem())) 9421 p.postfixExpression(f, n.PostfixExpression, pe, exprAddrOf, flags) 9422 if !n.Expression.Operand.IsZero() { 9423 p.nzUintptr(n, func() { p.expression(f, n.Expression, n.Expression.Operand.Type(), exprValue, flags) }, n.Expression.Operand) 9424 if sz := pe.Decay().Elem().Size(); sz != 1 { 9425 p.w("*%d", sz) 9426 } 9427 } 9428 p.w(")))") 9429 default: 9430 p.w("(") 9431 defer p.w(")") 9432 p.w("(*(**%s)(unsafe.Pointer(", p.typ(n, n.Operand.Type().Elem())) 9433 p.postfixExpression(f, n.PostfixExpression, pe, exprValue, flags) 9434 if !n.Expression.Operand.IsZero() { 9435 p.nzUintptr(n, func() { p.expression(f, n.Expression, n.Expression.Operand.Type(), exprValue, flags) }, n.Expression.Operand) 9436 if sz := pe.Decay().Elem().Size(); sz != 1 { 9437 p.w("*%d", sz) 9438 } 9439 } 9440 p.w(")))") 9441 } 9442 } 9443 9444 func (p *project) postfixExpressionSelect(f *function, n *cc.PostfixExpression, t cc.Type, mode exprMode, flags flags) { 9445 // PostfixExpression '.' IDENTIFIER 9446 switch n.Case { 9447 case cc.PostfixExpressionPrimary: // PrimaryExpression 9448 p.primaryExpression(f, n.PrimaryExpression, t, mode, flags) 9449 case cc.PostfixExpressionIndex: // PostfixExpression '[' Expression ']' 9450 p.postfixExpressionSelectIndex(f, n, t, mode, flags) 9451 case cc.PostfixExpressionCall: // PostfixExpression '(' ArgumentExpressionList ')' 9452 p.postfixExpression(f, n, t, exprValue, flags) 9453 case cc.PostfixExpressionSelect: // PostfixExpression '.' IDENTIFIER 9454 p.postfixExpressionSelectSelect(f, n, t, mode, flags) 9455 case cc.PostfixExpressionPSelect: // PostfixExpression "->" IDENTIFIER 9456 p.postfixExpressionSelectPSelect(f, n, t, mode, flags) 9457 case cc.PostfixExpressionInc: // PostfixExpression "++" 9458 panic(todo("", p.pos(n))) 9459 case cc.PostfixExpressionDec: // PostfixExpression "--" 9460 panic(todo("", p.pos(n))) 9461 case cc.PostfixExpressionComplit: // '(' TypeName ')' '{' InitializerList ',' '}' 9462 panic(todo("", p.pos(n))) 9463 case cc.PostfixExpressionTypeCmp: // "__builtin_types_compatible_p" '(' TypeName ',' TypeName ')' 9464 panic(todo("", p.pos(n))) 9465 case cc.PostfixExpressionChooseExpr: 9466 panic(todo("", p.pos(n))) 9467 default: 9468 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 9469 } 9470 } 9471 9472 func (p *project) postfixExpressionPSelectPSelect(f *function, n *cc.PostfixExpression, t cc.Type, mode exprMode, flags flags) { 9473 // PostfixExpression "->" IDENTIFIER 9474 switch k := p.opKind(f, n.PostfixExpression, n.PostfixExpression.Operand.Type().Elem()); k { 9475 case opStruct: 9476 p.postfixExpressionPSelectPSelectStruct(f, n, t, mode, flags) 9477 default: 9478 panic(todo("", n.Position(), k)) 9479 } 9480 } 9481 9482 func (p *project) postfixExpressionPSelectPSelectStruct(f *function, n *cc.PostfixExpression, t cc.Type, mode exprMode, flags flags) { 9483 // PostfixExpression "->" IDENTIFIER 9484 fld := n.Field 9485 switch { 9486 case n.Operand.Type().IsBitFieldType(): 9487 panic(todo("", p.pos(n))) 9488 default: 9489 if fld.IsBitField() { 9490 p.err(&n.Token2, "internal error, wrong function for accessing a bit field: %s", n.Token2.Value) 9491 } 9492 pe := n.PostfixExpression.Operand.Type() 9493 defer p.w("%s", p.convert(n, n.Operand, t, flags)) 9494 p.w("(*%s)(unsafe.Pointer(", p.typ(n, t.Elem())) 9495 p.postfixExpression(f, n.PostfixExpression, pe, exprPSelect, flags) 9496 p.w(".%s", p.fieldName(n, n.Token2.Value)) 9497 p.w("))") 9498 } 9499 } 9500 9501 func (p *project) postfixExpressionSelectPSelect(f *function, n *cc.PostfixExpression, t cc.Type, mode exprMode, flags flags) { 9502 // PostfixExpression "->" IDENTIFIER 9503 switch k := p.opKind(f, n.PostfixExpression, n.PostfixExpression.Operand.Type().Elem()); k { 9504 case opStruct: 9505 p.postfixExpressionSelectPSelectStruct(f, n, t, mode, flags) 9506 case opUnion: 9507 p.postfixExpressionSelectPSelectUnion(f, n, t, mode, flags) 9508 default: 9509 panic(todo("", n.Position(), k)) 9510 } 9511 } 9512 9513 func (p *project) postfixExpressionSelectPSelectUnion(f *function, n *cc.PostfixExpression, t cc.Type, mode exprMode, flags flags) { 9514 // PostfixExpression "->" IDENTIFIER 9515 fld := n.Field 9516 if fld.Offset() != 0 { 9517 p.err(&n.Token2, "internal error, union field with non-zero offset: %s %v", n.Token2.Value, fld.Offset()) 9518 } 9519 switch { 9520 case n.Operand.Type().IsBitFieldType(): 9521 panic(todo("", p.pos(n))) 9522 case n.Operand.Type().Kind() == cc.Array: 9523 panic(todo("", p.pos(n))) 9524 default: 9525 if fld.IsBitField() { 9526 p.err(&n.Token2, "internal error, wrong function for accessing a bit field: %s", n.Token2.Value) 9527 } 9528 pe := n.PostfixExpression.Operand.Type() 9529 defer p.w("%s", p.convert(n, n.Operand, t, flags)) 9530 p.w("(*%s)(unsafe.Pointer(", p.typ(n, n.Operand.Type())) 9531 p.postfixExpression(f, n.PostfixExpression, pe, exprValue, flags) 9532 p.w("))") 9533 } 9534 } 9535 9536 func (p *project) postfixExpressionSelectPSelectStruct(f *function, n *cc.PostfixExpression, t cc.Type, mode exprMode, flags flags) { 9537 // PostfixExpression "->" IDENTIFIER 9538 fld := n.Field 9539 switch { 9540 case n.Operand.Type().IsBitFieldType(): 9541 panic(todo("", p.pos(n))) 9542 default: 9543 if fld.IsBitField() { 9544 p.err(&n.Token2, "internal error, wrong function for accessing a bit field: %s", n.Token2.Value) 9545 } 9546 pe := n.PostfixExpression.Operand.Type() 9547 defer p.w("%s", p.convert(n, n.Operand, t, flags)) 9548 et := n.PostfixExpression.Operand.Type().Elem() 9549 fld, path, ok := et.FieldByName2(n.Token2.Value) 9550 switch { 9551 case !ok: 9552 panic(todo("", n.Token.Position())) 9553 case fld.InUnion(): 9554 p.w("(*(*%s)(unsafe.Pointer(", p.typ(n, n.Operand.Type())) 9555 p.postfixExpression(f, n.PostfixExpression, pe, exprValue, flags) 9556 p.w("%s)))", nonZeroUintptr(pathOff(et, path))) 9557 case len(path) != 1: 9558 panic(todo("", n.Token.Position())) 9559 default: 9560 p.w("(*%s)(unsafe.Pointer(", p.typ(n, pe.Elem())) 9561 switch { 9562 case pe.Kind() == cc.Array: 9563 p.postfixExpression(f, n.PostfixExpression, pe, exprAddrOf, flags) 9564 default: 9565 p.postfixExpression(f, n.PostfixExpression, pe, exprValue, flags) 9566 } 9567 p.w(")).%s", p.fieldName(n, n.Token2.Value)) 9568 } 9569 } 9570 } 9571 9572 func (p *project) postfixExpressionSelectSelect(f *function, n *cc.PostfixExpression, t cc.Type, mode exprMode, flags flags) { 9573 // PostfixExpression '.' IDENTIFIER 9574 switch k := p.structOrUnion(n); k { 9575 case opUnion: 9576 p.postfixExpressionSelectSelectUnion(f, n, t, mode, flags) 9577 case opStruct: 9578 p.postfixExpressionSelectSelectStruct(f, n, t, mode, flags) 9579 default: 9580 panic(todo("", n.Position(), k)) 9581 } 9582 } 9583 9584 func (p *project) structOrUnion(n *cc.PostfixExpression) opKind { 9585 t := n.PostfixExpression.Operand.Type() 9586 switch n.Case { 9587 case cc.PostfixExpressionSelect: // PostfixExpression '.' IDENTIFIER 9588 // ok 9589 case cc.PostfixExpressionPSelect: // PostfixExpression "->" IDENTIFIER 9590 if t.Kind() == cc.Ptr { 9591 t = t.Elem() 9592 break 9593 } 9594 9595 p.err(n, "expected pointer type: %s", t) 9596 return opStruct 9597 } 9598 f, path, ok := t.FieldByName2(n.Token2.Src) 9599 if !ok { 9600 p.err(&n.Token, "unknown field: %s", n.Token2) 9601 return opStruct 9602 } 9603 9604 for len(path) > 1 { 9605 f = t.FieldByIndex(path[:1]) 9606 path = path[1:] 9607 t = f.Type() 9608 } 9609 if t.Kind() == cc.Union { 9610 // trc("%v: %q %v", n.Token2.Position(), n.Token2.Src, opUnion) 9611 return opUnion 9612 } 9613 9614 // trc("%v: %q %v", n.Token2.Position(), n.Token2.Src, opStruct) 9615 return opStruct 9616 } 9617 9618 func (p *project) postfixExpressionSelectSelectStruct(f *function, n *cc.PostfixExpression, t cc.Type, mode exprMode, flags flags) { 9619 // PostfixExpression '.' IDENTIFIER 9620 fld := n.Field 9621 switch { 9622 case n.Operand.Type().IsBitFieldType(): 9623 panic(todo("", p.pos(n))) 9624 case n.Operand.Type().Kind() == cc.Array: 9625 panic(todo("", p.pos(n))) 9626 default: 9627 if fld.IsBitField() { 9628 p.err(&n.Token2, "internal error, wrong function for accessing a bit field: %s", n.Token2.Value) 9629 } 9630 pe := n.PostfixExpression.Operand.Type() 9631 p.postfixExpression(f, n.PostfixExpression, pe, exprSelect, flags) 9632 p.w(".%s", p.fieldName(n, n.Token2.Value)) 9633 } 9634 } 9635 9636 func (p *project) postfixExpressionSelectSelectUnion(f *function, n *cc.PostfixExpression, t cc.Type, mode exprMode, flags flags) { 9637 // PostfixExpression '.' IDENTIFIER 9638 fld := n.Field 9639 if fld.Offset() != 0 { 9640 p.err(&n.Token2, "internal error, union field with non-zero offset: %s %v", n.Token2.Value, fld.Offset()) 9641 } 9642 switch { 9643 case n.Operand.Type().IsBitFieldType(): 9644 panic(todo("", p.pos(n))) 9645 case n.Operand.Type().Kind() == cc.Array: 9646 panic(todo("", p.pos(n))) 9647 default: 9648 if fld.IsBitField() { 9649 p.err(&n.Token2, "internal error, wrong function for accessing a bit field: %s", n.Token2.Value) 9650 } 9651 pe := n.PostfixExpression.Operand.Type() 9652 defer p.w("%s", p.convert(n, n.Operand, t, flags)) 9653 p.w("(*%s)(unsafe.Pointer(", p.typ(n, n.Operand.Type())) 9654 p.postfixExpression(f, n.PostfixExpression, pe, exprAddrOf, flags) 9655 p.w("))") 9656 } 9657 } 9658 9659 func (p *project) postfixExpressionSelectIndex(f *function, n *cc.PostfixExpression, t cc.Type, mode exprMode, flags flags) { 9660 // PostfixExpression '[' Expression ']' 9661 switch k := p.opKind(f, n.PostfixExpression, n.PostfixExpression.Operand.Type()); k { 9662 case opArray: 9663 p.postfixExpressionSelectIndexArray(f, n, t, mode, flags) 9664 case opNormal: 9665 p.postfixExpressionSelectIndexNormal(f, n, t, mode, flags) 9666 case opArrayParameter: 9667 p.postfixExpressionSelectIndexArrayParamater(f, n, t, mode, flags) 9668 default: 9669 panic(todo("", n.Position(), k)) 9670 } 9671 } 9672 9673 func (p *project) postfixExpressionSelectIndexArrayParamater(f *function, n *cc.PostfixExpression, t cc.Type, mode exprMode, flags flags) { 9674 pe := n.PostfixExpression.Operand.Type() 9675 // PostfixExpression '[' Expression ']' 9676 switch { 9677 case n.Operand.Type().IsBitFieldType(): 9678 panic(todo("", p.pos(n))) 9679 case n.Operand.Type().Kind() == cc.Array: 9680 panic(todo("", p.pos(n))) 9681 default: 9682 p.w("(*%s)(unsafe.Pointer(", p.typ(n, pe.Elem())) 9683 p.postfixExpression(f, n.PostfixExpression, pe, exprValue, flags) 9684 if !n.Expression.Operand.IsZero() { 9685 p.nzUintptr(n, func() { p.expression(f, n.Expression, n.Expression.Operand.Type(), exprValue, flags) }, n.Expression.Operand) 9686 if sz := pe.Decay().Elem().Size(); sz != 1 { 9687 p.w("*%d", sz) 9688 } 9689 } 9690 p.w("))") 9691 } 9692 } 9693 9694 func (p *project) postfixExpressionSelectIndexNormal(f *function, n *cc.PostfixExpression, t cc.Type, mode exprMode, flags flags) { 9695 pe := n.PostfixExpression.Operand.Type() 9696 // PostfixExpression '[' Expression ']' 9697 switch { 9698 case n.Operand.Type().IsBitFieldType(): 9699 panic(todo("", p.pos(n))) 9700 case n.Operand.Type().Kind() == cc.Array: 9701 panic(todo("", p.pos(n))) 9702 case pe.Kind() != cc.Ptr: 9703 p.w("(*%s)(unsafe.Pointer(", p.typ(n, pe.Elem())) 9704 p.postfixExpression(f, n.PostfixExpression, pe, exprAddrOf, flags) 9705 if !n.Expression.Operand.IsZero() { 9706 p.nzUintptr(n, func() { p.expression(f, n.Expression, n.Expression.Operand.Type(), exprValue, flags) }, n.Expression.Operand) 9707 if sz := pe.Decay().Elem().Size(); sz != 1 { 9708 p.w("*%d", sz) 9709 } 9710 } 9711 p.w("))") 9712 default: 9713 p.w("(*%s)(unsafe.Pointer(", p.typ(n, pe.Elem())) 9714 p.postfixExpression(f, n.PostfixExpression, pe, exprValue, flags) 9715 if !n.Expression.Operand.IsZero() { 9716 p.nzUintptr(n, func() { p.expression(f, n.Expression, n.Expression.Operand.Type(), exprValue, flags) }, n.Expression.Operand) 9717 if sz := pe.Decay().Elem().Size(); sz != 1 { 9718 p.w("*%d", sz) 9719 } 9720 } 9721 p.w("))") 9722 } 9723 } 9724 9725 func (p *project) postfixExpressionSelectIndexArray(f *function, n *cc.PostfixExpression, t cc.Type, mode exprMode, flags flags) { 9726 // PostfixExpression '[' Expression ']' 9727 switch { 9728 case n.Operand.Type().IsBitFieldType(): 9729 panic(todo("", p.pos(n))) 9730 case n.Operand.Type().Kind() == cc.Array: 9731 panic(todo("", p.pos(n))) 9732 default: 9733 pe := n.PostfixExpression.Operand.Type() 9734 p.postfixExpression(f, n.PostfixExpression, pe, mode, flags) 9735 p.w("[") 9736 p.expression(f, n.Expression, n.Expression.Operand.Type(), exprValue, flags) 9737 p.w("]") 9738 } 9739 } 9740 9741 func (p *project) postfixExpressionAddrOf(f *function, n *cc.PostfixExpression, t cc.Type, mode exprMode, flags flags) { 9742 switch n.Case { 9743 case cc.PostfixExpressionPrimary: // PrimaryExpression 9744 p.primaryExpression(f, n.PrimaryExpression, t, mode, flags) 9745 case cc.PostfixExpressionIndex: // PostfixExpression '[' Expression ']' 9746 p.postfixExpressionAddrOfIndex(f, n, t, mode, flags) 9747 case cc.PostfixExpressionCall: // PostfixExpression '(' ArgumentExpressionList ')' 9748 ot := n.Operand.Type() 9749 switch ot.Kind() { 9750 case cc.Struct, cc.Union: 9751 // ok 9752 default: 9753 p.err(n, "cannot take address of value of type %v", n.Operand.Type()) 9754 return 9755 } 9756 9757 if p.pass1 { 9758 off := roundup(f.off, uintptr(ot.Align())) 9759 f.complits[n] = off 9760 f.off += ot.Size() 9761 return 9762 } 9763 9764 off := f.complits[n] 9765 p.w("func() uintptr { *(*%s)(unsafe.Pointer(%s%s)) = ", p.typ(n, ot), f.bpName, nonZeroUintptr(off)) 9766 p.postfixExpressionValue(f, n, ot, exprValue, flags) 9767 p.w("; return %s%s }()", f.bpName, nonZeroUintptr(off)) 9768 case cc.PostfixExpressionSelect: // PostfixExpression '.' IDENTIFIER 9769 p.postfixExpressionAddrOfSelect(f, n, t, mode, flags) 9770 case cc.PostfixExpressionPSelect: // PostfixExpression "->" IDENTIFIER 9771 p.postfixExpressionAddrOfPSelect(f, n, t, mode, flags) 9772 case cc.PostfixExpressionInc: // PostfixExpression "++" 9773 p.postfixExpressionIncDec(f, n, "++", "+=", t, exprLValue, flags) 9774 case cc.PostfixExpressionDec: // PostfixExpression "--" 9775 panic(todo("", p.pos(n))) 9776 case cc.PostfixExpressionComplit: // '(' TypeName ')' '{' InitializerList ',' '}' 9777 tn := n.TypeName.Type() 9778 switch tn.Decay().Kind() { 9779 case cc.Ptr: 9780 switch tn.Kind() { 9781 case cc.Array: 9782 switch { 9783 case p.pass1: 9784 off := roundup(f.off, uintptr(tn.Elem().Align())) 9785 f.complits[n] = off 9786 f.off += tn.Size() 9787 default: 9788 off := f.complits[n] 9789 p.w(" func() uintptr { *(*%s)(unsafe.Pointer(%s%s)) = ", p.typ(n, tn), f.bpName, nonZeroUintptr(off)) 9790 p.initializer(f, &cc.Initializer{Case: cc.InitializerInitList, InitializerList: n.InitializerList}, tn, cc.Automatic, nil) 9791 p.w("; return %s%s }()", f.bpName, nonZeroUintptr(off)) 9792 } 9793 default: 9794 panic(todo("%v: %v", n.Position(), tn)) 9795 } 9796 default: 9797 switch { 9798 case p.pass1: 9799 off := roundup(f.off, uintptr(tn.Align())) 9800 f.complits[n] = off 9801 f.off += tn.Size() 9802 default: 9803 off := f.complits[n] 9804 p.w(" func() uintptr { *(*%s)(unsafe.Pointer(%s%s)) = ", p.typ(n, tn), f.bpName, nonZeroUintptr(off)) 9805 p.initializer(f, &cc.Initializer{Case: cc.InitializerInitList, InitializerList: n.InitializerList}, tn, cc.Automatic, nil) 9806 p.w("; return %s%s }()", f.bpName, nonZeroUintptr(off)) 9807 } 9808 } 9809 case cc.PostfixExpressionTypeCmp: // "__builtin_types_compatible_p" '(' TypeName ',' TypeName ')' 9810 panic(todo("", p.pos(n))) 9811 case cc.PostfixExpressionChooseExpr: 9812 panic(todo("", p.pos(n))) 9813 default: 9814 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 9815 } 9816 } 9817 9818 func (p *project) postfixExpressionAddrOfPSelect(f *function, n *cc.PostfixExpression, t cc.Type, mode exprMode, flags flags) { 9819 // PostfixExpression "->" IDENTIFIER 9820 p.w("(") 9821 defer p.w(")") 9822 pe := n.PostfixExpression.Operand.Type() 9823 switch { 9824 case n.Operand.Type().IsBitFieldType(): 9825 p.postfixExpression(f, n.PostfixExpression, pe, exprValue, flags) 9826 p.bitFldOff(pe.Elem(), n.Token2) 9827 case pe.Kind() == cc.Array: 9828 p.postfixExpression(f, n.PostfixExpression, pe, exprDecay, flags) 9829 p.fldOff(pe.Elem(), n.Token2) 9830 default: 9831 p.postfixExpression(f, n.PostfixExpression, pe, exprValue, flags) 9832 p.fldOff(pe.Elem(), n.Token2) 9833 } 9834 } 9835 9836 func (p *project) postfixExpressionAddrOfIndex(f *function, n *cc.PostfixExpression, t cc.Type, mode exprMode, flags flags) { 9837 // PostfixExpression '[' Expression ']' 9838 p.w("(") 9839 defer p.w(")") 9840 switch { 9841 case n.Operand.Type().Kind() == cc.Array: 9842 fallthrough 9843 default: 9844 pe := n.PostfixExpression.Operand.Type() 9845 d := n.PostfixExpression.Declarator() 9846 switch { 9847 case pe.Kind() == cc.Ptr: 9848 p.postfixExpression(f, n.PostfixExpression, pe, exprValue, flags) 9849 case pe.Kind() == cc.Array && d != nil && d.IsParameter: 9850 p.postfixExpression(f, n.PostfixExpression, pe, exprValue, flags) 9851 default: 9852 p.postfixExpression(f, n.PostfixExpression, pe, mode, flags) 9853 } 9854 if !n.Expression.Operand.IsZero() { 9855 p.nzUintptr(n, func() { p.expression(f, n.Expression, n.Expression.Operand.Type(), exprValue, flags) }, n.Expression.Operand) 9856 if sz := pe.Decay().Elem().Size(); sz != 1 { 9857 p.w("*%d", sz) 9858 } 9859 } 9860 } 9861 } 9862 9863 func (p *project) postfixExpressionAddrOfSelect(f *function, n *cc.PostfixExpression, t cc.Type, mode exprMode, flags flags) { 9864 // PostfixExpression '.' IDENTIFIER 9865 p.w("(") 9866 defer p.w(")") 9867 switch { 9868 case n.Operand.Type().IsBitFieldType(): 9869 pe := n.PostfixExpression.Operand.Type() 9870 p.postfixExpression(f, n.PostfixExpression, nil, mode, flags) 9871 p.bitFldOff(pe, n.Token2) 9872 case n.Operand.Type().Kind() == cc.Array: 9873 fallthrough 9874 default: 9875 pe := n.PostfixExpression.Operand.Type() 9876 p.postfixExpression(f, n.PostfixExpression, nil, mode, flags) 9877 p.fldOff(pe, n.Token2) 9878 } 9879 } 9880 9881 func (p *project) postfixExpressionFunc(f *function, n *cc.PostfixExpression, t cc.Type, mode exprMode, flags flags) { 9882 switch n.Case { 9883 case cc.PostfixExpressionPrimary: // PrimaryExpression 9884 p.primaryExpression(f, n.PrimaryExpression, t, mode, flags) 9885 case cc.PostfixExpressionIndex: // PostfixExpression '[' Expression ']' 9886 switch n.Operand.Type().Kind() { 9887 case cc.Ptr: 9888 switch et := n.Operand.Type().Elem(); et.Kind() { 9889 case cc.Function: 9890 p.fnVal(n, f, func() { 9891 p.postfixExpression(f, n, n.Operand.Type(), exprValue, flags) 9892 }, nil, n.Operand.Type(), 0, mode, flags) 9893 default: 9894 panic(todo("", p.pos(n), et, et.Kind())) 9895 } 9896 default: 9897 panic(todo("", n.Position(), n.Operand.Type())) 9898 } 9899 case cc.PostfixExpressionCall: // PostfixExpression '(' ArgumentExpressionList ')' 9900 switch n.Operand.Type().Kind() { 9901 case cc.Ptr: 9902 switch et := n.Operand.Type().Elem(); et.Kind() { 9903 case cc.Function: 9904 p.fnVal(n, f, func() { 9905 p.postfixExpressionCall(f, n, t, exprValue, flags) 9906 }, nil, n.Operand.Type(), 0, mode, flags) 9907 default: 9908 panic(todo("", p.pos(n), et, et.Kind())) 9909 } 9910 default: 9911 panic(todo("", n.Position(), n.Operand.Type())) 9912 } 9913 case cc.PostfixExpressionSelect: // PostfixExpression '.' IDENTIFIER 9914 switch n.Operand.Type().Kind() { 9915 case cc.Ptr: 9916 switch n.Operand.Type().Kind() { 9917 case cc.Ptr: 9918 switch et := n.Operand.Type().Elem(); et.Kind() { 9919 case cc.Function: 9920 p.fnVal(n, f, func() { p.postfixExpression(f, n, p.ptrType, exprValue, flags) }, nil, n.Operand.Type(), 0, mode, flags) 9921 default: 9922 panic(todo("", p.pos(n), et, et.Kind())) 9923 } 9924 default: 9925 panic(todo("", p.pos(n), n.Operand.Type(), n.Operand.Type().Kind())) 9926 } 9927 default: 9928 panic(todo("", n.Position(), n.Operand.Type())) 9929 } 9930 case cc.PostfixExpressionPSelect: // PostfixExpression "->" IDENTIFIER 9931 p.fnVal(n, f, func() { p.postfixExpression(f, n, p.ptrType, exprValue, flags) }, nil, n.Operand.Type(), 0, mode, flags) 9932 case cc.PostfixExpressionInc: // PostfixExpression "++" 9933 panic(todo("", p.pos(n))) 9934 case cc.PostfixExpressionDec: // PostfixExpression "--" 9935 panic(todo("", p.pos(n))) 9936 case cc.PostfixExpressionComplit: // '(' TypeName ')' '{' InitializerList ',' '}' 9937 panic(todo("", p.pos(n))) 9938 case cc.PostfixExpressionTypeCmp: // "__builtin_types_compatible_p" '(' TypeName ',' TypeName ')' 9939 panic(todo("", p.pos(n))) 9940 case cc.PostfixExpressionChooseExpr: 9941 panic(todo("", p.pos(n))) 9942 default: 9943 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 9944 } 9945 } 9946 9947 func (p *project) postfixExpressionVoid(f *function, n *cc.PostfixExpression, t cc.Type, mode exprMode, flags flags) { 9948 switch n.Case { 9949 case cc.PostfixExpressionPrimary: // PrimaryExpression 9950 p.primaryExpression(f, n.PrimaryExpression, t, mode, flags) 9951 case cc.PostfixExpressionIndex: // PostfixExpression '[' Expression ']' 9952 p.w("_ = ") 9953 p.postfixExpression(f, n, n.Operand.Type(), exprValue, flags) 9954 case cc.PostfixExpressionCall: // PostfixExpression '(' ArgumentExpressionList ')' 9955 p.postfixExpressionCall(f, n, n.Operand.Type(), mode, flags) 9956 case cc.PostfixExpressionSelect: // PostfixExpression '.' IDENTIFIER 9957 p.w("_ = ") 9958 p.postfixExpression(f, n, n.Operand.Type(), exprValue, flags) 9959 case cc.PostfixExpressionPSelect: // PostfixExpression "->" IDENTIFIER 9960 p.w("_ = ") 9961 p.postfixExpression(f, n, n.Operand.Type(), exprValue, flags) 9962 case cc.PostfixExpressionInc: // PostfixExpression "++" 9963 p.postfixExpressionIncDec(f, n, "++", "+=", t, mode, flags) 9964 case cc.PostfixExpressionDec: // PostfixExpression "--" 9965 p.postfixExpressionIncDec(f, n, "--", "-=", t, mode, flags) 9966 case cc.PostfixExpressionComplit: // '(' TypeName ')' '{' InitializerList ',' '}' 9967 tn := n.TypeName.Type() 9968 switch tn.Decay().Kind() { 9969 case cc.Ptr: 9970 switch tn.Kind() { 9971 case cc.Array: 9972 switch { 9973 case p.pass1: 9974 off := roundup(f.off, uintptr(tn.Elem().Align())) 9975 f.complits[n] = off 9976 f.off += tn.Size() 9977 default: 9978 off := f.complits[n] 9979 p.w("*(*%s)(unsafe.Pointer(%s%s)) = ", p.typ(n, tn), f.bpName, nonZeroUintptr(off)) 9980 p.initializer(f, &cc.Initializer{Case: cc.InitializerInitList, InitializerList: n.InitializerList}, tn, cc.Automatic, nil) 9981 } 9982 return 9983 default: 9984 panic(todo("%v: %v", n.Position(), tn)) 9985 } 9986 } 9987 9988 defer p.w("%s", p.convertType(n, tn, t, flags)) 9989 p.w("_ = ") 9990 p.initializer(f, &cc.Initializer{Case: cc.InitializerInitList, InitializerList: n.InitializerList}, tn, cc.Automatic, nil) 9991 case cc.PostfixExpressionTypeCmp: // "__builtin_types_compatible_p" '(' TypeName ',' TypeName ')' 9992 panic(todo("", p.pos(n))) 9993 case cc.PostfixExpressionChooseExpr: 9994 panic(todo("", p.pos(n))) 9995 default: 9996 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 9997 } 9998 } 9999 10000 func (p *project) postfixExpressionValue(f *function, n *cc.PostfixExpression, t cc.Type, mode exprMode, flags flags) { 10001 switch n.Case { 10002 case cc.PostfixExpressionPrimary: // PrimaryExpression 10003 if p.isArray(f, n.PrimaryExpression, n.Operand.Type()) && t.Kind() == cc.Ptr { 10004 mode = exprDecay 10005 } 10006 p.primaryExpression(f, n.PrimaryExpression, t, mode, flags) 10007 case cc.PostfixExpressionIndex: // PostfixExpression '[' Expression ']' 10008 p.postfixExpressionValueIndex(f, n, t, mode, flags) 10009 case cc.PostfixExpressionCall: // PostfixExpression '(' ArgumentExpressionList ')' 10010 p.postfixExpressionCall(f, n, t, mode, flags) 10011 case cc.PostfixExpressionSelect: // PostfixExpression '.' IDENTIFIER 10012 p.postfixExpressionValueSelect(f, n, t, mode, flags) 10013 case cc.PostfixExpressionPSelect: // PostfixExpression "->" IDENTIFIER 10014 p.postfixExpressionValuePSelect(f, n, t, mode, flags) 10015 case cc.PostfixExpressionInc: // PostfixExpression "++" 10016 p.postfixExpressionIncDec(f, n, "++", "+=", t, mode, flags) 10017 case cc.PostfixExpressionDec: // PostfixExpression "--" 10018 p.postfixExpressionIncDec(f, n, "--", "-=", t, mode, flags) 10019 case cc.PostfixExpressionComplit: // '(' TypeName ')' '{' InitializerList ',' '}' 10020 tn := n.TypeName.Type() 10021 switch tn.Decay().Kind() { 10022 case cc.Ptr: 10023 switch tn.Kind() { 10024 case cc.Array: 10025 switch { 10026 case p.pass1: 10027 off := roundup(f.off, uintptr(tn.Elem().Align())) 10028 f.complits[n] = off 10029 f.off += tn.Size() 10030 default: 10031 off := f.complits[n] 10032 p.w(" func() uintptr { *(*%s)(unsafe.Pointer(%s%s)) = ", p.typ(n, tn), f.bpName, nonZeroUintptr(off)) 10033 p.initializer(f, &cc.Initializer{Case: cc.InitializerInitList, InitializerList: n.InitializerList}, tn, cc.Automatic, nil) 10034 p.w("; return %s%s }()", f.bpName, nonZeroUintptr(off)) 10035 } 10036 return 10037 default: 10038 panic(todo("%v: %v", n.Position(), tn)) 10039 } 10040 } 10041 10042 defer p.w("%s", p.convertType(n, tn, t, flags)) 10043 p.initializer(f, &cc.Initializer{Case: cc.InitializerInitList, InitializerList: n.InitializerList}, tn, cc.Automatic, nil) 10044 case cc.PostfixExpressionTypeCmp: // "__builtin_types_compatible_p" '(' TypeName ',' TypeName ')' 10045 // Built-in Function: int __builtin_types_compatible_p (type1, type2) You can 10046 // use the built-in function __builtin_types_compatible_p to determine whether 10047 // two types are the same. 10048 // 10049 // This built-in function returns 1 if the unqualified versions of the types 10050 // type1 and type2 (which are types, not expressions) are compatible, 0 10051 // otherwise. The result of this built-in function can be used in integer 10052 // constant expressions. 10053 // 10054 // This built-in function ignores top level qualifiers (e.g., const, volatile). 10055 // For example, int is equivalent to const int. 10056 // 10057 // The type int[] and int[5] are compatible. On the other hand, int and char * 10058 // are not compatible, even if the size of their types, on the particular 10059 // architecture are the same. Also, the amount of pointer indirection is taken 10060 // into account when determining similarity. Consequently, short * is not 10061 // similar to short **. Furthermore, two types that are typedefed are 10062 // considered compatible if their underlying types are compatible. 10063 // 10064 // An enum type is not considered to be compatible with another enum type even 10065 // if both are compatible with the same integer type; this is what the C 10066 // standard specifies. For example, enum {foo, bar} is not similar to enum 10067 // {hot, dog}. 10068 // 10069 // You typically use this function in code whose execution varies depending on 10070 // the arguments’ types. For example: 10071 // 10072 // #define foo(x) \ 10073 // ({ \ 10074 // typeof (x) tmp = (x); \ 10075 // if (__builtin_types_compatible_p (typeof (x), long double)) \ 10076 // tmp = foo_long_double (tmp); \ 10077 // else if (__builtin_types_compatible_p (typeof (x), double)) \ 10078 // tmp = foo_double (tmp); \ 10079 // else if (__builtin_types_compatible_p (typeof (x), float)) \ 10080 // tmp = foo_float (tmp); \ 10081 // else \ 10082 // abort (); \ 10083 // tmp; \ 10084 // }) 10085 // 10086 // Note: This construct is only available for C. 10087 p.w(" %d ", n.Operand.Value()) 10088 case cc.PostfixExpressionChooseExpr: // "__builtin_choose_expr" '(' AssignmentExpression ',' AssignmentExpression ',' AssignmentExpression ')' 10089 // You can use the built-in function __builtin_choose_expr to evaluate code 10090 // depending on the value of a constant expression. This built-in function 10091 // returns exp1 if const_exp, which is an integer constant expression, is 10092 // nonzero. Otherwise it returns exp2. 10093 // 10094 // This built-in function is analogous to the ‘? :’ operator in C, except that 10095 // the expression returned has its type unaltered by promotion rules. Also, the 10096 // built-in function does not evaluate the expression that is not chosen. For 10097 // example, if const_exp evaluates to true, exp2 is not evaluated even if it 10098 // has side effects. 10099 // 10100 // This built-in function can return an lvalue if the chosen argument is an 10101 // lvalue. 10102 // 10103 // If exp1 is returned, the return type is the same as exp1’s type. Similarly, 10104 // if exp2 is returned, its return type is the same as exp2. 10105 // 10106 // Example: 10107 // 10108 // #define foo(x) \ 10109 // __builtin_choose_expr ( \ 10110 // __builtin_types_compatible_p (typeof (x), double), \ 10111 // foo_double (x), \ 10112 // __builtin_choose_expr ( \ 10113 // __builtin_types_compatible_p (typeof (x), float), \ 10114 // foo_float (x), \ 10115 // /* The void expression results in a compile-time error \ 10116 // when assigning the result to something. */ \ 10117 // (void)0)) 10118 // 10119 // Note: This construct is only available for C. Furthermore, the unused 10120 // expression (exp1 or exp2 depending on the value of const_exp) may still 10121 // generate syntax errors. This may change in future revisions. 10122 switch op := n.AssignmentExpression.Operand; { 10123 case op.IsNonZero(): 10124 p.assignmentExpression(f, n.AssignmentExpression2, t, mode, flags) 10125 case op.IsZero(): 10126 p.assignmentExpression(f, n.AssignmentExpression3, t, mode, flags) 10127 default: 10128 panic(todo("")) 10129 } 10130 default: 10131 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 10132 } 10133 } 10134 10135 func (p *project) postfixExpressionValuePSelect(f *function, n *cc.PostfixExpression, t cc.Type, mode exprMode, flags flags) { 10136 // PostfixExpression "->" IDENTIFIER 10137 switch k := p.opKind(f, n.PostfixExpression, n.PostfixExpression.Operand.Type().Elem()); k { 10138 case opStruct: 10139 p.postfixExpressionValuePSelectStruct(f, n, t, mode, flags) 10140 case opUnion: 10141 p.postfixExpressionValuePSelectUnion(f, n, t, mode, flags) 10142 default: 10143 panic(todo("", n.Position(), k)) 10144 } 10145 } 10146 10147 func (p *project) postfixExpressionValuePSelectUnion(f *function, n *cc.PostfixExpression, t cc.Type, mode exprMode, flags flags) { 10148 // PostfixExpression "->" IDENTIFIER 10149 fld := n.Field 10150 if fld.Offset() != 0 { 10151 p.err(&n.Token2, "internal error, union field with non-zero offset: %s %v", n.Token2.Value, fld.Offset()) 10152 } 10153 pe := n.PostfixExpression.Operand.Type() 10154 switch { 10155 case n.Operand.Type().IsBitFieldType(): 10156 panic(todo("", p.pos(n))) 10157 case n.Operand.Type().Kind() == cc.Array: 10158 panic(todo("", p.pos(n))) 10159 default: 10160 if fld.IsBitField() { 10161 p.err(&n.Token2, "internal error, wrong function for accessing a bit field: %s", n.Token2.Value) 10162 } 10163 defer p.w("%s", p.convert(n, n.Operand, t, flags)) 10164 p.w("*(*%s)(unsafe.Pointer(", p.typ(n, n.Operand.Type())) 10165 p.postfixExpression(f, n.PostfixExpression, pe, exprValue, flags) 10166 p.w("/* .%s */", p.fieldName(n, n.Token2.Value)) 10167 p.w("))") 10168 } 10169 } 10170 10171 func (p *project) postfixExpressionValuePSelectStruct(f *function, n *cc.PostfixExpression, t cc.Type, mode exprMode, flags flags) { 10172 // PostfixExpression "->" IDENTIFIER 10173 fld := n.Field 10174 pe := n.PostfixExpression.Operand.Type() 10175 k := p.opKind(f, n.PostfixExpression, n.PostfixExpression.Operand.Type()) 10176 switch { 10177 case n.Operand.Type().IsBitFieldType(): 10178 p.w("(") 10179 defer p.w(")") 10180 fld := n.Field 10181 defer p.w("%s", p.convertType(n, fld.Promote(), t, flags)) 10182 switch pe.Kind() { 10183 case cc.Array: 10184 x := p.convertType(n, nil, fld.Promote(), flags) 10185 p.w("*(*uint%d)(unsafe.Pointer(", fld.BitFieldBlockWidth()) 10186 p.postfixExpression(f, n.PostfixExpression, pe, exprDecay, flags) 10187 p.bitFldOff(pe.Elem(), n.Token2) 10188 p.w("))") 10189 p.w("&%#x>>%d%s", fld.Mask(), fld.BitFieldOffset(), x) 10190 if fld.Type().IsSignedType() { 10191 panic(todo("")) 10192 p.w("<<%d>>%[1]d", int(fld.Promote().Size()*8)-fld.BitFieldWidth()) 10193 } 10194 default: 10195 x := p.convertType(n, nil, fld.Promote(), flags) 10196 p.w("*(*uint%d)(unsafe.Pointer(", fld.BitFieldBlockWidth()) 10197 p.postfixExpression(f, n.PostfixExpression, pe, exprValue, flags) 10198 p.bitFldOff(pe.Elem(), n.Token2) 10199 p.w("))&%#x>>%d%s", fld.Mask(), fld.BitFieldOffset(), x) 10200 if fld.Type().IsSignedType() { 10201 p.w("<<%d>>%[1]d", int(fld.Promote().Size()*8)-fld.BitFieldWidth()) 10202 } 10203 } 10204 case n.Operand.Type().Kind() == cc.Array: 10205 defer p.w("%s", p.convertType(n, n.Operand.Type().Decay(), t.Decay(), flags)) 10206 p.postfixExpression(f, n.PostfixExpression, pe, exprValue, flags) 10207 p.fldOff(n.PostfixExpression.Operand.Type().Elem(), n.Token2) 10208 case k == opArray: 10209 defer p.w("%s", p.convert(n, n.Operand, t, flags)) 10210 p.postfixExpression(f, n.PostfixExpression, pe, exprValue, flags) 10211 p.w("[0].%s", p.fieldName(n, n.Token2.Value)) 10212 default: 10213 if fld.IsBitField() { 10214 p.err(&n.Token2, "internal error, wrong function for accessing a bit field: %s", n.Token2.Value) 10215 } 10216 defer p.w("%s", p.convert(n, n.Operand, t, flags)) 10217 et := pe.Elem() 10218 fld, path, ok := et.FieldByName2(n.Token2.Value) 10219 switch { 10220 case !ok: 10221 panic(todo("")) 10222 case fld.InUnion(): 10223 p.w("*(*%s)(unsafe.Pointer(", p.typ(n, n.Operand.Type())) 10224 p.postfixExpression(f, n.PostfixExpression, pe, exprValue, flags) 10225 p.w("%s))", nonZeroUintptr(pathOff(et, path))) 10226 case len(path) != 1: 10227 panic(todo("")) 10228 default: 10229 p.w("(*%s)(unsafe.Pointer(", p.typ(n, pe.Elem())) 10230 p.postfixExpression(f, n.PostfixExpression, pe, exprValue, flags) 10231 p.w(")).%s", p.fieldName(n, n.Token2.Value)) 10232 } 10233 } 10234 } 10235 10236 func pathOff(t cc.Type, path []int) (r uintptr) { 10237 for len(path) != 0 { 10238 f := t.FieldByIndex(path[:1]) 10239 r += f.Offset() 10240 path = path[1:] 10241 t = f.Type() 10242 } 10243 return r 10244 } 10245 10246 func (p *project) postfixExpressionValueIndex(f *function, n *cc.PostfixExpression, t cc.Type, mode exprMode, flags flags) { 10247 // PostfixExpression '[' Expression ']' 10248 switch k := p.opKind(f, n.PostfixExpression, n.PostfixExpression.Operand.Type()); k { 10249 case opArray: 10250 p.postfixExpressionValueIndexArray(f, n, t, mode, flags) 10251 case opNormal: 10252 p.postfixExpressionValueIndexNormal(f, n, t, mode, flags) 10253 case opArrayParameter: 10254 p.postfixExpressionValueIndexArrayParameter(f, n, t, mode, flags) 10255 default: 10256 panic(todo("", n.Position(), k)) 10257 } 10258 } 10259 func (p *project) postfixExpressionValueIndexArrayParameter(f *function, n *cc.PostfixExpression, t cc.Type, mode exprMode, flags flags) { 10260 // PostfixExpression '[' Expression ']' 10261 pe := n.PostfixExpression.Operand.Type() 10262 switch { 10263 case n.Operand.Type().Kind() == cc.Array: 10264 defer p.w("%s", p.convert(n, n.Operand, t, flags)) 10265 p.w("(") 10266 defer p.w(")") 10267 p.postfixExpression(f, n.PostfixExpression, pe, exprValue, flags) 10268 if !n.Expression.Operand.IsZero() { 10269 p.nzUintptr(n, func() { p.expression(f, n.Expression, n.Expression.Operand.Type(), exprValue, flags) }, n.Expression.Operand) 10270 if sz := pe.Elem().Size(); sz != 1 { 10271 p.w("*%d", sz) 10272 } 10273 } 10274 default: 10275 defer p.w("%s", p.convert(n, n.Operand, t, flags)) 10276 p.w("*(*%s)(unsafe.Pointer(", p.typ(n, pe.Elem())) 10277 p.postfixExpression(f, n.PostfixExpression, pe, exprValue, flags) 10278 if !n.Expression.Operand.IsZero() { 10279 p.nzUintptr(n, func() { p.expression(f, n.Expression, n.Expression.Operand.Type(), exprValue, flags) }, n.Expression.Operand) 10280 if sz := pe.Elem().Size(); sz != 1 { 10281 p.w("*%d", sz) 10282 } 10283 } 10284 p.w("))") 10285 } 10286 } 10287 10288 func (p *project) postfixExpressionValueIndexNormal(f *function, n *cc.PostfixExpression, t cc.Type, mode exprMode, flags flags) { 10289 // PostfixExpression '[' Expression ']' 10290 switch { 10291 case n.Operand.Type().Kind() == cc.Array: 10292 p.w("(") 10293 defer p.w(")") 10294 pe := n.PostfixExpression.Operand.Type() 10295 defer p.w("%s", p.convert(n, n.Operand, t, flags)) 10296 p.postfixExpression(f, n.PostfixExpression, pe, exprValue, flags) 10297 if !n.Expression.Operand.IsZero() { 10298 p.nzUintptr(n, func() { p.expression(f, n.Expression, n.Expression.Operand.Type(), exprValue, flags) }, n.Expression.Operand) 10299 if sz := pe.Elem().Size(); sz != 1 { 10300 p.w("*%d", sz) 10301 } 10302 } 10303 default: 10304 switch pe := n.PostfixExpression.Operand.Type(); pe.Kind() { 10305 case cc.Ptr: 10306 defer p.w("%s", p.convert(n, n.Operand, t, flags)) 10307 p.w("*(*%s)(unsafe.Pointer(", p.typ(n, pe.Elem())) 10308 p.postfixExpression(f, n.PostfixExpression, pe, exprValue, flags) 10309 if !n.Expression.Operand.IsZero() { 10310 p.nzUintptr(n, func() { p.expression(f, n.Expression, n.Expression.Operand.Type(), exprValue, flags) }, n.Expression.Operand) 10311 if sz := pe.Elem().Size(); sz != 1 { 10312 p.w("*%d", sz) 10313 } 10314 } 10315 p.w("))") 10316 case cc.Array: 10317 defer p.w("%s", p.convert(n, n.Operand, t, flags)) 10318 p.w("*(*%s)(unsafe.Pointer(", p.typ(n, pe.Elem())) 10319 p.postfixExpression(f, n.PostfixExpression, pe, exprDecay, flags) 10320 if !n.Expression.Operand.IsZero() { 10321 p.nzUintptr(n, func() { p.expression(f, n.Expression, n.Expression.Operand.Type(), exprValue, flags) }, n.Expression.Operand) 10322 if sz := pe.Elem().Size(); sz != 1 { 10323 p.w("*%d", sz) 10324 } 10325 } 10326 p.w("))") 10327 default: 10328 panic(todo("", p.pos(n), pe, pe.Kind())) 10329 } 10330 } 10331 } 10332 10333 func (p *project) postfixExpressionValueIndexArray(f *function, n *cc.PostfixExpression, t cc.Type, mode exprMode, flags flags) { 10334 // PostfixExpression '[' Expression ']' 10335 pe := n.PostfixExpression.Operand.Type() 10336 switch n.Operand.Type().Kind() { 10337 case cc.Array: 10338 defer p.w("%s", p.convert(n, n.Operand, t, flags)) 10339 p.w("(") 10340 defer p.w(")") 10341 p.postfixExpression(f, n.PostfixExpression, pe, exprDecay, flags) 10342 if !n.Expression.Operand.IsZero() { 10343 p.nzUintptr(n, func() { p.expression(f, n.Expression, n.Expression.Operand.Type(), exprValue, flags) }, n.Expression.Operand) 10344 if sz := pe.Elem().Size(); sz != 1 { 10345 p.w("*%d", sz) 10346 } 10347 } 10348 default: 10349 defer p.w("%s", p.convert(n, n.Operand, t, flags)) 10350 p.postfixExpression(f, n.PostfixExpression, pe, mode, flags) 10351 p.w("[") 10352 p.expression(f, n.Expression, n.Expression.Operand.Type(), exprValue, flags) 10353 p.w("]") 10354 } 10355 } 10356 10357 func (p *project) postfixExpressionValueSelect(f *function, n *cc.PostfixExpression, t cc.Type, mode exprMode, flags flags) { 10358 // PostfixExpression '.' IDENTIFIER 10359 switch k := p.opKind(f, n.PostfixExpression, n.PostfixExpression.Operand.Type()); k { 10360 case opStruct: 10361 p.postfixExpressionValueSelectStruct(f, n, t, mode, flags) 10362 case opUnion: 10363 p.postfixExpressionValueSelectUnion(f, n, t, mode, flags) 10364 default: 10365 panic(todo("", n.Position(), k)) 10366 } 10367 } 10368 10369 func (p *project) postfixExpressionValueSelectUnion(f *function, n *cc.PostfixExpression, t cc.Type, mode exprMode, flags flags) { 10370 // PostfixExpression '.' IDENTIFIER 10371 pe := n.PostfixExpression.Operand.Type() 10372 fld := n.Field 10373 switch { 10374 case n.Operand.Type().IsBitFieldType(): 10375 p.w("(") 10376 defer p.w("%s)", p.convertType(n, fld.Promote(), t, flags)) 10377 x := p.convertType(n, nil, fld.Promote(), flags) 10378 p.w("*(*uint%d)(unsafe.Pointer(", fld.BitFieldBlockWidth()) 10379 p.postfixExpression(f, n.PostfixExpression, pe, exprAddrOf, flags) 10380 p.bitFldOff(pe, n.Token2) 10381 p.w("))&%#x>>%d%s", fld.Mask(), fld.BitFieldOffset(), x) 10382 if fld.Type().IsSignedType() { 10383 p.w("<<%d>>%[1]d", int(fld.Promote().Size()*8)-fld.BitFieldWidth()) 10384 } 10385 case n.Operand.Type().Kind() == cc.Array: 10386 p.postfixExpression(f, n.PostfixExpression, pe, exprAddrOf, flags) 10387 default: 10388 if fld.IsBitField() { 10389 p.err(&n.Token2, "internal error, wrong function for accessing a bit field: %s", n.Token2.Value) 10390 } 10391 defer p.w("%s", p.convert(n, n.Operand, t, flags)) 10392 p.w("*(*%s)(unsafe.Pointer(", p.typ(n, n.Operand.Type())) 10393 p.postfixExpression(f, n.PostfixExpression, pe, exprAddrOf, flags) 10394 p.w("))") 10395 } 10396 } 10397 10398 func (p *project) postfixExpressionValueSelectStruct(f *function, n *cc.PostfixExpression, t cc.Type, mode exprMode, flags flags) { 10399 // PostfixExpression '.' IDENTIFIER 10400 pe := n.PostfixExpression.Operand.Type() 10401 fld := n.Field 10402 switch { 10403 case n.Operand.Type().IsBitFieldType(): 10404 p.w("(") 10405 defer p.w("%s)", p.convertType(n, fld.Promote(), t, flags)) 10406 x := p.convertType(n, nil, fld.Promote(), flags) 10407 p.w("*(*uint%d)(unsafe.Pointer(", fld.BitFieldBlockWidth()) 10408 p.postfixExpression(f, n.PostfixExpression, pe, exprAddrOf, flags) 10409 p.bitFldOff(pe, n.Token2) 10410 p.w("))&%#x>>%d%s", fld.Mask(), fld.BitFieldOffset(), x) 10411 if fld.Type().IsSignedType() { 10412 p.w("<<%d>>%[1]d", int(fld.Promote().Size()*8)-fld.BitFieldWidth()) 10413 } 10414 case n.Operand.Type().Kind() == cc.Array: 10415 p.postfixExpression(f, n, t, exprDecay, flags) 10416 case fld.InUnion(): 10417 defer p.w("%s", p.convert(n, n.Operand, t, flags)) 10418 p.w("*(*%s)(unsafe.Pointer(", p.typ(n, fld.Type())) 10419 p.postfixExpression(f, n.PostfixExpression, pe, exprAddrOf, flags) 10420 p.fldOff(pe, n.Token2) 10421 p.w("))") 10422 default: 10423 if fld.IsBitField() { 10424 p.err(&n.Token2, "internal error, wrong function for accessing a bit field: %s", n.Token2.Value) 10425 } 10426 defer p.w("%s", p.convert(n, n.Operand, t, flags)) 10427 p.postfixExpression(f, n.PostfixExpression, pe, exprSelect, flags) 10428 p.w(".%s", p.fieldName(n, n.Token2.Value)) 10429 } 10430 } 10431 10432 func (p *project) postfixExpressionLValue(f *function, n *cc.PostfixExpression, t cc.Type, mode exprMode, flags flags) { 10433 switch n.Case { 10434 case cc.PostfixExpressionPrimary: // PrimaryExpression 10435 p.primaryExpression(f, n.PrimaryExpression, t, mode, flags) 10436 case cc.PostfixExpressionIndex: // PostfixExpression '[' Expression ']' 10437 p.postfixExpressionLValueIndex(f, n, t, mode, flags) 10438 case cc.PostfixExpressionCall: // PostfixExpression '(' ArgumentExpressionList ')' 10439 panic(todo("", p.pos(n))) 10440 case cc.PostfixExpressionSelect: // PostfixExpression '.' IDENTIFIER 10441 p.postfixExpressionLValueSelect(f, n, t, mode, flags) 10442 case cc.PostfixExpressionPSelect: // PostfixExpression "->" IDENTIFIER 10443 p.postfixExpressionLValuePSelect(f, n, t, mode, flags) 10444 case cc.PostfixExpressionInc: // PostfixExpression "++" 10445 p.postfixExpressionIncDec(f, n, "++", "+=", t, mode, flags) 10446 case cc.PostfixExpressionDec: // PostfixExpression "--" 10447 p.postfixExpressionIncDec(f, n, "--", "-=", t, mode, flags) 10448 case cc.PostfixExpressionComplit: // '(' TypeName ')' '{' InitializerList ',' '}' 10449 panic(todo("", p.pos(n))) 10450 case cc.PostfixExpressionTypeCmp: // "__builtin_types_compatible_p" '(' TypeName ',' TypeName ')' 10451 panic(todo("", p.pos(n))) 10452 case cc.PostfixExpressionChooseExpr: 10453 panic(todo("", p.pos(n))) 10454 default: 10455 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 10456 } 10457 } 10458 10459 func (p *project) postfixExpressionLValuePSelect(f *function, n *cc.PostfixExpression, t cc.Type, mode exprMode, flags flags) { 10460 // PostfixExpression "->" IDENTIFIER 10461 pe := n.PostfixExpression 10462 switch k := p.opKind(f, n.PostfixExpression, n.PostfixExpression.Operand.Type().Elem()); k { 10463 case opStruct: 10464 if !p.inUnion(n, pe.Operand.Type().Elem(), n.Token2.Value) { 10465 p.postfixExpressionLValuePSelectStruct(f, n, t, mode, flags) 10466 break 10467 } 10468 10469 p.w("*(*%s)(unsafe.Pointer(", p.typ(n, n.Operand.Type())) 10470 p.postfixExpression(f, pe, pe.Operand.Type(), exprValue, flags) 10471 p.fldOff(pe.Operand.Type().Elem(), n.Token2) 10472 p.w("))") 10473 case opUnion: 10474 p.postfixExpressionLValuePSelectUnion(f, n, t, mode, flags) 10475 default: 10476 panic(todo("", n.Position(), k)) 10477 } 10478 } 10479 10480 func (p *project) postfixExpressionLValuePSelectUnion(f *function, n *cc.PostfixExpression, t cc.Type, mode exprMode, flags flags) { 10481 // PostfixExpression "->" IDENTIFIER 10482 fld := n.Field 10483 if fld.Offset() != 0 { 10484 p.err(&n.Token2, "internal error, union field with non-zero offset: %s %v", n.Token2.Value, fld.Offset()) 10485 } 10486 switch { 10487 case n.Operand.Type().IsBitFieldType(): 10488 panic(todo("", p.pos(n))) 10489 default: 10490 if fld.IsBitField() { 10491 p.err(&n.Token2, "internal error, wrong function for accessing a bit field: %s", n.Token2.Value) 10492 } 10493 pe := n.PostfixExpression.Operand.Type() 10494 defer p.w("%s", p.convert(n, n.Operand, t, flags)) 10495 p.w("(*(*%s)(unsafe.Pointer(", p.typ(n, n.Operand.Type())) 10496 p.postfixExpression(f, n.PostfixExpression, pe, exprValue, flags) 10497 p.w("/* .%s */", p.fieldName(n, n.Token2.Value)) 10498 p.w(")))") 10499 } 10500 } 10501 10502 func (p *project) postfixExpressionLValuePSelectStruct(f *function, n *cc.PostfixExpression, t cc.Type, mode exprMode, flags flags) { 10503 // PostfixExpression "->" IDENTIFIER 10504 fld := n.Field 10505 pe := n.PostfixExpression.Operand.Type() 10506 k := p.opKind(f, n.PostfixExpression, n.PostfixExpression.Operand.Type()) 10507 switch { 10508 case n.Operand.Type().IsBitFieldType(): 10509 panic(todo("", p.pos(n))) 10510 case k == opArray: 10511 defer p.w("%s", p.convert(n, n.Operand, t, flags)) 10512 p.postfixExpression(f, n.PostfixExpression, pe, exprValue, flags) 10513 p.w("[0].%s", p.fieldName(n, n.Token2.Value)) 10514 default: 10515 if fld.IsBitField() { 10516 p.err(&n.Token2, "internal error, wrong function for accessing a bit field: %s", n.Token2.Value) 10517 } 10518 defer p.w("%s", p.convert(n, n.Operand, t, flags)) 10519 p.w("(*%s)(unsafe.Pointer(", p.typ(n, pe.Elem())) 10520 p.postfixExpression(f, n.PostfixExpression, pe, exprValue, flags) 10521 p.w(")).%s", p.fieldName(n, n.Token2.Value)) 10522 } 10523 } 10524 10525 func (p *project) postfixExpressionLValueIndex(f *function, n *cc.PostfixExpression, t cc.Type, mode exprMode, flags flags) { 10526 // PostfixExpression '[' Expression ']' 10527 switch k := p.opKind(f, n.PostfixExpression, n.PostfixExpression.Operand.Type()); k { 10528 case opArray: 10529 p.postfixExpressionLValueIndexArray(f, n, t, mode, flags) 10530 case opNormal: 10531 p.postfixExpressionLValueIndexNormal(f, n, t, mode, flags) 10532 case opArrayParameter: 10533 p.postfixExpressionLValueIndexArrayParameter(f, n, t, mode, flags) 10534 default: 10535 panic(todo("", n.Position(), k)) 10536 } 10537 } 10538 10539 func (p *project) postfixExpressionLValueIndexArrayParameter(f *function, n *cc.PostfixExpression, t cc.Type, mode exprMode, flags flags) { 10540 // PostfixExpression '[' Expression ']' 10541 defer p.w("%s", p.convert(n, n.Operand, t, flags)) 10542 pe := n.PostfixExpression.Operand.Type() 10543 p.w("*(*%s)(unsafe.Pointer(", p.typ(n, pe.Elem())) 10544 p.postfixExpression(f, n.PostfixExpression, pe, exprValue, flags) 10545 if !n.Expression.Operand.IsZero() { 10546 p.nzUintptr(n, func() { p.expression(f, n.Expression, n.Expression.Operand.Type(), exprValue, flags) }, n.Expression.Operand) 10547 if sz := pe.Elem().Size(); sz != 1 { 10548 p.w("*%d", sz) 10549 } 10550 } 10551 p.w("))") 10552 } 10553 10554 func (p *project) postfixExpressionLValueIndexNormal(f *function, n *cc.PostfixExpression, t cc.Type, mode exprMode, flags flags) { 10555 // PostfixExpression '[' Expression ']' 10556 switch { 10557 case n.Operand.Type().Kind() == cc.Array: 10558 panic(todo("", p.pos(n))) 10559 default: 10560 switch pe := n.PostfixExpression.Operand.Type(); pe.Kind() { 10561 case cc.Ptr: 10562 defer p.w("%s", p.convert(n, n.Operand, t, flags)) 10563 p.w("*(*%s)(unsafe.Pointer(", p.typ(n, pe.Elem())) 10564 p.postfixExpression(f, n.PostfixExpression, pe, exprValue, flags) 10565 if !n.Expression.Operand.IsZero() { 10566 p.nzUintptr(n, func() { p.expression(f, n.Expression, n.Expression.Operand.Type(), exprValue, flags) }, n.Expression.Operand) 10567 if sz := pe.Elem().Size(); sz != 1 { 10568 p.w("*%d", sz) 10569 } 10570 } 10571 p.w("))") 10572 case cc.Array: 10573 defer p.w("%s", p.convert(n, n.Operand, t, flags)) 10574 p.w("*(*%s)(unsafe.Pointer(", p.typ(n, pe.Elem())) 10575 p.postfixExpression(f, n.PostfixExpression, pe, exprDecay, flags) 10576 if !n.Expression.Operand.IsZero() { 10577 p.nzUintptr(n, func() { p.expression(f, n.Expression, n.Expression.Operand.Type(), exprValue, flags) }, n.Expression.Operand) 10578 if sz := pe.Elem().Size(); sz != 1 { 10579 p.w("*%d", sz) 10580 } 10581 } 10582 p.w("))") 10583 default: 10584 panic(todo("", p.pos(n), pe)) 10585 } 10586 } 10587 } 10588 10589 func (p *project) postfixExpressionLValueIndexArray(f *function, n *cc.PostfixExpression, t cc.Type, mode exprMode, flags flags) { 10590 // PostfixExpression '[' Expression ']' 10591 pe := n.PostfixExpression.Operand.Type() 10592 p.postfixExpression(f, n.PostfixExpression, pe, mode, flags) 10593 p.w("[") 10594 p.expression(f, n.Expression, n.Expression.Operand.Type(), exprValue, flags) 10595 p.w("]") 10596 } 10597 10598 func (p *project) postfixExpressionLValueSelect(f *function, n *cc.PostfixExpression, t cc.Type, mode exprMode, flags flags) { 10599 // PostfixExpression '.' IDENTIFIER 10600 pe := n.PostfixExpression 10601 switch k := p.opKind(f, pe, pe.Operand.Type()); k { 10602 case opStruct: 10603 if !p.inUnion(n, pe.Operand.Type(), n.Token2.Value) { 10604 p.postfixExpressionLValueSelectStruct(f, n, t, mode, flags) 10605 break 10606 } 10607 10608 p.w("*(*%s)(unsafe.Pointer(", p.typ(n, n.Operand.Type())) 10609 p.postfixExpression(f, pe, pe.Operand.Type(), exprAddrOf, flags) 10610 p.fldOff(pe.Operand.Type(), n.Token2) 10611 p.w("))") 10612 case opUnion: 10613 p.postfixExpressionLValueSelectUnion(f, n, t, mode, flags) 10614 default: 10615 panic(todo("", n.Position(), k)) 10616 } 10617 } 10618 10619 func (p *project) inUnion(n cc.Node, t cc.Type, fname cc.StringID) bool { 10620 f, ok := t.FieldByName(fname) 10621 if !ok { 10622 p.err(n, "unknown field: %s", fname) 10623 return false 10624 } 10625 10626 return f.InUnion() 10627 } 10628 10629 func (p *project) postfixExpressionLValueSelectUnion(f *function, n *cc.PostfixExpression, t cc.Type, mode exprMode, flags flags) { 10630 fld := n.Field 10631 pe := n.PostfixExpression.Operand.Type() 10632 switch { 10633 case pe.Kind() == cc.Array: 10634 panic(todo("", p.pos(n))) 10635 case n.Operand.Type().IsBitFieldType(): 10636 panic(todo("", p.pos(n))) 10637 default: 10638 if fld.IsBitField() { 10639 p.err(&n.Token2, "internal error, wrong function for accessing a bit field: %s", n.Token2.Value) 10640 } 10641 p.w("*(*%s)(unsafe.Pointer(", p.typ(n, n.Operand.Type())) 10642 p.postfixExpression(f, n.PostfixExpression, pe, exprAddrOf, flags) 10643 nonZeroUintptr(fld.Offset()) 10644 p.w("))") 10645 } 10646 } 10647 10648 func (p *project) postfixExpressionLValueSelectStruct(f *function, n *cc.PostfixExpression, t cc.Type, mode exprMode, flags flags) { 10649 // PostfixExpression '.' IDENTIFIER 10650 fld := n.Field 10651 switch { 10652 case n.Operand.Type().IsBitFieldType(): 10653 panic(todo("", p.pos(n))) 10654 default: 10655 if fld.IsBitField() { 10656 p.err(&n.Token2, "internal error, wrong function for accessing a bit field: %s", n.Token2.Value) 10657 } 10658 pe := n.PostfixExpression.Operand.Type() 10659 p.postfixExpression(f, n.PostfixExpression, pe, exprSelect, flags) 10660 p.w(".%s", p.fieldName(n, n.Token2.Value)) 10661 } 10662 } 10663 10664 func (p *project) postfixExpressionIncDec(f *function, n *cc.PostfixExpression, oper, oper2 string, t cc.Type, mode exprMode, flags flags) { 10665 switch mode { 10666 case exprVoid: 10667 p.postfixExpressionIncDecVoid(f, n, oper, oper2, t, mode, flags) 10668 case exprLValue: 10669 p.postfixExpressionIncDecLValue(f, n, oper, oper2, t, mode, flags) 10670 case exprValue: 10671 p.postfixExpressionIncDecValue(f, n, oper, oper2, t, mode, flags) 10672 default: 10673 panic(todo("", mode)) 10674 } 10675 } 10676 10677 func (p *project) postfixExpressionIncDecValue(f *function, n *cc.PostfixExpression, oper, oper2 string, t cc.Type, mode exprMode, flags flags) { 10678 // PostfixExpression "++" 10679 pe := n.PostfixExpression.Operand.Type() 10680 switch k := p.opKind(f, n.PostfixExpression, pe); k { 10681 case opNormal: 10682 p.postfixExpressionIncDecValueNormal(f, n, oper, oper2, t, mode, flags) 10683 case opBitfield: 10684 p.postfixExpressionIncDecValueBitfield(f, n, oper, oper2, t, mode, flags) 10685 case opArrayParameter: 10686 p.postfixExpressionIncDecValueArrayParameter(f, n, oper, oper2, t, mode, flags) 10687 default: 10688 panic(todo("", n.Position(), pe, pe.Kind(), k)) 10689 } 10690 } 10691 10692 func (p *project) postfixExpressionIncDecValueArrayParameter(f *function, n *cc.PostfixExpression, oper, oper2 string, t cc.Type, mode exprMode, flags flags) { 10693 // PostfixExpression "++" 10694 pe := n.PostfixExpression.Operand.Type() 10695 defer p.w("%s", p.convert(n, n.PostfixExpression.Operand, t, flags)) 10696 x := "Dec" 10697 if oper == "++" { 10698 x = "Inc" 10699 } 10700 p.w("%sPost%s%s(&", p.task.crt, x, p.helperType(n, pe.Decay())) 10701 p.postfixExpression(f, n.PostfixExpression, pe, exprLValue, flags) 10702 p.w(", %d)", p.incDelta(n.PostfixExpression, pe)) 10703 } 10704 10705 func (p *project) postfixExpressionIncDecValueBitfield(f *function, n *cc.PostfixExpression, oper, oper2 string, t cc.Type, mode exprMode, flags flags) { 10706 // PostfixExpression "++" 10707 pe := n.PostfixExpression.Operand.Type() 10708 defer p.w("%s", p.convert(n, n.PostfixExpression.Operand, t, flags)) 10709 x := "Dec" 10710 if oper == "++" { 10711 x = "Inc" 10712 } 10713 bf := pe.BitField() 10714 p.w("%sPost%sBitFieldPtr%d%s(", p.task.crt, x, bf.BitFieldBlockWidth(), p.bfHelperType(pe)) 10715 p.postfixExpression(f, n.PostfixExpression, pe, exprAddrOf, flags) 10716 p.w(", %d, %d, %d, %#x)", p.incDelta(n.PostfixExpression, pe), bf.BitFieldBlockWidth(), bf.BitFieldOffset(), bf.Mask()) 10717 } 10718 10719 func (p *project) postfixExpressionIncDecValueNormal(f *function, n *cc.PostfixExpression, oper, oper2 string, t cc.Type, mode exprMode, flags flags) { 10720 // PostfixExpression "++" 10721 pe := n.PostfixExpression.Operand.Type() 10722 defer p.w("%s", p.convert(n, n.PostfixExpression.Operand, t, flags)) 10723 x := "Dec" 10724 if oper == "++" { 10725 x = "Inc" 10726 } 10727 if d := n.PostfixExpression.Declarator(); d != nil && p.isVolatileOrAtomic(d) { 10728 p.w("%sPost%sAtomic%s(&", p.task.crt, x, p.helperType(n, pe)) 10729 var local *local 10730 var tld *tld 10731 if f != nil { 10732 local = f.locals[d] 10733 } 10734 if local == nil { 10735 tld = p.tlds[d] 10736 } 10737 switch { 10738 case local != nil: 10739 p.w("%s", local.name) 10740 case tld != nil: 10741 p.w("%s", tld.name) 10742 default: 10743 panic(todo("")) 10744 } 10745 p.w(", %d)", p.incDelta(n.PostfixExpression, pe)) 10746 return 10747 } 10748 10749 p.w("%sPost%s%s(&", p.task.crt, x, p.helperType(n, pe)) 10750 p.postfixExpression(f, n.PostfixExpression, pe, exprLValue, flags) 10751 p.w(", %d)", p.incDelta(n.PostfixExpression, pe)) 10752 } 10753 10754 func (p *project) postfixExpressionIncDecLValue(f *function, n *cc.PostfixExpression, oper, oper2 string, t cc.Type, mode exprMode, flags flags) { 10755 switch k := p.opKind(f, n, n.Operand.Type()); k { 10756 case opNormal: 10757 p.postfixExpressionIncDecLValueNormal(f, n, oper, oper2, t, mode, flags) 10758 default: 10759 panic(todo("", n.Position(), k)) 10760 } 10761 } 10762 10763 func (p *project) postfixExpressionIncDecLValueNormal(f *function, n *cc.PostfixExpression, oper, oper2 string, t cc.Type, mode exprMode, flags flags) { 10764 pe := n.PostfixExpression.Operand.Type() 10765 defer p.w("%s", p.convert(n, n.PostfixExpression.Operand, t, flags)) 10766 x := "Dec" 10767 if oper == "++" { 10768 x = "Inc" 10769 } 10770 p.w("%sPost%s%s(&", p.task.crt, x, p.helperType(n, pe)) 10771 p.postfixExpression(f, n.PostfixExpression, pe, exprLValue, flags) 10772 p.w(", %d)", p.incDelta(n.PostfixExpression, pe)) 10773 } 10774 10775 func (p *project) postfixExpressionIncDecVoid(f *function, n *cc.PostfixExpression, oper, oper2 string, t cc.Type, mode exprMode, flags flags) { 10776 switch k := p.opKind(f, n, n.Operand.Type()); k { 10777 case opNormal: 10778 p.postfixExpressionIncDecVoidNormal(f, n, oper, oper2, t, mode, flags) 10779 case opBitfield: 10780 p.postfixExpressionIncDec(f, n, oper, oper2, t, exprValue, flags) 10781 default: 10782 panic(todo("", n.Position(), k)) 10783 } 10784 } 10785 10786 func (p *project) postfixExpressionIncDecVoidNormal(f *function, n *cc.PostfixExpression, oper, oper2 string, t cc.Type, mode exprMode, flags flags) { 10787 if d := n.PostfixExpression.Declarator(); d != nil && p.isVolatileOrAtomic(d) { 10788 switch d.Type().Size() { 10789 case 4, 8: 10790 if !d.Type().IsIntegerType() { 10791 p.err(n, "unsupported volatile declarator type: %v", d.Type()) 10792 return 10793 } 10794 10795 if f != nil { 10796 if local := f.locals[d]; local != nil { 10797 if local.isPinned { 10798 panic(todo("")) 10799 } 10800 10801 p.w("atomic.Add%s(&%s, ", p.helperType(n, d.Type()), local.name) 10802 switch oper { 10803 case "++": 10804 // ok 10805 case "--": 10806 p.w("-") 10807 default: 10808 p.err(n, "unsupported volatile declarator operation: %v", oper) 10809 } 10810 p.w("%d)", p.incDelta(n, d.Type())) 10811 return 10812 } 10813 } 10814 10815 if tld := p.tlds[d]; tld != nil { 10816 p.w("atomic.Add%s(&%s, ", p.helperType(n, d.Type()), tld.name) 10817 switch oper { 10818 case "++": 10819 // ok 10820 case "--": 10821 p.w("-") 10822 default: 10823 p.err(n, "unsupported volatile declarator operation: %v", oper) 10824 } 10825 p.w("%d)", p.incDelta(n, d.Type())) 10826 return 10827 } 10828 10829 panic(todo("", n.Position(), d.Position())) 10830 default: 10831 p.err(n, "unsupported volatile declarator size: %v", d.Type().Size()) 10832 return 10833 } 10834 } 10835 10836 pe := n.PostfixExpression.Operand.Type().Decay() 10837 p.postfixExpression(f, n.PostfixExpression, pe, exprLValue, flags) 10838 if pe.IsIntegerType() || pe.Kind() == cc.Ptr && p.incDelta(n, pe) == 1 { 10839 p.w("%s", oper) 10840 return 10841 } 10842 10843 switch pe.Kind() { 10844 case cc.Ptr, cc.Float, cc.Double: 10845 p.w("%s %d", oper2, p.incDelta(n, pe)) 10846 return 10847 } 10848 10849 panic(todo("", n.Position(), pe, pe.Kind())) 10850 } 10851 10852 func (p *project) incDelta(n cc.Node, t cc.Type) uintptr { 10853 if t.IsArithmeticType() { 10854 return 1 10855 } 10856 10857 if t.Kind() == cc.Ptr || t.Kind() == cc.Array { 10858 return t.Elem().Size() 10859 } 10860 10861 panic(todo("", n.Position(), t.Kind())) 10862 } 10863 10864 func (p *project) bitFldOff(t cc.Type, tok cc.Token) { 10865 var off uintptr 10866 fld, ok := t.FieldByName(tok.Value) 10867 switch { 10868 case ok && !fld.IsBitField(): 10869 panic(todo("%v: internal error: bitFdlOff must not be used with non bit fields", origin(2))) 10870 case !ok: 10871 p.err(&tok, "uknown field: %s", tok.Value) 10872 default: 10873 off = fld.BitFieldBlockFirst().Offset() 10874 } 10875 if off != 0 { 10876 p.w("+%d", off) 10877 } 10878 p.w("/* &.%s */", tok.Value) 10879 } 10880 10881 func (p *project) fldOff(t cc.Type, tok cc.Token) { 10882 if t.Kind() == cc.Ptr { 10883 t = t.Elem() 10884 } 10885 var off uintptr 10886 fld, ok := t.FieldByName(tok.Value) 10887 switch { 10888 case ok && fld.IsBitField(): 10889 panic(todo("%v: internal error: fdlOff must not be used with bit fields", origin(2))) 10890 case !ok: 10891 p.err(&tok, "uknown field: %s", tok.Value) 10892 default: 10893 off = fld.Offset() 10894 } 10895 if off != 0 { 10896 p.w("+%d", off) 10897 } 10898 p.w("/* &.%s */", tok.Value) 10899 } 10900 10901 func (p *project) postfixExpressionCall(f *function, n *cc.PostfixExpression, t cc.Type, mode exprMode, flags flags) { 10902 // PostfixExpression '(' ArgumentExpressionList ')' 10903 switch mode { 10904 case exprVoid: 10905 p.postfixExpressionCallVoid(f, n, t, mode, flags) 10906 case exprValue: 10907 p.postfixExpressionCallValue(f, n, t, mode, flags) 10908 case exprBool: 10909 p.postfixExpressionCallBool(f, n, t, mode, flags) 10910 default: 10911 panic(todo("", mode)) 10912 } 10913 } 10914 10915 func (p *project) postfixExpressionCallBool(f *function, n *cc.PostfixExpression, t cc.Type, mode exprMode, flags flags) { 10916 // PostfixExpression '(' ArgumentExpressionList ')' 10917 p.w("(") 10918 defer p.w(")") 10919 defer p.w(" != 0") 10920 if d := n.PostfixExpression.Declarator(); d != nil { 10921 switch d.Name() { 10922 case idVaArg: 10923 if !f.vaType.IsScalarType() { 10924 panic(todo("", f.vaType)) 10925 } 10926 10927 lhs := n.ArgumentExpressionList.AssignmentExpression 10928 p.w("%sVa%s(&", p.task.crt, p.helperType(n, f.vaType)) 10929 p.assignmentExpression(f, lhs, lhs.Operand.Type(), exprLValue, flags) 10930 p.w(")") 10931 return 10932 case idAtomicLoadN: 10933 p.atomicLoadN(f, n, t, mode, flags) 10934 return 10935 case idBuiltinConstantPImpl: 10936 p.w("%v", n.Operand.Value()) 10937 return 10938 } 10939 } 10940 10941 var va uintptr 10942 if f != nil { 10943 va = f.vaLists[n] 10944 } 10945 p.postfixExpression(f, n.PostfixExpression, n.PostfixExpression.Operand.Type(), exprFunc, flags) 10946 p.argumentExpressionList(f, n.PostfixExpression, n.ArgumentExpressionList, va) 10947 } 10948 10949 func (p *project) postfixExpressionCallValue(f *function, n *cc.PostfixExpression, t cc.Type, mode exprMode, flags flags) { 10950 // PostfixExpression '(' ArgumentExpressionList ')' 10951 defer p.w("%s", p.convert(n, n.Operand, t, flags)) 10952 if d := n.PostfixExpression.Declarator(); d != nil { 10953 switch d.Name() { 10954 case idVaEnd: 10955 p.w("_ = ") 10956 arg := n.ArgumentExpressionList.AssignmentExpression 10957 p.assignmentExpression(f, arg, arg.Operand.Type(), exprValue, flags) 10958 return 10959 case idVaStart: 10960 lhs := n.ArgumentExpressionList.AssignmentExpression 10961 p.assignmentExpression(f, lhs, lhs.Operand.Type(), exprLValue, flags) 10962 p.w(" = %s", f.vaName) 10963 return 10964 case idVaArg: 10965 if !f.vaType.IsScalarType() { 10966 panic(todo("", f.vaType)) 10967 } 10968 10969 lhs := n.ArgumentExpressionList.AssignmentExpression 10970 p.w("%sVa%s(&", p.task.crt, p.helperType(n, f.vaType)) 10971 p.assignmentExpression(f, lhs, lhs.Operand.Type(), exprLValue, flags) 10972 p.w(")") 10973 return 10974 case idAtomicLoadN: 10975 p.atomicLoadN(f, n, t, mode, flags) 10976 return 10977 case idAddOverflow: 10978 p.addOverflow(f, n, t, mode, flags) 10979 return 10980 case idSubOverflow: 10981 p.subOverflow(f, n, t, mode, flags) 10982 return 10983 case idMulOverflow: 10984 p.mulOverflow(f, n, t, mode, flags) 10985 return 10986 case idBuiltinConstantPImpl: 10987 p.w("%v", n.Operand.Value()) 10988 return 10989 } 10990 } 10991 var va uintptr 10992 if f != nil { 10993 va = f.vaLists[n] 10994 } 10995 p.postfixExpression(f, n.PostfixExpression, n.PostfixExpression.Operand.Type(), exprFunc, flags) 10996 p.argumentExpressionList(f, n.PostfixExpression, n.ArgumentExpressionList, va) 10997 } 10998 10999 // bool __builtin_mul_overflow (type1 a, type2 b, type3 *res) 11000 func (p *project) mulOverflow(f *function, n *cc.PostfixExpression, t cc.Type, mode exprMode, flags flags) { 11001 args := p.argList(n.ArgumentExpressionList) 11002 if len(args) != 3 { 11003 p.err(n, "expected 3 arguments in call to __builtin_mul_overflow") 11004 return 11005 } 11006 11007 pt := args[2].Operand.Type() 11008 if pt.Kind() != cc.Ptr { 11009 p.err(n, "invalid argument of __builtin_mul_overflow (expected pointer): %s", pt) 11010 return 11011 } 11012 11013 vt := pt.Elem() 11014 switch { 11015 case vt.IsIntegerType(): 11016 switch vt.Size() { 11017 case 1, 2, 4, 8, 16: 11018 p.w("%sX__builtin_mul_overflow%s", p.task.crt, p.helperType(n, vt)) 11019 default: 11020 p.err(n, "invalid argument of __builtin_mul_overflow: %v, elem kind %v", pt, vt.Kind()) 11021 return 11022 } 11023 p.w("(%s", f.tlsName) 11024 types := []cc.Type{vt, vt, pt} 11025 for i, v := range args[:3] { 11026 p.w(", ") 11027 p.assignmentExpression(f, v, types[i], exprValue, flags) 11028 } 11029 p.w(")") 11030 return 11031 } 11032 11033 p.err(n, "invalid arguments of __builtin_mul_overflow: (%v, %v, %v)", args[0].Operand.Type(), args[1].Operand.Type(), args[2].Operand.Type()) 11034 } 11035 11036 // bool __builtin_sub_overflow (type1 a, type2 b, type3 *res) 11037 func (p *project) subOverflow(f *function, n *cc.PostfixExpression, t cc.Type, mode exprMode, flags flags) { 11038 args := p.argList(n.ArgumentExpressionList) 11039 if len(args) != 3 { 11040 p.err(n, "expected 3 arguments in call to __builtin_sub_overflow") 11041 return 11042 } 11043 11044 pt := args[2].Operand.Type() 11045 if pt.Kind() != cc.Ptr { 11046 p.err(n, "invalid argument of __builtin_sub_overflow (expected pointer): %s", pt) 11047 return 11048 } 11049 11050 vt := pt.Elem() 11051 switch { 11052 case vt.IsIntegerType(): 11053 switch vt.Size() { 11054 case 1, 2, 4, 8: 11055 p.w("%sX__builtin_sub_overflow%s", p.task.crt, p.helperType(n, vt)) 11056 default: 11057 p.err(n, "invalid argument of __builtin_sub_overflow: %v, elem kind %v", pt, vt.Kind()) 11058 return 11059 } 11060 p.w("(%s", f.tlsName) 11061 types := []cc.Type{vt, vt, pt} 11062 for i, v := range args[:3] { 11063 p.w(", ") 11064 p.assignmentExpression(f, v, types[i], exprValue, flags) 11065 } 11066 p.w(")") 11067 return 11068 } 11069 11070 p.err(n, "invalid arguments of __builtin_sub_overflow: (%v, %v, %v)", args[0].Operand.Type(), args[1].Operand.Type(), args[2].Operand.Type()) 11071 } 11072 11073 // bool __builtin_add_overflow (type1 a, type2 b, type3 *res) 11074 func (p *project) addOverflow(f *function, n *cc.PostfixExpression, t cc.Type, mode exprMode, flags flags) { 11075 args := p.argList(n.ArgumentExpressionList) 11076 if len(args) != 3 { 11077 p.err(n, "expected 3 arguments in call to __builtin_add_overflow") 11078 return 11079 } 11080 11081 pt := args[2].Operand.Type() 11082 if pt.Kind() != cc.Ptr { 11083 p.err(n, "invalid argument of __builtin_add_overflow (expected pointer): %s", pt) 11084 return 11085 } 11086 11087 vt := pt.Elem() 11088 switch { 11089 case vt.IsIntegerType(): 11090 switch vt.Size() { 11091 case 1, 2, 4, 8: 11092 p.w("%sX__builtin_add_overflow%s", p.task.crt, p.helperType(n, vt)) 11093 default: 11094 p.err(n, "invalid argument of __builtin_add_overflow: %v, elem kind %v", pt, vt.Kind()) 11095 return 11096 } 11097 p.w("(%s", f.tlsName) 11098 types := []cc.Type{vt, vt, pt} 11099 for i, v := range args[:3] { 11100 p.w(", ") 11101 p.assignmentExpression(f, v, types[i], exprValue, flags) 11102 } 11103 p.w(")") 11104 return 11105 } 11106 11107 p.err(n, "invalid arguments of __builtin_add_overflow: (%v, %v, %v)", args[0].Operand.Type(), args[1].Operand.Type(), args[2].Operand.Type()) 11108 } 11109 11110 // type __atomic_load_n (type *ptr, int memorder) 11111 func (p *project) atomicLoadN(f *function, n *cc.PostfixExpression, t cc.Type, mode exprMode, flags flags) { 11112 args := p.argList(n.ArgumentExpressionList) 11113 if len(args) != 2 { 11114 p.err(n, "expected 2 arguments in call to __atomic_load_n") 11115 return 11116 } 11117 11118 pt := args[0].Operand.Type() 11119 if pt.Kind() != cc.Ptr { 11120 p.err(n, "invalid argument of __atomic_load_n (expected pointer): %s", pt) 11121 return 11122 } 11123 11124 vt := pt.Elem() 11125 switch { 11126 case vt.IsIntegerType(): 11127 var s, sb string 11128 switch { 11129 case vt.IsSignedType(): 11130 s = "Int" 11131 sb = "int8" 11132 default: 11133 s = "Uint" 11134 sb = "byte" 11135 } 11136 switch vt.Size() { 11137 case 1: 11138 switch { 11139 case p.task.ignoreUnsupportedAligment: 11140 p.w("(*(*%s)(unsafe.Pointer(", sb) 11141 p.assignmentExpression(f, args[0], pt, exprValue, flags) 11142 p.w(")))") 11143 default: 11144 p.err(n, "invalid argument of __atomic_load_n: %v, elem kind %v", pt, vt.Kind()) 11145 } 11146 return 11147 case 2, 4, 8: 11148 p.w("%sAtomicLoadN%s%d", p.task.crt, s, 8*vt.Size()) 11149 default: 11150 p.err(n, "invalid argument of __atomic_load_n: %v, elem kind %v", pt, vt.Kind()) 11151 return 11152 } 11153 types := []cc.Type{pt, p.intType} 11154 p.w("(") 11155 for i, v := range args[:2] { 11156 if i != 0 { 11157 p.w(", ") 11158 } 11159 p.assignmentExpression(f, v, types[i], exprValue, flags) 11160 } 11161 p.w(")") 11162 return 11163 case vt.Kind() == cc.Ptr: 11164 panic(todo("", pt, vt)) 11165 } 11166 11167 p.err(n, "invalid first argument of __atomic_load_n: %v, elem kind %v", pt, vt.Kind()) 11168 } 11169 11170 func (p *project) postfixExpressionCallVoid(f *function, n *cc.PostfixExpression, t cc.Type, mode exprMode, flags flags) { 11171 // PostfixExpression '(' ArgumentExpressionList ')' 11172 if d := n.PostfixExpression.Declarator(); d != nil { 11173 switch d.Name() { 11174 case idVaEnd: 11175 p.w("_ = ") 11176 arg := n.ArgumentExpressionList.AssignmentExpression 11177 p.assignmentExpression(f, arg, arg.Operand.Type(), exprValue, flags) 11178 return 11179 case idVaStart: 11180 lhs := n.ArgumentExpressionList.AssignmentExpression 11181 p.assignmentExpression(f, lhs, lhs.Operand.Type(), exprLValue, flags) 11182 p.w(" = %s", f.vaName) 11183 return 11184 case idVaArg: 11185 if !f.vaType.IsScalarType() { 11186 panic(todo("", f.vaType)) 11187 } 11188 11189 lhs := n.ArgumentExpressionList.AssignmentExpression 11190 p.w("%sVa%s(&", p.task.crt, p.helperType(n, f.vaType)) 11191 p.assignmentExpression(f, lhs, lhs.Operand.Type(), exprLValue, flags) 11192 p.w(")") 11193 return 11194 case idAtomicStoreN: 11195 p.atomicStoreN(f, n, t, mode, flags) 11196 return 11197 case idMulOverflow: 11198 p.mulOverflow(f, n, t, mode, flags) 11199 return 11200 } 11201 } 11202 var va uintptr 11203 if f != nil { 11204 va = f.vaLists[n] 11205 } 11206 p.postfixExpression(f, n.PostfixExpression, n.PostfixExpression.Operand.Type(), exprFunc, flags) 11207 p.argumentExpressionList(f, n.PostfixExpression, n.ArgumentExpressionList, va) 11208 } 11209 11210 // void __atomic_store_n (type *ptr, type val, int memorder) 11211 func (p *project) atomicStoreN(f *function, n *cc.PostfixExpression, t cc.Type, mode exprMode, flags flags) { 11212 args := p.argList(n.ArgumentExpressionList) 11213 if len(args) != 3 { 11214 p.err(n, "expected 3 arguments in call to __atomic_store_n") 11215 return 11216 } 11217 11218 pt := args[0].Operand.Type() 11219 if pt.Kind() != cc.Ptr { 11220 p.err(n, "invalid first argument of __atomic_store_n (expected pointer): %s", pt) 11221 return 11222 } 11223 11224 vt := args[1].Operand.Type() 11225 switch { 11226 case vt.IsIntegerType(): 11227 var s string 11228 switch { 11229 case vt.IsSignedType(): 11230 s = "Int" 11231 default: 11232 s = "Uint" 11233 } 11234 switch vt.Size() { 11235 case 2, 4, 8: 11236 p.w("%sAtomicStoreN%s%d", p.task.crt, s, 8*vt.Size()) 11237 default: 11238 p.err(n, "invalid arguments of __atomic_store_n: (%v, %v), element kind %v", pt, vt, vt.Kind()) 11239 return 11240 } 11241 p.w("(") 11242 types := []cc.Type{pt, vt, p.intType} 11243 for i, v := range args[:3] { 11244 if i != 0 { 11245 p.w(", ") 11246 } 11247 if i == 1 { 11248 p.w("%s(", strings.ToLower(p.helperType(n, vt))) 11249 } 11250 p.assignmentExpression(f, v, types[i], exprValue, flags) 11251 if i == 1 { 11252 p.w(")") 11253 } 11254 } 11255 p.w(")") 11256 return 11257 case vt.Kind() == cc.Ptr: 11258 p.w("%sAtomicStoreNUintptr", p.task.crt) 11259 p.w("(") 11260 types := []cc.Type{pt, vt, p.intType} 11261 for i, v := range args[:3] { 11262 if i != 0 { 11263 p.w(", ") 11264 } 11265 if i == 1 { 11266 p.w("%s(", strings.ToLower(p.helperType(n, vt))) 11267 } 11268 p.assignmentExpression(f, v, types[i], exprValue, flags) 11269 if i == 1 { 11270 p.w(")") 11271 } 11272 } 11273 p.w(")") 11274 return 11275 } 11276 11277 p.err(n, "invalid arguments of __atomic_store_n: (%v, %v), element kind %v", pt, vt, vt.Kind()) 11278 } 11279 11280 func (p *project) argList(n *cc.ArgumentExpressionList) (r []*cc.AssignmentExpression) { 11281 for ; n != nil; n = n.ArgumentExpressionList { 11282 r = append(r, n.AssignmentExpression) 11283 } 11284 return r 11285 } 11286 11287 func (p *project) argumentExpressionList(f *function, pe *cc.PostfixExpression, n *cc.ArgumentExpressionList, bpOff uintptr) { 11288 switch { 11289 case f == nil: 11290 p.w("(nil") 11291 default: 11292 p.w("(%s", f.tlsName) 11293 } 11294 ft := funcType(pe.Operand.Type()) 11295 isVariadic := ft.IsVariadic() 11296 params := ft.Parameters() 11297 if len(params) == 1 && params[0].Type().Kind() == cc.Void { 11298 params = nil 11299 } 11300 var args []*cc.AssignmentExpression 11301 for ; n != nil; n = n.ArgumentExpressionList { 11302 args = append(args, n.AssignmentExpression) 11303 } 11304 if len(args) < len(params) { 11305 panic(todo("", p.pos(n))) 11306 } 11307 11308 va := true 11309 if len(args) > len(params) && !isVariadic { 11310 var a []string 11311 for _, v := range args { 11312 a = append(a, v.Operand.Type().String()) 11313 } 11314 sargs := strings.Join(a, ",") 11315 switch d := pe.Declarator(); { 11316 case d == nil: 11317 p.err(pe, "too many arguments (%s) in call to %s", sargs, ft) 11318 default: 11319 p.err(pe, "too many arguments (%s) in call to %s of type %s", sargs, d.Name(), ft) 11320 } 11321 va = false 11322 } 11323 11324 paren := "" 11325 for i, arg := range args { 11326 p.w(",%s", tidyComment(" ", arg)) 11327 mode := exprValue 11328 if at := arg.Operand.Type(); at.Kind() == cc.Array { 11329 mode = exprDecay 11330 } 11331 switch { 11332 case i < len(params): 11333 switch pt := params[i].Type(); { 11334 case isTransparentUnion(params[i].Type()): 11335 p.callArgTransparentUnion(f, arg, pt) 11336 default: 11337 p.assignmentExpression(f, arg, arg.Promote(), mode, 0) 11338 } 11339 case va && i == len(params): 11340 p.w("%sVaList(%s%s, ", p.task.crt, f.bpName, nonZeroUintptr(bpOff)) 11341 paren = ")" 11342 fallthrough 11343 default: 11344 var flags flags 11345 if arg.Promote().IsIntegerType() { 11346 switch x := arg.Operand.Value().(type) { 11347 case cc.Int64Value: 11348 if x < mathutil.MinInt || x > mathutil.MaxInt { 11349 flags |= fForceConv 11350 } 11351 case cc.Uint64Value: 11352 if x > mathutil.MaxInt { 11353 flags |= fForceConv 11354 } 11355 } 11356 } 11357 p.assignmentExpression(f, arg, arg.Promote(), mode, flags) 11358 } 11359 } 11360 if isVariadic && len(args) == len(params) { 11361 p.w(", 0") 11362 } 11363 p.w("%s)", paren) 11364 } 11365 11366 // https://gcc.gnu.org/onlinedocs/gcc-3.3/gcc/Type-Attributes.html 11367 // 11368 // transparent_union 11369 // 11370 // This attribute, attached to a union type definition, indicates that any 11371 // function parameter having that union type causes calls to that function to 11372 // be treated in a special way. 11373 // 11374 // First, the argument corresponding to a transparent union type can be of any 11375 // type in the union; no cast is required. Also, if the union contains a 11376 // pointer type, the corresponding argument can be a null pointer constant or a 11377 // void pointer expression; and if the union contains a void pointer type, the 11378 // corresponding argument can be any pointer expression. If the union member 11379 // type is a pointer, qualifiers like const on the referenced type must be 11380 // respected, just as with normal pointer conversions. 11381 // 11382 // Second, the argument is passed to the function using the calling conventions 11383 // of first member of the transparent union, not the calling conventions of the 11384 // union itself. All members of the union must have the same machine 11385 // representation; this is necessary for this argument passing to work 11386 // properly. 11387 // 11388 // Transparent unions are designed for library functions that have multiple 11389 // interfaces for compatibility reasons. For example, suppose the wait function 11390 // must accept either a value of type int * to comply with Posix, or a value of 11391 // type union wait * to comply with the 4.1BSD interface. If wait's parameter 11392 // were void *, wait would accept both kinds of arguments, but it would also 11393 // accept any other pointer type and this would make argument type checking 11394 // less useful. Instead, <sys/wait.h> might define the interface as follows: 11395 // 11396 // typedef union 11397 // { 11398 // int *__ip; 11399 // union wait *__up; 11400 // } wait_status_ptr_t __attribute__ ((__transparent_union__)); 11401 // 11402 // pid_t wait (wait_status_ptr_t); 11403 // 11404 // This interface allows either int * or union wait * arguments to be passed, 11405 // using the int * calling convention. The program can call wait with arguments 11406 // of either type: 11407 // 11408 // int w1 () { int w; return wait (&w); } 11409 // int w2 () { union wait w; return wait (&w); } 11410 // 11411 // With this interface, wait's implementation might look like this: 11412 // 11413 // pid_t wait (wait_status_ptr_t p) 11414 // { 11415 // return waitpid (-1, p.__ip, 0); 11416 // } 11417 func (p *project) callArgTransparentUnion(f *function, n *cc.AssignmentExpression, pt cc.Type) { 11418 if pt.Kind() != cc.Union { 11419 panic(todo("internal error")) 11420 } 11421 11422 ot := n.Operand.Type() 11423 switch k := pt.UnionCommon(); k { 11424 case cc.Ptr: 11425 if ot.Kind() != k { 11426 panic(todo("", n.Position(), k, pt)) 11427 } 11428 11429 p.assignmentExpression(f, n, ot, exprValue, 0) 11430 default: 11431 panic(todo("", n.Position(), k, pt)) 11432 } 11433 } 11434 11435 func isTransparentUnion(t cc.Type) (r bool) { 11436 for _, v := range attrs(t) { 11437 cc.Inspect(v, func(n cc.Node, _ bool) bool { 11438 if x, ok := n.(*cc.AttributeValue); ok && x.Token.Value == idTransparentUnion { 11439 r = true 11440 return false 11441 } 11442 11443 return true 11444 }) 11445 } 11446 return r 11447 } 11448 11449 func attrs(t cc.Type) []*cc.AttributeSpecifier { 11450 if a := t.Attributes(); len(a) != 0 { 11451 return a 11452 } 11453 11454 if t.IsAliasType() { 11455 if a := t.Alias().Attributes(); len(a) != 0 { 11456 return a 11457 } 11458 11459 return t.AliasDeclarator().Type().Attributes() 11460 } 11461 11462 return nil 11463 } 11464 11465 func (p *project) nzUintptr(n cc.Node, f func(), op cc.Operand) { 11466 if op.Type().IsIntegerType() { 11467 switch { 11468 case op.IsZero(): 11469 return 11470 case op.Value() != nil: 11471 switch x := op.Value().(type) { 11472 case cc.Int64Value: 11473 if x > 0 && uint64(x) <= 1<<(8*p.ptrSize)-1 { 11474 p.w("+%d", x) 11475 return 11476 } 11477 case cc.Uint64Value: 11478 if uint64(x) <= 1<<(8*p.ptrSize)-1 { 11479 p.w("+%d", x) 11480 return 11481 } 11482 } 11483 11484 p.w(" +%sUintptrFrom%s(", p.task.crt, p.helperType(n, op.Type())) 11485 default: 11486 p.w(" +uintptr(") 11487 } 11488 11489 f() 11490 p.w(")") 11491 return 11492 } 11493 11494 panic(todo("", p.pos(n))) 11495 } 11496 11497 func (p *project) primaryExpression(f *function, n *cc.PrimaryExpression, t cc.Type, mode exprMode, flags flags) { 11498 switch mode { 11499 case exprLValue: 11500 p.primaryExpressionLValue(f, n, t, mode, flags) 11501 case exprValue: 11502 p.primaryExpressionValue(f, n, t, mode, flags) 11503 case exprFunc: 11504 p.primaryExpressionFunc(f, n, t, mode, flags) 11505 case exprAddrOf: 11506 p.primaryExpressionAddrOf(f, n, t, mode, flags) 11507 case exprSelect: 11508 p.primaryExpressionSelect(f, n, t, mode, flags) 11509 case exprPSelect: 11510 p.primaryExpressionPSelect(f, n, t, mode, flags) 11511 case exprBool: 11512 p.primaryExpressionBool(f, n, t, mode, flags) 11513 case exprVoid: 11514 p.primaryExpressionVoid(f, n, t, mode, flags) 11515 case exprDecay: 11516 p.primaryExpressionDecay(f, n, t, mode, flags) 11517 default: 11518 panic(todo("", n.Position(), mode)) 11519 } 11520 } 11521 11522 func (p *project) primaryExpressionDecay(f *function, n *cc.PrimaryExpression, t cc.Type, mode exprMode, flags flags) { 11523 switch n.Case { 11524 case cc.PrimaryExpressionIdent: // IDENTIFIER 11525 switch d := n.Declarator(); { 11526 case d != nil: 11527 p.declarator(n, f, d, t, mode, flags) 11528 default: 11529 panic(todo("", p.pos(n))) 11530 } 11531 case cc.PrimaryExpressionInt: // INTCONST 11532 p.intConst(n, n.Token.Src.String(), n.Operand, t, flags) 11533 case cc.PrimaryExpressionFloat: // FLOATCONST 11534 panic(todo("", p.pos(n))) 11535 case cc.PrimaryExpressionEnum: // ENUMCONST 11536 panic(todo("", p.pos(n))) 11537 case cc.PrimaryExpressionChar: // CHARCONST 11538 panic(todo("", p.pos(n))) 11539 case cc.PrimaryExpressionLChar: // LONGCHARCONST 11540 panic(todo("", p.pos(n))) 11541 case cc.PrimaryExpressionString: // STRINGLITERAL 11542 p.w("%s", p.stringLiteral(n.Operand.Value())) 11543 case cc.PrimaryExpressionLString: // LONGSTRINGLITERAL 11544 p.w("%s", p.wideStringLiteral(n.Operand.Value(), 0)) 11545 case cc.PrimaryExpressionExpr: // '(' Expression ')' 11546 p.expression(f, n.Expression, t, mode, flags) 11547 case cc.PrimaryExpressionStmt: // '(' CompoundStatement ')' 11548 p.err(n, "statement expressions not supported") 11549 default: 11550 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 11551 } 11552 } 11553 11554 func (p *project) primaryExpressionVoid(f *function, n *cc.PrimaryExpression, t cc.Type, mode exprMode, flags flags) { 11555 11556 switch n.Case { 11557 case cc.PrimaryExpressionIdent: // IDENTIFIER 11558 p.w("_ = ") 11559 p.primaryExpression(f, n, n.Operand.Type(), exprValue, flags) 11560 case cc.PrimaryExpressionInt, // INTCONST 11561 cc.PrimaryExpressionFloat, // FLOATCONST 11562 cc.PrimaryExpressionEnum, // ENUMCONST 11563 cc.PrimaryExpressionChar, // CHARCONST 11564 cc.PrimaryExpressionLChar, // LONGCHARCONST 11565 cc.PrimaryExpressionString, // STRINGLITERAL 11566 cc.PrimaryExpressionLString: // LONGSTRINGLITERAL 11567 11568 // nop 11569 case cc.PrimaryExpressionExpr: // '(' Expression ')' 11570 p.expression(f, n.Expression, n.Expression.Operand.Type(), mode, flags) 11571 case cc.PrimaryExpressionStmt: // '(' CompoundStatement ')' 11572 p.compoundStatement(f, n.CompoundStatement, "", true, false, 0) 11573 default: 11574 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 11575 } 11576 } 11577 11578 func (p *project) primaryExpressionBool(f *function, n *cc.PrimaryExpression, t cc.Type, mode exprMode, flags flags) { 11579 if n.Case != cc.PrimaryExpressionExpr { 11580 p.w("(") 11581 defer p.w(")") 11582 } 11583 11584 if n.Case != cc.PrimaryExpressionExpr { 11585 defer p.w(" != 0") 11586 } 11587 switch n.Case { 11588 case cc.PrimaryExpressionIdent: // IDENTIFIER 11589 switch d := n.Declarator(); { 11590 case d != nil: 11591 p.declarator(n, f, d, d.Type(), exprValue, flags) 11592 default: 11593 panic(todo("", p.pos(n))) 11594 } 11595 case cc.PrimaryExpressionInt: // INTCONST 11596 p.intConst(n, n.Token.Src.String(), n.Operand, n.Operand.Type(), flags) 11597 case cc.PrimaryExpressionFloat: // FLOATCONST 11598 panic(todo("", p.pos(n))) 11599 case cc.PrimaryExpressionEnum: // ENUMCONST 11600 panic(todo("", p.pos(n))) 11601 case cc.PrimaryExpressionChar: // CHARCONST 11602 panic(todo("", p.pos(n))) 11603 case cc.PrimaryExpressionLChar: // LONGCHARCONST 11604 p.charConst(n, n.Token.Src.String(), n.Operand, t, flags) 11605 case cc.PrimaryExpressionString: // STRINGLITERAL 11606 p.w(" 1 ") 11607 case cc.PrimaryExpressionLString: // LONGSTRINGLITERAL 11608 panic(todo("", p.pos(n))) 11609 case cc.PrimaryExpressionExpr: // '(' Expression ')' 11610 p.w("(") 11611 defer p.w(")") 11612 p.expression(f, n.Expression, t, mode, flags) 11613 case cc.PrimaryExpressionStmt: // '(' CompoundStatement ')' 11614 p.w("func() %v {", p.typ(n, n.CompoundStatement.Operand.Type())) 11615 p.compoundStatement(f, n.CompoundStatement, "", true, false, exprValue) 11616 p.w("}()") 11617 default: 11618 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 11619 } 11620 } 11621 11622 func (p *project) primaryExpressionPSelect(f *function, n *cc.PrimaryExpression, t cc.Type, mode exprMode, flags flags) { 11623 switch n.Case { 11624 case cc.PrimaryExpressionIdent: // IDENTIFIER 11625 switch d := n.Declarator(); { 11626 case d != nil: 11627 switch k := p.declaratorKind(d); k { 11628 case opArray: 11629 panic(todo("", p.pos(n))) 11630 p.primaryExpression(f, n, t, exprDecay, flags) 11631 default: 11632 p.declarator(n, f, d, t, mode, flags) 11633 } 11634 default: 11635 panic(todo("", p.pos(n))) 11636 } 11637 case cc.PrimaryExpressionInt: // INTCONST 11638 panic(todo("", p.pos(n))) 11639 case cc.PrimaryExpressionFloat: // FLOATCONST 11640 panic(todo("", p.pos(n))) 11641 case cc.PrimaryExpressionEnum: // ENUMCONST 11642 panic(todo("", p.pos(n))) 11643 case cc.PrimaryExpressionChar: // CHARCONST 11644 panic(todo("", p.pos(n))) 11645 case cc.PrimaryExpressionLChar: // LONGCHARCONST 11646 panic(todo("", p.pos(n))) 11647 case cc.PrimaryExpressionString: // STRINGLITERAL 11648 panic(todo("", p.pos(n))) 11649 case cc.PrimaryExpressionLString: // LONGSTRINGLITERAL 11650 panic(todo("", p.pos(n))) 11651 case cc.PrimaryExpressionExpr: // '(' Expression ')' 11652 p.expression(f, n.Expression, t, mode, flags) 11653 case cc.PrimaryExpressionStmt: // '(' CompoundStatement ')' 11654 p.err(n, "statement expressions not supported") 11655 default: 11656 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 11657 } 11658 } 11659 11660 func (p *project) primaryExpressionSelect(f *function, n *cc.PrimaryExpression, t cc.Type, mode exprMode, flags flags) { 11661 switch n.Case { 11662 case cc.PrimaryExpressionIdent: // IDENTIFIER 11663 switch d := n.Declarator(); { 11664 case d != nil: 11665 p.declarator(n, f, d, t, mode, flags) 11666 default: 11667 panic(todo("", p.pos(n))) 11668 } 11669 case cc.PrimaryExpressionInt: // INTCONST 11670 panic(todo("", p.pos(n))) 11671 case cc.PrimaryExpressionFloat: // FLOATCONST 11672 panic(todo("", p.pos(n))) 11673 case cc.PrimaryExpressionEnum: // ENUMCONST 11674 panic(todo("", p.pos(n))) 11675 case cc.PrimaryExpressionChar: // CHARCONST 11676 panic(todo("", p.pos(n))) 11677 case cc.PrimaryExpressionLChar: // LONGCHARCONST 11678 panic(todo("", p.pos(n))) 11679 case cc.PrimaryExpressionString: // STRINGLITERAL 11680 panic(todo("", p.pos(n))) 11681 case cc.PrimaryExpressionLString: // LONGSTRINGLITERAL 11682 panic(todo("", p.pos(n))) 11683 case cc.PrimaryExpressionExpr: // '(' Expression ')' 11684 p.expression(f, n.Expression, t, mode, flags) 11685 case cc.PrimaryExpressionStmt: // '(' CompoundStatement ')' 11686 p.err(n, "statement expressions not supported") 11687 default: 11688 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 11689 } 11690 } 11691 11692 func (p *project) primaryExpressionAddrOf(f *function, n *cc.PrimaryExpression, t cc.Type, mode exprMode, flags flags) { 11693 switch n.Case { 11694 case cc.PrimaryExpressionIdent: // IDENTIFIER 11695 switch d := n.Declarator(); { 11696 case d != nil: 11697 p.declarator(n, f, d, t, mode, flags) 11698 default: 11699 panic(todo("", p.pos(n))) 11700 } 11701 case cc.PrimaryExpressionInt: // INTCONST 11702 panic(todo("", p.pos(n))) 11703 case cc.PrimaryExpressionFloat: // FLOATCONST 11704 panic(todo("", p.pos(n))) 11705 case cc.PrimaryExpressionEnum: // ENUMCONST 11706 panic(todo("", p.pos(n))) 11707 case cc.PrimaryExpressionChar: // CHARCONST 11708 panic(todo("", p.pos(n))) 11709 case cc.PrimaryExpressionLChar: // LONGCHARCONST 11710 panic(todo("", p.pos(n))) 11711 case cc.PrimaryExpressionString: // STRINGLITERAL 11712 p.w("%s", p.stringLiteral(n.Operand.Value())) 11713 case cc.PrimaryExpressionLString: // LONGSTRINGLITERAL 11714 p.w("%s", p.wideStringLiteral(n.Operand.Value(), 0)) 11715 case cc.PrimaryExpressionExpr: // '(' Expression ')' 11716 p.expression(f, n.Expression, t, mode, flags) 11717 case cc.PrimaryExpressionStmt: // '(' CompoundStatement ')' 11718 p.err(n, "statement expressions not supported") 11719 default: 11720 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 11721 } 11722 } 11723 11724 func (p *project) primaryExpressionFunc(f *function, n *cc.PrimaryExpression, t cc.Type, mode exprMode, flags flags) { 11725 switch n.Case { 11726 case cc.PrimaryExpressionIdent: // IDENTIFIER 11727 p.fnVal(n, f, func() { p.primaryExpression(f, n, n.Operand.Type(), exprValue, flags) }, n.Declarator(), n.Operand.Type(), 0, mode, flags) 11728 case cc.PrimaryExpressionInt: // INTCONST 11729 panic(todo("", p.pos(n))) 11730 case cc.PrimaryExpressionFloat: // FLOATCONST 11731 panic(todo("", p.pos(n))) 11732 case cc.PrimaryExpressionEnum: // ENUMCONST 11733 panic(todo("", p.pos(n))) 11734 case cc.PrimaryExpressionChar: // CHARCONST 11735 panic(todo("", p.pos(n))) 11736 case cc.PrimaryExpressionLChar: // LONGCHARCONST 11737 panic(todo("", p.pos(n))) 11738 case cc.PrimaryExpressionString: // STRINGLITERAL 11739 panic(todo("", p.pos(n))) 11740 case cc.PrimaryExpressionLString: // LONGSTRINGLITERAL 11741 panic(todo("", p.pos(n))) 11742 case cc.PrimaryExpressionExpr: // '(' Expression ')' 11743 p.expression(f, n.Expression, t, mode, flags) 11744 case cc.PrimaryExpressionStmt: // '(' CompoundStatement ')' 11745 p.err(n, "statement expressions not supported") 11746 default: 11747 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 11748 } 11749 } 11750 11751 func cmpNormalizeValue(v cc.Value) cc.Value { 11752 switch x := v.(type) { 11753 case cc.Int64Value: 11754 if x >= 0 { 11755 return cc.Uint64Value(x) 11756 } 11757 } 11758 return v 11759 } 11760 11761 func (p *project) primaryExpressionValue(f *function, n *cc.PrimaryExpression, t cc.Type, mode exprMode, flags flags) { 11762 switch n.Case { 11763 case cc.PrimaryExpressionIdent: // IDENTIFIER 11764 switch d := n.Declarator(); { 11765 case d != nil: 11766 p.declarator(n, f, d, t, mode, flags) 11767 default: 11768 panic(todo("", p.pos(n))) 11769 } 11770 case cc.PrimaryExpressionInt: // INTCONST 11771 if m := n.Token.Macro(); m != 0 { 11772 if d := p.defines[m]; d.name != "" { 11773 if cmpNormalizeValue(n.Operand.Value()) == cmpNormalizeValue(d.value) { 11774 defer p.w("%s", p.convert(n, n.Operand, t, flags)) 11775 p.w(" %s ", d.name) 11776 break 11777 } 11778 11779 p.w("/* %s */", m) 11780 } 11781 } 11782 11783 p.intConst(n, n.Token.Src.String(), n.Operand, t, flags) 11784 case cc.PrimaryExpressionFloat: // FLOATCONST 11785 //TODO use #define 11786 p.floatConst(n, n.Token.Src.String(), n.Operand, t, flags) 11787 case cc.PrimaryExpressionEnum: // ENUMCONST 11788 en := n.ResolvedTo().(*cc.Enumerator) 11789 if n.ResolvedIn().Parent() == nil { 11790 if nm := p.enumConsts[en.Token.Value]; nm != "" { 11791 p.w(" %s ", nm) 11792 break 11793 } 11794 } 11795 11796 p.intConst(n, "", n.Operand, t, flags) 11797 p.w("/* %s */", en.Token.Value) 11798 case cc.PrimaryExpressionChar: // CHARCONST 11799 p.charConst(n, n.Token.Src.String(), n.Operand, t, flags) 11800 case cc.PrimaryExpressionLChar: // LONGCHARCONST 11801 p.charConst(n, n.Token.Src.String(), n.Operand, t, flags) 11802 case cc.PrimaryExpressionString: // STRINGLITERAL 11803 p.w("%s", p.stringLiteral(n.Operand.Value())) 11804 case cc.PrimaryExpressionLString: // LONGSTRINGLITERAL 11805 p.w("%s", p.wideStringLiteral(n.Operand.Value(), 0)) 11806 case cc.PrimaryExpressionExpr: // '(' Expression ')' 11807 p.w("(") 11808 defer p.w(")") 11809 p.expression(f, n.Expression, t, mode, flags) 11810 case cc.PrimaryExpressionStmt: // '(' CompoundStatement ')' 11811 p.statementExpression(f, n.CompoundStatement, t, mode, flags) 11812 default: 11813 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 11814 } 11815 } 11816 11817 func (p *project) statementExpression(f *function, n *cc.CompoundStatement, t cc.Type, mode exprMode, flags flags) { 11818 defer p.w("%s", p.convert(n, n.Operand, t, flags)) 11819 p.w(" func() %v {", p.typ(n, n.Operand.Type())) 11820 p.compoundStatement(f, n, "", true, false, mode) 11821 p.w("}()") 11822 } 11823 11824 func (p *project) primaryExpressionLValue(f *function, n *cc.PrimaryExpression, t cc.Type, mode exprMode, flags flags) { 11825 switch n.Case { 11826 case cc.PrimaryExpressionIdent: // IDENTIFIER 11827 switch d := n.Declarator(); { 11828 case d != nil: 11829 p.declarator(n, f, d, t, mode, flags) 11830 default: 11831 panic(todo("", p.pos(n))) 11832 } 11833 case cc.PrimaryExpressionInt: // INTCONST 11834 panic(todo("", p.pos(n))) 11835 case cc.PrimaryExpressionFloat: // FLOATCONST 11836 panic(todo("", p.pos(n))) 11837 case cc.PrimaryExpressionEnum: // ENUMCONST 11838 panic(todo("", p.pos(n))) 11839 case cc.PrimaryExpressionChar: // CHARCONST 11840 panic(todo("", p.pos(n))) 11841 case cc.PrimaryExpressionLChar: // LONGCHARCONST 11842 panic(todo("", p.pos(n))) 11843 case cc.PrimaryExpressionString: // STRINGLITERAL 11844 panic(todo("", p.pos(n))) 11845 case cc.PrimaryExpressionLString: // LONGSTRINGLITERAL 11846 panic(todo("", p.pos(n))) 11847 case cc.PrimaryExpressionExpr: // '(' Expression ')' 11848 p.w("(") 11849 defer p.w(")") 11850 p.expression(f, n.Expression, t, mode, flags) 11851 case cc.PrimaryExpressionStmt: // '(' CompoundStatement ')' 11852 p.err(n, "statement expressions not supported") 11853 default: 11854 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 11855 } 11856 } 11857 11858 func (p *project) stringLiteralString(s string) string { 11859 if p.pass1 { 11860 return "" 11861 } 11862 11863 id := cc.String(s) 11864 off, ok := p.tsOffs[id] 11865 if !ok { 11866 off = uintptr(p.ts.Len()) 11867 p.ts.WriteString(s) 11868 p.ts.WriteByte(0) 11869 p.tsOffs[id] = off 11870 } 11871 return fmt.Sprintf("(%s%s)%s", p.tsNameP, nonZeroUintptr(off), p.stringSnippet(s)) 11872 } 11873 11874 func (p *project) stringLiteral(v cc.Value) string { 11875 if p.pass1 { 11876 return "" 11877 } 11878 11879 switch x := v.(type) { 11880 case cc.StringValue: 11881 id := cc.StringID(x) 11882 off, ok := p.tsOffs[id] 11883 s := id.String() 11884 if !ok { 11885 off = uintptr(p.ts.Len()) 11886 p.ts.WriteString(s) 11887 p.ts.WriteByte(0) 11888 p.tsOffs[id] = off 11889 } 11890 return fmt.Sprintf("(%s%s)%s", p.tsNameP, nonZeroUintptr(off), p.stringSnippet(s)) 11891 default: 11892 panic(todo("%T", x)) 11893 } 11894 } 11895 11896 func (p *project) stringSnippet(s string) string { 11897 s = strings.ReplaceAll(s, "*/", "*\\/") 11898 const max = 16 11899 switch { 11900 case len(s) <= max: 11901 return fmt.Sprintf("/* %q */", s) 11902 default: 11903 return fmt.Sprintf("/* %q */", s[:16]+"...") 11904 } 11905 } 11906 11907 func (p *project) wideStringLiteral(v cc.Value, pad int) string { 11908 if p.pass1 { 11909 return "" 11910 } 11911 11912 switch x := v.(type) { 11913 case cc.WideStringValue: 11914 id := cc.StringID(x) 11915 off, ok := p.tsWOffs[id] 11916 if !ok { 11917 off = p.wcharSize * uintptr(len(p.tsW)) 11918 s := []rune(id.String()) 11919 if pad != 0 { 11920 s = append(s, make([]rune, pad)...) 11921 } 11922 p.tsW = append(p.tsW, s...) 11923 p.tsW = append(p.tsW, 0) 11924 p.tsWOffs[id] = off 11925 } 11926 return fmt.Sprintf("(%s%s)", p.tsWNameP, nonZeroUintptr(off)) 11927 default: 11928 panic(todo("%T", x)) 11929 } 11930 } 11931 11932 func (p *project) charConst(n cc.Node, src string, op cc.Operand, to cc.Type, flags flags) { 11933 switch { 11934 case to.IsArithmeticType(): 11935 defer p.w("%s", p.convert(n, op, to, flags)) 11936 case to.Kind() == cc.Ptr && op.IsZero(): 11937 p.w(" 0 ") 11938 return 11939 default: 11940 panic(todo("%v: t %v, to %v, to.Alias() %v", n.Position(), op.Type(), to, to.Alias())) 11941 } 11942 11943 r, mb, _, err := strconv.UnquoteChar(src[1:len(src)-1], '\'') 11944 rValid := !mb && err == nil 11945 var on uint64 11946 switch x := op.Value().(type) { 11947 case cc.Int64Value: 11948 on = uint64(x) 11949 case cc.Uint64Value: 11950 on = uint64(x) 11951 default: 11952 panic(todo("%T(%v)", x, x)) 11953 } 11954 var mask uint64 11955 switch { 11956 case !to.IsIntegerType(): 11957 // ok 11958 if rValid { // Prefer original form 11959 p.w("%s", src) 11960 return 11961 } 11962 11963 p.w("%d", on) 11964 return 11965 case to.IsSignedType(): 11966 var in int64 11967 var ok bool 11968 switch to.Size() { 11969 case 1: 11970 in = int64(int8(on)) 11971 ok = int8(on) >= 0 11972 case 2: 11973 in = int64(int16(on)) 11974 ok = int16(on) >= 0 11975 case 4: 11976 in = int64(int32(on)) 11977 ok = int32(on) >= 0 11978 case 8: 11979 in = int64(int64(on)) 11980 ok = in >= 0 11981 default: 11982 panic(todo("", op.Type().Size())) 11983 } 11984 if ok && rValid && uint64(in) == on { // Prefer original form 11985 p.w("%s", src) 11986 return 11987 } 11988 11989 p.w("%d", in) 11990 default: 11991 switch to.Size() { 11992 case 1: 11993 mask = 0xff 11994 case 2: 11995 mask = 0xffff 11996 case 4: 11997 mask = 0xffffffff 11998 case 8: 11999 mask = 0xffffffffffffffff 12000 default: 12001 panic(todo("", op.Type().Size())) 12002 } 12003 if rValid && uint64(r)&mask == on { // Prefer original form 12004 p.w("%s", src) 12005 return 12006 } 12007 12008 p.w("%d", on&mask) 12009 } 12010 } 12011 12012 func (p *project) floatConst(n cc.Node, src string, op cc.Operand, to cc.Type, flags flags) { 12013 if flags&fForceRuntimeConv != 0 { 12014 p.w("%s(", p.helperType2(n, op.Type(), to)) 12015 defer p.w(")") 12016 } 12017 12018 bits := 64 12019 switch to.Kind() { 12020 case cc.Float: 12021 bits = 32 12022 } 12023 src = strings.TrimRight(src, "flFL") 12024 sn, err := strconv.ParseFloat(src, bits) 12025 snValid := err == nil 12026 switch x := op.Value().(type) { 12027 case cc.Float64Value: 12028 switch to.Kind() { 12029 case cc.Double: 12030 if snValid && sn == float64(x) { // Prefer original form. 12031 p.w("%s", src) 12032 return 12033 } 12034 12035 p.w("math.Float64frombits(%#x)", math.Float64bits(float64(x))) 12036 case cc.Float: 12037 if snValid && float32(sn) == float32(x) { // Prefer original form. 12038 p.w("%s", src) 12039 return 12040 } 12041 12042 p.w("math.Float32frombits(%#x)", math.Float32bits(float32(x))) 12043 default: 12044 defer p.w("%s", p.convert(n, op, to, 0)) 12045 if snValid && sn == float64(x) { // Prefer original form. 12046 p.w("%s", src) 12047 return 12048 } 12049 12050 p.w("math.Float64frombits(%#x)", math.Float64bits(float64(x))) 12051 } 12052 case cc.Float32Value: 12053 switch to.Kind() { 12054 case cc.Double: 12055 if snValid && float32(sn) == float32(x) { // Prefer original form. 12056 p.w("%s", src) 12057 return 12058 } 12059 12060 p.w("math.Float64frombits(%#x)", math.Float64bits(float64(x))) 12061 case cc.Float: 12062 if snValid && float32(sn) == float32(x) { // Prefer original form. 12063 p.w("%s", src) 12064 return 12065 } 12066 12067 p.w("math.Float32frombits(%#x)", math.Float32bits(float32(x))) 12068 default: 12069 if to.IsIntegerType() { 12070 if s := p.float2Int(n, x, to); s != "" { 12071 defer p.w("%s%s", s, p.convertType(n, op.Type(), to, 0)) 12072 break 12073 } 12074 } 12075 12076 defer p.w("%s", p.convert(n, op, to, 0)) 12077 if snValid && float32(sn) == float32(x) { // Prefer original form. 12078 p.w("%s", src) 12079 return 12080 } 12081 12082 p.w("math.Float32frombits(%#x)", math.Float32bits(float32(x))) 12083 } 12084 default: 12085 panic(todo("%T(%v)", x, x)) 12086 } 12087 } 12088 12089 func (p *project) float2Int(n cc.Node, x cc.Float32Value, to cc.Type) string { 12090 switch { 12091 case to.IsSignedType(): 12092 limits := &signedSaturationLimits[to.Size()] 12093 v := float64(x) 12094 switch { 12095 case math.IsNaN(v): 12096 panic(todo("", p.pos(n))) 12097 case math.IsInf(v, -1): 12098 panic(todo("", p.pos(n))) 12099 case math.IsInf(v, 1): 12100 panic(todo("", p.pos(n))) 12101 case v < limits.fmin: 12102 return fmt.Sprint(limits.min) 12103 case v > limits.fmax: 12104 return fmt.Sprint(limits.max) 12105 } 12106 default: 12107 limits := &unsignedSaturationLimits[to.Size()] 12108 v := float64(x) 12109 switch { 12110 case math.IsNaN(v): 12111 panic(todo("", p.pos(n))) 12112 case math.IsInf(v, -1): 12113 panic(todo("", p.pos(n))) 12114 case math.IsInf(v, 1): 12115 panic(todo("", p.pos(n))) 12116 case v < 0: 12117 return "0" 12118 case v > limits.fmax: 12119 return fmt.Sprint(limits.max) 12120 } 12121 } 12122 return "" 12123 } 12124 12125 type signedSaturationLimit struct { 12126 fmin, fmax float64 12127 min, max int64 12128 } 12129 12130 type unsignedSaturationLimit struct { 12131 fmax float64 12132 max uint64 12133 } 12134 12135 var ( 12136 signedSaturationLimits = [...]signedSaturationLimit{ 12137 1: {math.Nextafter(math.MinInt32, 0), math.Nextafter(math.MaxInt32, 0), math.MinInt32, math.MaxInt32}, 12138 2: {math.Nextafter(math.MinInt32, 0), math.Nextafter(math.MaxInt32, 0), math.MinInt32, math.MaxInt32}, 12139 4: {math.Nextafter(math.MinInt32, 0), math.Nextafter(math.MaxInt32, 0), math.MinInt32, math.MaxInt32}, 12140 8: {math.Nextafter(math.MinInt64, 0), math.Nextafter(math.MaxInt64, 0), math.MinInt64, math.MaxInt64}, 12141 } 12142 12143 unsignedSaturationLimits = [...]unsignedSaturationLimit{ 12144 1: {math.Nextafter(math.MaxUint32, 0), math.MaxUint32}, 12145 2: {math.Nextafter(math.MaxUint32, 0), math.MaxUint32}, 12146 4: {math.Nextafter(math.MaxUint32, 0), math.MaxUint32}, 12147 8: {math.Nextafter(math.MaxUint64, 0), math.MaxUint64}, 12148 } 12149 ) 12150 12151 func (p *project) intConst(n cc.Node, src string, op cc.Operand, to cc.Type, flags flags) { 12152 ptr := to.Kind() == cc.Ptr 12153 switch { 12154 case to.IsArithmeticType(): 12155 // p.w("/*10568 %T(%#[1]x) %v -> %v */", op.Value(), op.Type(), to) //TODO- 12156 if flags&fForceNoConv != 0 { 12157 break 12158 } 12159 12160 if !op.Type().IsSignedType() && op.Type().Size() == 8 && op.Value().(cc.Uint64Value) > math.MaxInt64 { 12161 flags |= fForceRuntimeConv 12162 } 12163 defer p.w("%s", p.convert(n, op, to, flags)) 12164 case ptr: 12165 p.w(" uintptr(") 12166 defer p.w(")") 12167 // ok 12168 default: 12169 panic(todo("%v: %v -> %v", p.pos(n), op.Type(), to)) 12170 } 12171 12172 src = strings.TrimRight(src, "luLU") 12173 sn, err := strconv.ParseUint(src, 0, 64) 12174 snValid := err == nil 12175 var on uint64 12176 switch x := op.Value().(type) { 12177 case cc.Int64Value: 12178 if x < 0 { 12179 sn, err := strconv.ParseInt(src, 0, 64) 12180 snValid := err == nil 12181 if snValid && sn == int64(x) { // Prefer original form 12182 p.w("%s", src) 12183 return 12184 } 12185 12186 p.w("%d", x) 12187 return 12188 } 12189 12190 on = uint64(x) 12191 case cc.Uint64Value: 12192 on = uint64(x) 12193 default: 12194 panic(todo("%T(%v)", x, x)) 12195 } 12196 12197 if snValid && sn == on { // Prefer original form 12198 p.w("%s", src) 12199 return 12200 } 12201 12202 p.w("%d", on) 12203 } 12204 12205 func (p *project) assignShiftOp(f *function, n *cc.AssignmentExpression, t cc.Type, mode exprMode, oper, oper2 string, flags flags) { 12206 // UnaryExpression "<<=" AssignmentExpression etc. 12207 switch mode { 12208 case exprVoid: 12209 p.assignShiftOpVoid(f, n, t, mode, oper, oper2, flags) 12210 default: 12211 panic(todo("", mode)) 12212 } 12213 } 12214 12215 func (p *project) assignShiftOpVoid(f *function, n *cc.AssignmentExpression, t cc.Type, mode exprMode, oper, oper2 string, flags flags) { 12216 // UnaryExpression "<<=" AssignmentExpression etc. 12217 switch k := p.opKind(f, n.UnaryExpression, n.UnaryExpression.Operand.Type()); k { 12218 case opNormal: 12219 p.assignShiftOpVoidNormal(f, n, t, mode, oper, oper2, flags) 12220 default: 12221 panic(todo("", n.Position(), k)) 12222 } 12223 } 12224 12225 func (p *project) assignShiftOpVoidNormal(f *function, n *cc.AssignmentExpression, t cc.Type, mode exprMode, oper, oper2 string, flags flags) { 12226 switch { 12227 case n.Operand.Type().IsBitFieldType(): 12228 panic(todo("", p.pos(n))) 12229 default: 12230 if d := n.UnaryExpression.Declarator(); d != nil { 12231 switch d.Type().Kind() { 12232 case cc.Int128, cc.UInt128: 12233 p.declarator(n, f, d, d.Type(), exprLValue, flags) 12234 p.w(".LValue%s(", oper2) 12235 p.assignmentExpression(f, n.AssignmentExpression, p.intType, exprValue, flags) 12236 p.w(")") 12237 return 12238 default: 12239 p.declarator(n, f, d, d.Type(), exprLValue, flags) 12240 p.w(" %s= ", oper) 12241 p.assignmentExpression(f, n.AssignmentExpression, n.Promote(), exprValue, flags) 12242 return 12243 } 12244 } 12245 12246 lhs := n.UnaryExpression 12247 switch { 12248 case lhs.Operand.Type().IsArithmeticType(): 12249 p.w("%sAssign%sPtr%s(", p.task.crt, oper2, p.helperType(n, lhs.Operand.Type())) 12250 p.unaryExpression(f, lhs, lhs.Operand.Type(), exprAddrOf, flags) 12251 p.w(", int(") 12252 p.assignmentExpression(f, n.AssignmentExpression, n.Promote(), exprValue, flags) 12253 p.w("))") 12254 default: 12255 panic(todo("", p.pos(n), lhs.Operand.Type())) 12256 } 12257 } 12258 } 12259 12260 func (p *project) assignOp(f *function, n *cc.AssignmentExpression, t cc.Type, mode exprMode, oper, oper2 string, flags flags) { 12261 // UnaryExpression "*=" AssignmentExpression etc. 12262 switch mode { 12263 case exprVoid: 12264 p.assignOpVoid(f, n, t, mode, oper, oper2, flags) 12265 case exprValue, exprCondReturn: 12266 p.assignOpValue(f, n, t, mode, oper, oper2, flags) 12267 default: 12268 panic(todo("", n.Position(), mode)) 12269 } 12270 } 12271 12272 func (p *project) assignOpValue(f *function, n *cc.AssignmentExpression, t cc.Type, mode exprMode, oper, oper2 string, flags flags) { 12273 // UnaryExpression "*=" AssignmentExpression etc. 12274 switch k := p.opKind(f, n.UnaryExpression, n.UnaryExpression.Operand.Type()); k { 12275 case opNormal: 12276 p.assignOpValueNormal(f, n, t, oper, oper2, mode, flags) 12277 case opBitfield: 12278 p.assignOpValueBitfield(f, n, t, oper, oper2, mode, flags) 12279 default: 12280 panic(todo("", n.Position(), k)) 12281 } 12282 } 12283 12284 func (p *project) assignOpValueBitfield(f *function, n *cc.AssignmentExpression, t cc.Type, oper, oper2 string, mode exprMode, flags flags) { 12285 // UnaryExpression "*=" AssignmentExpression etc. 12286 12287 asInt := oper2 == "Shl" || oper2 == "Shr" 12288 if asInt { 12289 panic(todo("")) 12290 } 12291 12292 ot := n.Operand.Type() 12293 lhs := n.UnaryExpression 12294 bf := lhs.Operand.Type().BitField() 12295 defer p.w("%s", p.convertType(n, ot, t, flags)) 12296 p.w(" func() %v {", p.typ(n, ot)) 12297 switch lhs.Case { 12298 case cc.UnaryExpressionPostfix: // PostfixExpression 12299 pe := n.UnaryExpression.PostfixExpression 12300 switch pe.Case { 12301 case cc.PostfixExpressionSelect: // PostfixExpression '.' IDENTIFIER 12302 p.w("__p := ") 12303 p.postfixExpression(f, pe, pe.Operand.Type(), exprAddrOf, flags) 12304 p.w("; __v := ") 12305 p.readBitfield(lhs, "__p", bf, ot) 12306 p.w(" %s (", oper) 12307 p.assignmentExpression(f, n.AssignmentExpression, ot, exprValue, flags) 12308 p.w("); return %sAssignBitFieldPtr%d%s(__p, __v, %d, %d, %#x)", p.task.crt, bf.BitFieldBlockWidth(), p.bfHelperType(ot), bf.BitFieldWidth(), bf.BitFieldOffset(), bf.Mask()) 12309 case cc.PostfixExpressionPSelect: // PostfixExpression "->" IDENTIFIER 12310 panic(todo("", p.pos(n))) 12311 default: 12312 panic(todo("", n.Position(), pe.Case)) 12313 } 12314 default: 12315 panic(todo("", n.Position(), lhs.Case)) 12316 } 12317 p.w("}()") 12318 } 12319 12320 func (p *project) readBitfield(n cc.Node, ptr string, bf cc.Field, promote cc.Type) { 12321 bw := bf.BitFieldBlockWidth() 12322 m := bf.Mask() 12323 o := bf.BitFieldOffset() 12324 w := bf.BitFieldWidth() 12325 p.w("(%s(*(*uint%d)(unsafe.Pointer(%s))&%#x)", p.typ(n, promote), bw, ptr, m) 12326 switch { 12327 case bf.Type().IsSignedType(): 12328 bits := int(promote.Size()) * 8 12329 p.w("<<%d>>%d)", bits-w-o, bits-w) 12330 default: 12331 p.w(">>%d)", o) 12332 } 12333 } 12334 12335 func (p *project) assignOpValueNormal(f *function, n *cc.AssignmentExpression, t cc.Type, oper, oper2 string, mode exprMode, flags flags) { 12336 if mode == exprCondReturn { 12337 p.w("return ") 12338 } 12339 asInt := oper2 == "Shl" || oper2 == "Shr" 12340 lhs := n.UnaryExpression 12341 // UnaryExpression "*=" AssignmentExpression etc. 12342 if d := lhs.Declarator(); d != nil { 12343 if local := f.locals[d]; local != nil && local.isPinned { 12344 switch { 12345 case lhs.Operand.Type().IsArithmeticType(): 12346 defer p.w("%s", p.convertType(n, lhs.Operand.Type(), t, flags)) 12347 p.w("%sAssign%sPtr%s(", p.task.crt, oper2, p.helperType(n, lhs.Operand.Type())) 12348 p.unaryExpression(f, lhs, lhs.Operand.Type(), exprAddrOf, flags) 12349 p.w(", ") 12350 if asInt { 12351 p.w("int(") 12352 } 12353 p.assignmentExpression(f, n.AssignmentExpression, lhs.Operand.Type(), exprValue, flags) 12354 if asInt { 12355 p.w(")") 12356 } 12357 p.w(")") 12358 default: 12359 panic(todo("", lhs.Operand.Type())) 12360 } 12361 return 12362 } 12363 12364 switch { 12365 case d.Type().Kind() == cc.Ptr: 12366 defer p.w("%s", p.convertType(n, d.Type(), t, flags)) 12367 p.w("%sAssign%s%s(&", p.task.crt, oper2, p.helperType(n, d.Type())) 12368 p.declarator(n, f, d, d.Type(), exprLValue, flags) 12369 p.w(", ") 12370 if dd := p.incDelta(d, d.Type()); dd != 1 { 12371 p.w("%d*(", dd) 12372 defer p.w(")") 12373 } 12374 p.assignmentExpression(f, n.AssignmentExpression, d.Type(), exprValue, flags) 12375 p.w(")") 12376 case d.Type().IsArithmeticType(): 12377 defer p.w("%s", p.convertType(n, d.Type(), t, flags)) 12378 p.w("%sAssign%s%s(&", p.task.crt, oper2, p.helperType(n, d.Type())) 12379 p.declarator(n, f, d, d.Type(), exprLValue, flags) 12380 p.w(", ") 12381 if asInt { 12382 p.w("int(") 12383 } 12384 p.assignmentExpression(f, n.AssignmentExpression, d.Type(), exprValue, flags) 12385 p.w(")") 12386 if asInt { 12387 p.w(")") 12388 } 12389 default: 12390 panic(todo("", p.pos(n), p.pos(d), d.Name())) 12391 } 12392 return 12393 } 12394 12395 switch { 12396 case lhs.Operand.Type().IsArithmeticType(): 12397 defer p.w("%s", p.convertType(n, lhs.Operand.Type(), t, flags)) 12398 p.w("%sAssign%sPtr%s(", p.task.crt, oper2, p.helperType(n, lhs.Operand.Type())) 12399 p.unaryExpression(f, lhs, lhs.Operand.Type(), exprAddrOf, flags) 12400 p.w(", ") 12401 if asInt { 12402 p.w("int(") 12403 } 12404 p.assignmentExpression(f, n.AssignmentExpression, lhs.Operand.Type(), exprValue, flags) 12405 if asInt { 12406 p.w(")") 12407 } 12408 p.w(")") 12409 default: 12410 panic(todo("", lhs.Operand.Type())) 12411 } 12412 } 12413 12414 func (p *project) assignOpVoid(f *function, n *cc.AssignmentExpression, t cc.Type, mode exprMode, oper, oper2 string, flags flags) { 12415 // UnaryExpression "*=" AssignmentExpression etc. 12416 switch k := p.opKind(f, n.UnaryExpression, n.UnaryExpression.Operand.Type()); k { 12417 case opNormal: 12418 p.assignOpVoidNormal(f, n, t, oper, oper2, mode, flags) 12419 case opBitfield: 12420 p.assignOpVoidBitfield(f, n, t, oper, oper2, mode, flags) 12421 case opArrayParameter: 12422 p.assignOpVoidArrayParameter(f, n, t, oper, oper2, mode, flags) 12423 default: 12424 panic(todo("", n.Position(), k)) 12425 } 12426 } 12427 12428 func (p *project) assignOpVoidArrayParameter(f *function, n *cc.AssignmentExpression, t cc.Type, oper, oper2 string, mode exprMode, flags flags) { 12429 // UnaryExpression "*=" AssignmentExpression etc. 12430 if oper != "+" && oper != "-" { 12431 panic(todo("", p.pos(n))) 12432 } 12433 12434 d := n.UnaryExpression.Declarator() 12435 switch local := f.locals[d]; { 12436 case local != nil && local.isPinned: 12437 p.w("*(*uintptr)(unsafe.Pointer(%s%s))", f.bpName, nonZeroUintptr(local.off)) 12438 default: 12439 p.declarator(n, f, d, d.Type(), exprLValue, flags) 12440 } 12441 12442 p.w(" %s= ", oper) 12443 if dd := p.incDelta(d, d.Type()); dd != 1 { 12444 p.w("%d*", dd) 12445 } 12446 p.w("uintptr(") 12447 p.assignmentExpression(f, n.AssignmentExpression, n.AssignmentExpression.Operand.Type(), exprValue, flags) 12448 p.w(")") 12449 } 12450 12451 func (p *project) assignOpVoidBitfield(f *function, n *cc.AssignmentExpression, t cc.Type, oper, oper2 string, mode exprMode, flags flags) { 12452 // UnaryExpression "*=" AssignmentExpression etc. 12453 lhs := n.UnaryExpression 12454 lt := lhs.Operand.Type() 12455 switch lhs.Case { 12456 case cc.UnaryExpressionPostfix: // PostfixExpression 12457 pe := n.UnaryExpression.PostfixExpression 12458 switch pe.Case { 12459 case cc.PostfixExpressionSelect: // PostfixExpression '.' IDENTIFIER 12460 bf := lt.BitField() 12461 p.w("%sSetBitFieldPtr%d%s(", p.task.crt, bf.BitFieldBlockWidth(), p.bfHelperType(n.Promote())) 12462 p.unaryExpression(f, lhs, lt, exprAddrOf, flags) 12463 p.w(", (") 12464 s := p.convertType(n, lt, n.Promote(), flags) 12465 p.unaryExpression(f, lhs, lt, exprValue, flags) 12466 p.w(")%s %s ", s, oper) 12467 s = p.convertType(n, lt, n.Promote(), flags) 12468 p.assignmentExpression(f, n.AssignmentExpression, n.Promote(), exprValue, flags) 12469 p.w("%s", s) 12470 p.w(", %d, %#x)", bf.BitFieldOffset(), bf.Mask()) 12471 case cc.PostfixExpressionPSelect: // PostfixExpression "->" IDENTIFIER 12472 switch d := pe.PostfixExpression.Declarator(); { 12473 case d != nil: 12474 panic(todo("", p.pos(n))) 12475 default: 12476 panic(todo("", p.pos(n))) 12477 } 12478 default: 12479 panic(todo("", n.Position(), pe.Case)) 12480 } 12481 default: 12482 panic(todo("", n.Position(), lhs.Case)) 12483 } 12484 } 12485 12486 func (p *project) assignOpVoidNormal(f *function, n *cc.AssignmentExpression, t cc.Type, oper, oper2 string, mode exprMode, flags flags) { 12487 // UnaryExpression "*=" AssignmentExpression etc. 12488 rop := n.AssignmentExpression.Operand 12489 if d := n.UnaryExpression.Declarator(); d != nil { 12490 if local := f.locals[d]; local != nil && local.isPinned { 12491 if p.isVolatileOrAtomic(d) { 12492 panic(todo("")) 12493 } 12494 12495 p.declarator(n, f, d, d.Type(), exprLValue, flags) 12496 switch { 12497 case d.Type().Kind() == cc.Ptr: 12498 p.w(" %s= ", oper) 12499 if dd := p.incDelta(d, d.Type()); dd != 1 { 12500 p.w("%d*(", dd) 12501 defer p.w(")") 12502 } 12503 defer p.w("%s", p.convert(n, rop.ConvertTo(n.Promote()), d.Type(), flags)) 12504 p.assignmentExpression(f, n.AssignmentExpression, n.Promote(), exprValue, flags) 12505 case d.Type().IsArithmeticType(): 12506 p.w(" %s= ", oper) 12507 defer p.w("%s", p.convert(n, rop.ConvertTo(n.Promote()), d.Type(), flags)) 12508 p.assignmentExpression(f, n.AssignmentExpression, n.Promote(), exprValue, flags) 12509 default: 12510 panic(todo("", n.Position(), d.Type().Kind())) 12511 } 12512 return 12513 } 12514 12515 if p.isVolatileOrAtomic(d) { 12516 var local *local 12517 var tld *tld 12518 var nm string 12519 if f != nil { 12520 if local = f.locals[d]; local != nil { 12521 nm = local.name 12522 } 12523 } 12524 12525 if local == nil { 12526 if tld = p.tlds[d]; tld == nil { 12527 p.err(n, "%v: internal error (%v: %v)", n.Position(), d.Position(), d.Name()) 12528 return 12529 } 12530 12531 nm = tld.name 12532 } 12533 var sign string 12534 switch oper { 12535 case "-": 12536 sign = oper 12537 fallthrough 12538 case "+": 12539 sz := d.Type().Size() 12540 var ht string 12541 switch sz { 12542 case 4, 8: 12543 if !d.Type().IsScalarType() { 12544 p.err(n, "unsupported volatile declarator type: %v", d.Type()) 12545 break 12546 } 12547 12548 ht = p.helperType(n, d.Type()) 12549 default: 12550 p.err(n, "unsupported volatile declarator size: %v", sz) 12551 return 12552 } 12553 12554 if local != nil { 12555 if local.isPinned { 12556 panic(todo("")) 12557 } 12558 } 12559 12560 p.w("%sAtomicAdd%s(&%s, %s%s(", p.task.crt, ht, nm, sign, p.typ(n, d.Type())) 12561 p.assignmentExpression(f, n.AssignmentExpression, n.Promote(), exprValue, flags) 12562 p.w("))") 12563 return 12564 default: 12565 p.warn(n, "unsupported volatile declarator operation: %v", oper) 12566 p.w("%s = ", nm) 12567 defer p.w("%s", p.convert(n, rop.ConvertTo(n.Promote()), d.Type(), flags)) 12568 p.declarator(n, f, d, n.Promote(), exprValue, flags) 12569 p.w(" %s (", oper) 12570 p.assignmentExpression(f, n.AssignmentExpression, n.Promote(), exprValue, flags) 12571 p.w(")") 12572 return 12573 } 12574 } 12575 12576 p.declarator(n, f, d, d.Type(), exprLValue, flags) 12577 switch d.Type().Kind() { 12578 case cc.Ptr: 12579 if oper != "+" && oper != "-" { 12580 panic(todo("", p.pos(n))) 12581 } 12582 12583 p.w(" %s= ", oper) 12584 if dd := p.incDelta(d, d.Type()); dd != 1 { 12585 p.w("%d*(", dd) 12586 defer p.w(")") 12587 } 12588 defer p.w("%s", p.convert(n, rop.ConvertTo(n.Promote()), d.Type(), flags)) 12589 p.assignmentExpression(f, n.AssignmentExpression, n.Promote(), exprValue, flags) 12590 case cc.Int128, cc.UInt128: 12591 p.w(" = ") 12592 p.declarator(n, f, d, n.Promote(), exprValue, flags) 12593 p.w(".%s(", oper2) 12594 p.assignmentExpression(f, n.AssignmentExpression, n.Promote(), exprValue, flags) 12595 p.w(")") 12596 default: 12597 p.w(" = ") 12598 defer p.w("%s", p.convert(n, rop.ConvertTo(n.Promote()), d.Type(), flags)) 12599 p.declarator(n, f, d, n.Promote(), exprValue, flags) 12600 p.w(" %s (", oper) 12601 p.assignmentExpression(f, n.AssignmentExpression, n.Promote(), exprValue, flags) 12602 p.w(")") 12603 } 12604 return 12605 } 12606 12607 lhs := n.UnaryExpression 12608 switch { 12609 case lhs.Operand.Type().IsArithmeticType(): 12610 p.w("*(*%s)(unsafe.Pointer(", p.typ(n, lhs.Operand.Type())) 12611 p.unaryExpression(f, lhs, lhs.Operand.Type(), exprAddrOf, flags) 12612 p.w(")) %s= ", oper) 12613 defer p.w("%s", p.convert(n, rop.ConvertTo(n.Promote()), lhs.Operand.Type(), flags)) 12614 p.w("(") 12615 p.assignmentExpression(f, n.AssignmentExpression, n.Promote(), exprValue, flags) 12616 p.w(")") 12617 case lhs.Operand.Type().Kind() == cc.Ptr: 12618 p.w("*(*%s)(unsafe.Pointer(", p.typ(n, lhs.Operand.Type())) 12619 p.unaryExpression(f, lhs, lhs.Operand.Type(), exprAddrOf, flags) 12620 p.w(")) %s= (", oper) 12621 p.assignmentExpression(f, n.AssignmentExpression, lhs.Operand.Type(), exprValue, flags) 12622 p.w(")") 12623 if dd := p.incDelta(n, lhs.Operand.Type()); dd != 1 { 12624 p.w("*%d", dd) 12625 } 12626 default: 12627 panic(todo("", lhs.Operand.Type())) 12628 } 12629 } 12630 12631 func (p *project) warn(n cc.Node, s string, args ...interface{}) { 12632 s = fmt.Sprintf(s, args...) 12633 s = strings.TrimRight(s, "\t\n\r") 12634 fmt.Fprintf(os.Stderr, "%v: warning: %s\n", n.Position(), s) 12635 } 12636 12637 func (p *project) iterationStatement(f *function, n *cc.IterationStatement) { 12638 sv := f.switchCtx 12639 sv2 := f.continueCtx 12640 sv3 := f.breakCtx 12641 f.switchCtx = 0 12642 f.continueCtx = 0 12643 f.breakCtx = 0 12644 defer func() { 12645 f.breakCtx = sv3 12646 f.continueCtx = sv2 12647 f.switchCtx = sv 12648 }() 12649 p.w("%s", tidyComment("\n", n)) 12650 switch n.Case { 12651 case cc.IterationStatementWhile: // "while" '(' Expression ')' Statement 12652 if f.hasJumps { 12653 // a: if !expr goto b 12654 // stmt 12655 // goto a 12656 // b: 12657 a := f.flatLabel() 12658 b := f.flatLabel() 12659 f.continueCtx = a 12660 f.breakCtx = b 12661 p.w("__%d: if !(", a) 12662 p.expression(f, n.Expression, n.Expression.Operand.Type(), exprBool, 0) 12663 p.w(") { goto __%d };", b) 12664 p.statement(f, n.Statement, false, false, false, 0) 12665 p.w("; goto __%d; __%d:", a, b) 12666 break 12667 } 12668 12669 p.w("for ") 12670 p.expression(f, n.Expression, n.Expression.Operand.Type(), exprBool, 0) 12671 p.statement(f, n.Statement, true, false, false, 0) 12672 case cc.IterationStatementDo: // "do" Statement "while" '(' Expression ')' ';' 12673 if f.hasJumps { 12674 // a: stmt 12675 // b: if expr goto a // b is the continue label 12676 // c: 12677 a := f.flatLabel() 12678 b := f.flatLabel() 12679 c := f.flatLabel() 12680 f.continueCtx = b 12681 f.breakCtx = c 12682 p.w("__%d:", a) 12683 p.statement(f, n.Statement, false, false, false, 0) 12684 p.w(";goto __%d; __%[1]d: if ", b) 12685 p.expression(f, n.Expression, n.Expression.Operand.Type(), exprBool, 0) 12686 p.w("{goto __%d};goto __%d;__%[2]d:", a, c) 12687 break 12688 } 12689 12690 v := "__ccgo" 12691 if !p.pass1 { 12692 v = f.scope.take(cc.String(v)) 12693 } 12694 p.w("for %v := true; %[1]v; %[1]v = ", v) 12695 p.expression(f, n.Expression, n.Expression.Operand.Type(), exprBool, 0) 12696 p.statement(f, n.Statement, true, false, false, 0) 12697 case cc.IterationStatementFor: // "for" '(' Expression ';' Expression ';' Expression ')' Statement 12698 if f.hasJumps || n.Expression3 != nil && n.Expression3.Case == cc.ExpressionComma { 12699 // expr 12700 // a: if !expr2 goto c 12701 // stmt 12702 // b: expr3 // label for continue 12703 // goto a 12704 // c: 12705 a := f.flatLabel() 12706 b := f.flatLabel() 12707 f.continueCtx = b 12708 c := f.flatLabel() 12709 f.breakCtx = c 12710 if n.Expression != nil { 12711 p.expression(f, n.Expression, n.Expression.Operand.Type(), exprVoid, fNoCondAssignment) 12712 } 12713 semi := "" 12714 if n.Expression != nil || n.Expression2 != nil || n.Expression3 != nil { 12715 semi = ";" 12716 } 12717 p.w("%s__%d:", semi, a) 12718 if n.Expression2 != nil { 12719 p.w("if !(") 12720 p.expression(f, n.Expression2, n.Expression2.Operand.Type(), exprBool, 0) 12721 p.w(") { goto __%d }", c) 12722 } 12723 p.w("%s", semi) 12724 p.statement(f, n.Statement, false, false, false, 0) 12725 p.w(";goto __%d; __%[1]d:", b) 12726 if n.Expression3 != nil { 12727 p.expression(f, n.Expression3, n.Expression3.Operand.Type(), exprVoid, fNoCondAssignment) 12728 } 12729 p.w("%sgoto __%d; goto __%d;__%[3]d:", semi, a, c) 12730 break 12731 } 12732 12733 expr := true 12734 if n.Expression != nil && n.Expression.Case == cc.ExpressionComma { 12735 p.expression(f, n.Expression, n.Expression.Operand.Type(), exprVoid, 0) 12736 p.w(";") 12737 expr = false 12738 } 12739 p.w("for ") 12740 if expr && n.Expression != nil { 12741 p.expression(f, n.Expression, n.Expression.Operand.Type(), exprVoid, fNoCondAssignment) 12742 } 12743 p.w("; ") 12744 if n.Expression2 != nil { 12745 p.expression(f, n.Expression2, n.Expression2.Operand.Type(), exprBool, 0) 12746 } 12747 p.w("; ") 12748 if n.Expression3 != nil { 12749 p.expression(f, n.Expression3, n.Expression3.Operand.Type(), exprVoid, fNoCondAssignment) 12750 } 12751 p.statement(f, n.Statement, true, false, false, 0) 12752 case cc.IterationStatementForDecl: // "for" '(' Declaration Expression ';' Expression ')' Statement 12753 if !(f.hasJumps || n.Expression2 != nil && n.Expression2.Case == cc.ExpressionComma) { 12754 p.w("{") 12755 p.declaration(f, n.Declaration, false) 12756 p.w("for ;") 12757 if n.Expression != nil { 12758 p.expression(f, n.Expression, n.Expression.Operand.Type(), exprBool, 0) 12759 } 12760 p.w(";") 12761 if n.Expression2 != nil { 12762 p.expression(f, n.Expression2, n.Expression2.Operand.Type(), exprVoid, fNoCondAssignment) 12763 } 12764 p.w("{") 12765 p.statement(f, n.Statement, false, true, false, 0) 12766 p.w("}};") 12767 break 12768 } 12769 12770 var ids []*cc.InitDeclarator 12771 for list := n.Declaration.InitDeclaratorList; list != nil; list = list.InitDeclaratorList { 12772 ids = append(ids, list.InitDeclarator) 12773 } 12774 12775 // declaration 12776 // a: if !expr goto c 12777 // stmt 12778 // b: expr2 // label for continue 12779 // goto a 12780 // c: 12781 a := f.flatLabel() 12782 b := f.flatLabel() 12783 f.continueCtx = b 12784 c := f.flatLabel() 12785 f.breakCtx = c 12786 p.w("{") 12787 p.declaration(f, n.Declaration, false) 12788 p.w(";") 12789 p.w("__%d:", a) 12790 if n.Expression != nil { 12791 p.w("if !(") 12792 p.expression(f, n.Expression, n.Expression.Operand.Type(), exprBool, 0) 12793 p.w(") { goto __%d }", c) 12794 } 12795 p.w(";") 12796 p.statement(f, n.Statement, false, false, false, 0) 12797 p.w(";goto __%d; __%[1]d:", b) 12798 if n.Expression2 != nil { 12799 p.expression(f, n.Expression2, n.Expression2.Operand.Type(), exprVoid, fNoCondAssignment) 12800 } 12801 p.w("; goto __%d; goto __%d;__%[2]d:\n}", a, c) 12802 default: 12803 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 12804 } 12805 } 12806 12807 func (p *project) selectionStatement(f *function, n *cc.SelectionStatement) { 12808 p.w("%s", tidyComment("\n", n)) 12809 switch n.Case { 12810 case cc.SelectionStatementIf: // "if" '(' Expression ')' Statement 12811 sv := f.ifCtx 12812 f.ifCtx = n 12813 defer func() { f.ifCtx = sv }() 12814 if f.hasJumps { 12815 // if !expr goto a 12816 // stmt 12817 // a: 12818 f.ifCtx = n 12819 a := f.flatLabel() 12820 p.w("if !(") 12821 p.expression(f, n.Expression, n.Expression.Operand.Type(), exprBool, 0) 12822 p.w(") { goto __%d };", a) 12823 p.statement(f, n.Statement, false, false, false, 0) 12824 p.w(";__%d: ", a) 12825 break 12826 } 12827 12828 p.w("if ") 12829 p.expression(f, n.Expression, n.Expression.Operand.Type(), exprBool, 0) 12830 p.statement(f, n.Statement, true, false, false, 0) 12831 case cc.SelectionStatementIfElse: // "if" '(' Expression ')' Statement "else" Statement 12832 sv := f.ifCtx 12833 f.ifCtx = n 12834 defer func() { f.ifCtx = sv }() 12835 if f.hasJumps { 12836 // if !expr goto a 12837 // stmt 12838 // goto b 12839 // a: 12840 // stmt2 12841 // b: 12842 a := f.flatLabel() 12843 b := f.flatLabel() 12844 p.w("if !(") 12845 p.expression(f, n.Expression, n.Expression.Operand.Type(), exprBool, 0) 12846 p.w(") { goto __%d };", a) 12847 p.statement(f, n.Statement, false, false, false, 0) 12848 p.w(";goto __%d; __%d:", b, a) 12849 p.statement(f, n.Statement2, false, false, false, 0) 12850 p.w(";__%d:", b) 12851 break 12852 } 12853 12854 p.w("if ") 12855 p.expression(f, n.Expression, n.Expression.Operand.Type(), exprBool, 0) 12856 p.statement(f, n.Statement, true, false, false, 0) 12857 p.w(" else ") 12858 switch { 12859 case p.isIfStmt(n.Statement2): 12860 p.statement(f, n.Statement2, false, true, false, 0) 12861 default: 12862 p.statement(f, n.Statement2, true, false, false, 0) 12863 } 12864 case cc.SelectionStatementSwitch: // "switch" '(' Expression ')' Statement 12865 // just dont generate in this case 12866 if f.switchCtx == inSwitchFirst { 12867 break 12868 } 12869 sv := f.switchCtx 12870 sb := f.block 12871 sc := p.pauseCodegen 12872 svBreakCtx := f.breakCtx 12873 f.breakCtx = 0 12874 f.block = f.blocks[n.Statement.CompoundStatement] 12875 12876 defer func() { 12877 f.block = sb 12878 f.switchCtx = sv 12879 f.breakCtx = svBreakCtx 12880 p.pauseCodegen = sc 12881 }() 12882 if f.hasJumps { 12883 f.switchCtx = inSwitchFlat 12884 p.flatSwitch(f, n) 12885 break 12886 } 12887 12888 f.switchCtx = inSwitchFirst 12889 // fmt.Println(f.block.decls) 12890 if len(f.block.decls) != 0 { 12891 f.block.topDecl = true 12892 // fmt.Printf("%p:%tf\n", f.block, f.block.topDecl) 12893 p.w("{") 12894 for _, v := range f.block.decls { 12895 // fmt.Printf("%p:%tf\n", f.block, f.block.topDecl) 12896 p.declaration(f, v, true) 12897 // fmt.Println("done!") 12898 } 12899 } 12900 12901 p.w("switch ") 12902 p.expression(f, n.Expression, n.Promote(), exprValue, 0) 12903 p.pauseCodegen = true 12904 p.statement(f, n.Statement, true, false, true, 0) 12905 p.pauseCodegen = false 12906 if len(f.block.decls) != 0 { 12907 p.w("}") 12908 } 12909 12910 default: 12911 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 12912 } 12913 } 12914 12915 func (p *project) isIfStmt(n *cc.Statement) bool { 12916 if n.Case != cc.StatementSelection { 12917 return false 12918 } 12919 12920 switch n.SelectionStatement.Case { 12921 case cc.SelectionStatementIf, cc.SelectionStatementIfElse: 12922 return true 12923 } 12924 12925 return false 12926 } 12927 12928 func (p *project) flatSwitch(f *function, n *cc.SelectionStatement) { 12929 if n.Statement.Case != cc.StatementCompound { 12930 panic(todo("", p.pos(n))) 12931 } 12932 12933 sv := f.block 12934 f.block = f.blocks[n.Statement.CompoundStatement] 12935 defer func() { f.block = sv }() 12936 // "switch" '(' Expression ')' Statement 12937 cases := n.Cases() 12938 labels := map[*cc.LabeledStatement]int{} 12939 svBreakCtx := f.breakCtx 12940 f.breakCtx = f.flatLabel() 12941 p.w("switch ") 12942 p.expression(f, n.Expression, n.Promote(), exprValue, 0) 12943 p.w("{") 12944 for _, ls := range cases { 12945 switch ls.Case { 12946 case cc.LabeledStatementLabel: // IDENTIFIER ':' AttributeSpecifierList Statement 12947 continue 12948 case cc.LabeledStatementCaseLabel: // "case" ConstantExpression ':' Statement 12949 p.w("%scase ", tidyComment("\n", ls)) 12950 p.constantExpression(f, ls.ConstantExpression, ls.ConstantExpression.Operand.Type(), exprValue, 0) 12951 p.w(":") 12952 case cc.LabeledStatementDefault: // "default" ':' Statement 12953 p.w("%sdefault:", tidyComment("\n", ls)) 12954 case cc.LabeledStatementRange: // "case" ConstantExpression "..." ConstantExpression ':' Statement 12955 panic(todo("", p.pos(n))) 12956 default: 12957 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 12958 } 12959 label := f.flatLabel() 12960 labels[ls] = label 12961 p.w("goto __%d;", label) 12962 } 12963 p.w("}; goto __%d;", f.breakCtx) 12964 svLabels := f.flatSwitchLabels 12965 f.flatSwitchLabels = labels 12966 p.statement(f, n.Statement, false, true, false, 0) 12967 f.flatSwitchLabels = svLabels 12968 p.w("__%d:", f.breakCtx) 12969 f.breakCtx = svBreakCtx 12970 } 12971 12972 func (p *project) expressionStatement(f *function, n *cc.ExpressionStatement) { 12973 p.w("%s", tidyComment("\n", n)) 12974 // Expression AttributeSpecifierList ';' 12975 if n.Expression == nil { 12976 return 12977 } 12978 12979 p.expression(f, n.Expression, n.Expression.Operand.Type(), exprVoid, 0) 12980 } 12981 12982 func (p *project) labeledStatement(f *function, n *cc.LabeledStatement) (r *cc.JumpStatement) { 12983 if f.hasJumps { //TODO merge with ...Flat below 12984 return p.labeledStatementFlat(f, n) 12985 } 12986 12987 switch n.Case { 12988 case cc.LabeledStatementLabel: // IDENTIFIER ':' AttributeSpecifierList Statement 12989 if _, ok := f.unusedLabels[n.Token.Value]; ok { 12990 p.w("goto %s;", f.labelNames[n.Token.Value]) 12991 } 12992 p.w("%s%s:", comment("\n", n), f.labelNames[n.Token.Value]) 12993 r = p.statement(f, n.Statement, false, false, false, 0) 12994 case 12995 cc.LabeledStatementCaseLabel, // "case" ConstantExpression ':' Statement 12996 cc.LabeledStatementDefault: // "default" ':' Statement 12997 12998 p.labeledStatementCase(f, n) 12999 case cc.LabeledStatementRange: // "case" ConstantExpression "..." ConstantExpression ':' Statement 13000 panic(todo("", n.Position(), n.Case)) 13001 default: 13002 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 13003 } 13004 return r 13005 } 13006 13007 func (p *project) labeledStatementFlat(f *function, n *cc.LabeledStatement) (r *cc.JumpStatement) { 13008 switch n.Case { 13009 case cc.LabeledStatementLabel: // IDENTIFIER ':' AttributeSpecifierList Statement 13010 if _, ok := f.unusedLabels[n.Token.Value]; ok { 13011 p.w("goto %s;", f.labelNames[n.Token.Value]) 13012 } 13013 p.w("%s%s:", tidyComment("\n", n), f.labelNames[n.Token.Value]) 13014 r = p.statement(f, n.Statement, false, false, false, 0) 13015 case 13016 cc.LabeledStatementCaseLabel, // "case" ConstantExpression ':' Statement 13017 cc.LabeledStatementDefault: // "default" ':' Statement 13018 13019 p.labeledStatementCase(f, n) 13020 case cc.LabeledStatementRange: // "case" ConstantExpression "..." ConstantExpression ':' Statement 13021 panic(todo("", n.Position(), n.Case)) 13022 default: 13023 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 13024 } 13025 return r 13026 } 13027 13028 func (p *project) labeledStatementCase(f *function, n *cc.LabeledStatement) { 13029 switch f.switchCtx { 13030 case inSwitchFirst: 13031 f.switchCtx = inSwitchCase 13032 p.pauseCodegen = false 13033 case inSwitchCase: 13034 p.w("\nfallthrough;") 13035 case inSwitchSeenBreak: 13036 f.switchCtx = inSwitchCase 13037 case inSwitchFlat: 13038 // ok 13039 default: 13040 panic(todo("", n.Position(), f.switchCtx)) 13041 } 13042 switch n.Case { 13043 case cc.LabeledStatementCaseLabel: // "case" ConstantExpression ':' Statement 13044 switch { 13045 case f.switchCtx == inSwitchFlat: 13046 p.w("%s__%d:", tidyComment("\n", n), f.flatSwitchLabels[n]) 13047 default: 13048 p.w("%scase ", tidyComment("\n", n)) 13049 p.constantExpression(f, n.ConstantExpression, n.ConstantExpression.Operand.Type(), exprValue, 0) 13050 p.w(":") 13051 } 13052 case cc.LabeledStatementDefault: // "default" ':' Statement 13053 switch { 13054 case f.switchCtx == inSwitchFlat: 13055 p.w("%s__%d:", tidyComment("\n", n), f.flatSwitchLabels[n]) 13056 default: 13057 p.w("%sdefault:", tidyComment("\n", n)) 13058 } 13059 default: 13060 panic(todo("%v: internal error: %v", n.Position(), n.Case)) 13061 } 13062 p.statement(f, n.Statement, false, false, false, 0) 13063 } 13064 13065 func (p *project) constantExpression(f *function, n *cc.ConstantExpression, t cc.Type, mode exprMode, flags flags) { 13066 // ConditionalExpression 13067 p.conditionalExpression(f, n.ConditionalExpression, t, mode, flags) 13068 } 13069 13070 func (p *project) functionDefinitionSignature(n cc.Node, f *function, tld *tld) { 13071 switch { 13072 case f.mainSignatureForced: 13073 p.w("%sfunc %s(%s *%sTLS, _ int32, _ uintptr) int32", tidyComment("\n", f.fndef), tld.name, f.tlsName, p.task.crt) 13074 default: 13075 p.w("%s", tidyComment("\n", f.fndef)) 13076 p.functionSignature(n, f, f.fndef.Declarator.Type(), tld.name) 13077 } 13078 } 13079 13080 func (p *project) functionSignature2(n cc.Node, f *function, t cc.Type, nm string) { 13081 p.w("func %s", nm) 13082 p.w("(_ *%sTLS", p.task.crt) 13083 suffix := 1 13084 for _, v := range t.Parameters() { 13085 if v.Type().Kind() == cc.Void { 13086 break 13087 } 13088 13089 pn := "_" 13090 if d := v.Declarator(); d != nil { 13091 pn = d.Name().String() 13092 if _, ok := reservedNames[pn]; ok { 13093 pn += strconv.Itoa(suffix) 13094 suffix++ 13095 } 13096 } 13097 p.w(", %s %s", pn, p.paramTyp(v.Declarator(), v.Type())) 13098 } 13099 if t.IsVariadic() { 13100 p.w(", _ /* va_list */ uintptr") 13101 } 13102 p.w(")") 13103 if rt := t.Result(); rt != nil && rt.Kind() != cc.Void { 13104 p.w(" %s", p.typ(n, rt)) 13105 } 13106 } 13107 13108 func (p *project) functionSignature(n cc.Node, f *function, t cc.Type, nm string) { 13109 p.w("func") 13110 if nm != "" { 13111 p.w(" %s", nm) 13112 } 13113 switch { 13114 case f == nil || nm == "": 13115 p.w("(*%sTLS", p.task.crt) 13116 default: 13117 p.w("(%s *%sTLS", f.tlsName, p.task.crt) 13118 } 13119 for _, v := range t.Parameters() { 13120 if v.Type().Kind() == cc.Void { 13121 break 13122 } 13123 13124 var pn string 13125 if f != nil && nm != "" { 13126 pn = "_" 13127 if d := v.Declarator(); d != nil { 13128 if local := f.locals[d]; local != nil { 13129 pn = local.name 13130 } 13131 } 13132 } 13133 p.w(", %s %s", pn, p.paramTyp(v.Declarator(), v.Type())) 13134 } 13135 if t.IsVariadic() { 13136 switch { 13137 case f == nil || nm == "": 13138 p.w(", uintptr") 13139 default: 13140 p.w(", %s uintptr", f.vaName) 13141 } 13142 } 13143 p.w(")") 13144 if rt := t.Result(); rt != nil && rt.Kind() != cc.Void { 13145 p.w(" %s", p.typ(n, rt)) 13146 } 13147 } 13148 13149 func (p *project) paramTyp(n cc.Node, t cc.Type) string { 13150 if t.Kind() == cc.Array { 13151 return "uintptr" 13152 } 13153 13154 if isTransparentUnion(t) { 13155 switch k := t.UnionCommon(); k { 13156 case cc.Ptr: 13157 return "uintptr" 13158 default: 13159 panic(todo("%v: %v %k", n, t, k)) 13160 } 13161 } 13162 13163 return p.typ(n, t) 13164 } 13165 13166 func (p *project) dbg(a ...interface{}) { 13167 p.w("/*DBG.%v %v */", a, origin(2)) 13168 } 13169 13170 func (p *project) fnVal(n cc.Node, f *function, expr func(), exprDecl *cc.Declarator, exprType cc.Type, deref int, mode exprMode, flags flags) { 13171 // C type Go type 13172 // fn N/A: produce name from exprDecl 13173 // (*)() func() 13174 // (**)() *func() 13175 13176 if deref < 0 || deref > 1 { 13177 panic(todo("")) 13178 } 13179 13180 switch exprType.Kind() { 13181 case cc.Function: 13182 // C: fn 13183 switch deref { 13184 case 0: 13185 p.declarator(n, f, exprDecl, exprType, mode, flags) 13186 default: 13187 panic(todo("", n.Position())) 13188 } 13189 case cc.Ptr: 13190 switch et := exprType.Elem(); et.Kind() { 13191 case cc.Function: 13192 // C: (*)() 13193 switch deref { 13194 case 0: 13195 // (*struct{ f func()})(unsafe.Pointer(&struct{uintptr}{fprintfptr})).f() 13196 p.w("(*struct{ f ") 13197 p.functionSignature(n, f, et, "") 13198 p.w("})(unsafe.Pointer(&struct{uintptr}{") 13199 expr() 13200 p.w("})).f") 13201 default: 13202 p.declarator(n, f, exprDecl, et, mode, flags) 13203 } 13204 case cc.Ptr: 13205 switch et2 := et.Elem(); et2.Kind() { 13206 case cc.Function: 13207 // C: (**)() 13208 switch deref { 13209 case 0: 13210 panic(todo("", n.Position())) 13211 default: 13212 // (*struct{ f func()})(unsafe.Pointer(&struct{uintptr}{fprintfptr})).f() 13213 p.w("(*(**struct{ f ") 13214 p.functionSignature(n, f, et2, "") 13215 p.w("})(unsafe.Pointer(&struct{uintptr}{") 13216 expr() 13217 p.w("}))).f") 13218 } 13219 default: 13220 panic(todo("", n.Position(), et2.Kind(), deref)) 13221 } 13222 default: 13223 panic(todo("", n.Position(), et.Kind(), deref)) 13224 } 13225 default: 13226 panic(todo("", n.Position(), exprType.Kind(), deref)) 13227 } 13228 }