github.com/rsc/tmp@v0.0.0-20240517235954-6deaab19748b/bootstrap/internal/gc/align.go (about) 1 // Do not edit. Bootstrap copy of /Users/rsc/g/go/src/cmd/internal/gc/align.go 2 3 // Copyright 2009 The Go Authors. All rights reserved. 4 // Use of this source code is governed by a BSD-style 5 // license that can be found in the LICENSE file. 6 7 package gc 8 9 import "rsc.io/tmp/bootstrap/internal/obj" 10 11 /* 12 * machine size and rounding 13 * alignment is dictated around 14 * the size of a pointer, set in betypeinit 15 * (see ../6g/galign.c). 16 */ 17 var defercalc int 18 19 func Rnd(o int64, r int64) int64 { 20 if r < 1 || r > 8 || r&(r-1) != 0 { 21 Fatal("rnd %d", r) 22 } 23 return (o + r - 1) &^ (r - 1) 24 } 25 26 func offmod(t *Type) { 27 o := int32(0) 28 for f := t.Type; f != nil; f = f.Down { 29 if f.Etype != TFIELD { 30 Fatal("offmod: not TFIELD: %v", Tconv(f, obj.FmtLong)) 31 } 32 f.Width = int64(o) 33 o += int32(Widthptr) 34 if int64(o) >= Thearch.MAXWIDTH { 35 Yyerror("interface too large") 36 o = int32(Widthptr) 37 } 38 } 39 } 40 41 func widstruct(errtype *Type, t *Type, o int64, flag int) int64 { 42 starto := o 43 maxalign := int32(flag) 44 if maxalign < 1 { 45 maxalign = 1 46 } 47 lastzero := int64(0) 48 var w int64 49 for f := t.Type; f != nil; f = f.Down { 50 if f.Etype != TFIELD { 51 Fatal("widstruct: not TFIELD: %v", Tconv(f, obj.FmtLong)) 52 } 53 if f.Type == nil { 54 // broken field, just skip it so that other valid fields 55 // get a width. 56 continue 57 } 58 59 dowidth(f.Type) 60 if int32(f.Type.Align) > maxalign { 61 maxalign = int32(f.Type.Align) 62 } 63 if f.Type.Width < 0 { 64 Fatal("invalid width %d", f.Type.Width) 65 } 66 w = f.Type.Width 67 if f.Type.Align > 0 { 68 o = Rnd(o, int64(f.Type.Align)) 69 } 70 f.Width = o // really offset for TFIELD 71 if f.Nname != nil { 72 // this same stackparam logic is in addrescapes 73 // in typecheck.c. usually addrescapes runs after 74 // widstruct, in which case we could drop this, 75 // but function closure functions are the exception. 76 if f.Nname.Stackparam != nil { 77 f.Nname.Stackparam.Xoffset = o 78 f.Nname.Xoffset = 0 79 } else { 80 f.Nname.Xoffset = o 81 } 82 } 83 84 if w == 0 { 85 lastzero = o 86 } 87 o += w 88 if o >= Thearch.MAXWIDTH { 89 Yyerror("type %v too large", Tconv(errtype, obj.FmtLong)) 90 o = 8 // small but nonzero 91 } 92 } 93 94 // For nonzero-sized structs which end in a zero-sized thing, we add 95 // an extra byte of padding to the type. This padding ensures that 96 // taking the address of the zero-sized thing can't manufacture a 97 // pointer to the next object in the heap. See issue 9401. 98 if flag == 1 && o > starto && o == lastzero { 99 o++ 100 } 101 102 // final width is rounded 103 if flag != 0 { 104 o = Rnd(o, int64(maxalign)) 105 } 106 t.Align = uint8(maxalign) 107 108 // type width only includes back to first field's offset 109 t.Width = o - starto 110 111 return o 112 } 113 114 func dowidth(t *Type) { 115 if Widthptr == 0 { 116 Fatal("dowidth without betypeinit") 117 } 118 119 if t == nil { 120 return 121 } 122 123 if t.Width > 0 { 124 return 125 } 126 127 if t.Width == -2 { 128 lno := int(lineno) 129 lineno = int32(t.Lineno) 130 if t.Broke == 0 { 131 t.Broke = 1 132 Yyerror("invalid recursive type %v", t) 133 } 134 135 t.Width = 0 136 lineno = int32(lno) 137 return 138 } 139 140 // break infinite recursion if the broken recursive type 141 // is referenced again 142 if t.Broke != 0 && t.Width == 0 { 143 return 144 } 145 146 // defer checkwidth calls until after we're done 147 defercalc++ 148 149 lno := int(lineno) 150 lineno = int32(t.Lineno) 151 t.Width = -2 152 t.Align = 0 153 154 et := int32(t.Etype) 155 switch et { 156 case TFUNC, TCHAN, TMAP, TSTRING: 157 break 158 159 /* simtype == 0 during bootstrap */ 160 default: 161 if Simtype[t.Etype] != 0 { 162 et = int32(Simtype[t.Etype]) 163 } 164 } 165 166 w := int64(0) 167 switch et { 168 default: 169 Fatal("dowidth: unknown type: %v", t) 170 171 /* compiler-specific stuff */ 172 case TINT8, TUINT8, TBOOL: 173 // bool is int8 174 w = 1 175 176 case TINT16, TUINT16: 177 w = 2 178 179 case TINT32, TUINT32, TFLOAT32: 180 w = 4 181 182 case TINT64, TUINT64, TFLOAT64, TCOMPLEX64: 183 w = 8 184 t.Align = uint8(Widthreg) 185 186 case TCOMPLEX128: 187 w = 16 188 t.Align = uint8(Widthreg) 189 190 case TPTR32: 191 w = 4 192 checkwidth(t.Type) 193 194 case TPTR64: 195 w = 8 196 checkwidth(t.Type) 197 198 case TUNSAFEPTR: 199 w = int64(Widthptr) 200 201 case TINTER: // implemented as 2 pointers 202 w = 2 * int64(Widthptr) 203 204 t.Align = uint8(Widthptr) 205 offmod(t) 206 207 case TCHAN: // implemented as pointer 208 w = int64(Widthptr) 209 210 checkwidth(t.Type) 211 212 // make fake type to check later to 213 // trigger channel argument check. 214 t1 := typ(TCHANARGS) 215 216 t1.Type = t 217 checkwidth(t1) 218 219 case TCHANARGS: 220 t1 := t.Type 221 dowidth(t.Type) // just in case 222 if t1.Type.Width >= 1<<16 { 223 Yyerror("channel element type too large (>64kB)") 224 } 225 t.Width = 1 226 227 case TMAP: // implemented as pointer 228 w = int64(Widthptr) 229 230 checkwidth(t.Type) 231 checkwidth(t.Down) 232 233 case TFORW: // should have been filled in 234 if t.Broke == 0 { 235 Yyerror("invalid recursive type %v", t) 236 } 237 w = 1 // anything will do 238 239 // dummy type; should be replaced before use. 240 case TANY: 241 if Debug['A'] == 0 { 242 Fatal("dowidth any") 243 } 244 w = 1 // anything will do 245 246 case TSTRING: 247 if sizeof_String == 0 { 248 Fatal("early dowidth string") 249 } 250 w = int64(sizeof_String) 251 t.Align = uint8(Widthptr) 252 253 case TARRAY: 254 if t.Type == nil { 255 break 256 } 257 if t.Bound >= 0 { 258 dowidth(t.Type) 259 if t.Type.Width != 0 { 260 cap := (uint64(Thearch.MAXWIDTH) - 1) / uint64(t.Type.Width) 261 if uint64(t.Bound) > cap { 262 Yyerror("type %v larger than address space", Tconv(t, obj.FmtLong)) 263 } 264 } 265 266 w = t.Bound * t.Type.Width 267 t.Align = t.Type.Align 268 } else if t.Bound == -1 { 269 w = int64(sizeof_Array) 270 checkwidth(t.Type) 271 t.Align = uint8(Widthptr) 272 } else if t.Bound == -100 { 273 if t.Broke == 0 { 274 Yyerror("use of [...] array outside of array literal") 275 t.Broke = 1 276 } 277 } else { 278 Fatal("dowidth %v", t) // probably [...]T 279 } 280 281 case TSTRUCT: 282 if t.Funarg != 0 { 283 Fatal("dowidth fn struct %v", t) 284 } 285 w = widstruct(t, t, 0, 1) 286 287 // make fake type to check later to 288 // trigger function argument computation. 289 case TFUNC: 290 t1 := typ(TFUNCARGS) 291 292 t1.Type = t 293 checkwidth(t1) 294 295 // width of func type is pointer 296 w = int64(Widthptr) 297 298 // function is 3 cated structures; 299 // compute their widths as side-effect. 300 case TFUNCARGS: 301 t1 := t.Type 302 303 w = widstruct(t.Type, *getthis(t1), 0, 0) 304 w = widstruct(t.Type, *getinarg(t1), w, Widthreg) 305 w = widstruct(t.Type, *Getoutarg(t1), w, Widthreg) 306 t1.Argwid = w 307 if w%int64(Widthreg) != 0 { 308 Warn("bad type %v %d\n", t1, w) 309 } 310 t.Align = 1 311 } 312 313 if Widthptr == 4 && w != int64(int32(w)) { 314 Yyerror("type %v too large", t) 315 } 316 317 t.Width = w 318 if t.Align == 0 { 319 if w > 8 || w&(w-1) != 0 { 320 Fatal("invalid alignment for %v", t) 321 } 322 t.Align = uint8(w) 323 } 324 325 lineno = int32(lno) 326 327 if defercalc == 1 { 328 resumecheckwidth() 329 } else { 330 defercalc-- 331 } 332 } 333 334 /* 335 * when a type's width should be known, we call checkwidth 336 * to compute it. during a declaration like 337 * 338 * type T *struct { next T } 339 * 340 * it is necessary to defer the calculation of the struct width 341 * until after T has been initialized to be a pointer to that struct. 342 * similarly, during import processing structs may be used 343 * before their definition. in those situations, calling 344 * defercheckwidth() stops width calculations until 345 * resumecheckwidth() is called, at which point all the 346 * checkwidths that were deferred are executed. 347 * dowidth should only be called when the type's size 348 * is needed immediately. checkwidth makes sure the 349 * size is evaluated eventually. 350 */ 351 type TypeList struct { 352 t *Type 353 next *TypeList 354 } 355 356 var tlfree *TypeList 357 358 var tlq *TypeList 359 360 func checkwidth(t *Type) { 361 if t == nil { 362 return 363 } 364 365 // function arg structs should not be checked 366 // outside of the enclosing function. 367 if t.Funarg != 0 { 368 Fatal("checkwidth %v", t) 369 } 370 371 if defercalc == 0 { 372 dowidth(t) 373 return 374 } 375 376 if t.Deferwidth != 0 { 377 return 378 } 379 t.Deferwidth = 1 380 381 l := tlfree 382 if l != nil { 383 tlfree = l.next 384 } else { 385 l = new(TypeList) 386 } 387 388 l.t = t 389 l.next = tlq 390 tlq = l 391 } 392 393 func defercheckwidth() { 394 // we get out of sync on syntax errors, so don't be pedantic. 395 if defercalc != 0 && nerrors == 0 { 396 Fatal("defercheckwidth") 397 } 398 defercalc = 1 399 } 400 401 func resumecheckwidth() { 402 if defercalc == 0 { 403 Fatal("resumecheckwidth") 404 } 405 for l := tlq; l != nil; l = tlq { 406 l.t.Deferwidth = 0 407 tlq = l.next 408 dowidth(l.t) 409 l.next = tlfree 410 tlfree = l 411 } 412 413 defercalc = 0 414 } 415 416 var itable *Type // distinguished *byte 417 418 func typeinit() { 419 if Widthptr == 0 { 420 Fatal("typeinit before betypeinit") 421 } 422 423 for i := 0; i < NTYPE; i++ { 424 Simtype[i] = uint8(i) 425 } 426 427 Types[TPTR32] = typ(TPTR32) 428 dowidth(Types[TPTR32]) 429 430 Types[TPTR64] = typ(TPTR64) 431 dowidth(Types[TPTR64]) 432 433 t := typ(TUNSAFEPTR) 434 Types[TUNSAFEPTR] = t 435 t.Sym = Pkglookup("Pointer", unsafepkg) 436 t.Sym.Def = typenod(t) 437 438 dowidth(Types[TUNSAFEPTR]) 439 440 Tptr = TPTR32 441 if Widthptr == 8 { 442 Tptr = TPTR64 443 } 444 445 for i := TINT8; i <= TUINT64; i++ { 446 Isint[i] = true 447 } 448 Isint[TINT] = true 449 Isint[TUINT] = true 450 Isint[TUINTPTR] = true 451 452 Isfloat[TFLOAT32] = true 453 Isfloat[TFLOAT64] = true 454 455 Iscomplex[TCOMPLEX64] = true 456 Iscomplex[TCOMPLEX128] = true 457 458 Isptr[TPTR32] = true 459 Isptr[TPTR64] = true 460 461 isforw[TFORW] = true 462 463 Issigned[TINT] = true 464 Issigned[TINT8] = true 465 Issigned[TINT16] = true 466 Issigned[TINT32] = true 467 Issigned[TINT64] = true 468 469 /* 470 * initialize okfor 471 */ 472 for i := 0; i < NTYPE; i++ { 473 if Isint[i] || i == TIDEAL { 474 okforeq[i] = true 475 okforcmp[i] = true 476 okforarith[i] = true 477 okforadd[i] = true 478 okforand[i] = true 479 okforconst[i] = true 480 issimple[i] = true 481 Minintval[i] = new(Mpint) 482 Maxintval[i] = new(Mpint) 483 } 484 485 if Isfloat[i] { 486 okforeq[i] = true 487 okforcmp[i] = true 488 okforadd[i] = true 489 okforarith[i] = true 490 okforconst[i] = true 491 issimple[i] = true 492 minfltval[i] = newMpflt() 493 maxfltval[i] = newMpflt() 494 } 495 496 if Iscomplex[i] { 497 okforeq[i] = true 498 okforadd[i] = true 499 okforarith[i] = true 500 okforconst[i] = true 501 issimple[i] = true 502 } 503 } 504 505 issimple[TBOOL] = true 506 507 okforadd[TSTRING] = true 508 509 okforbool[TBOOL] = true 510 511 okforcap[TARRAY] = true 512 okforcap[TCHAN] = true 513 514 okforconst[TBOOL] = true 515 okforconst[TSTRING] = true 516 517 okforlen[TARRAY] = true 518 okforlen[TCHAN] = true 519 okforlen[TMAP] = true 520 okforlen[TSTRING] = true 521 522 okforeq[TPTR32] = true 523 okforeq[TPTR64] = true 524 okforeq[TUNSAFEPTR] = true 525 okforeq[TINTER] = true 526 okforeq[TCHAN] = true 527 okforeq[TSTRING] = true 528 okforeq[TBOOL] = true 529 okforeq[TMAP] = true // nil only; refined in typecheck 530 okforeq[TFUNC] = true // nil only; refined in typecheck 531 okforeq[TARRAY] = true // nil slice only; refined in typecheck 532 okforeq[TSTRUCT] = true // it's complicated; refined in typecheck 533 534 okforcmp[TSTRING] = true 535 536 var i int 537 for i = 0; i < len(okfor); i++ { 538 okfor[i] = okfornone[:] 539 } 540 541 // binary 542 okfor[OADD] = okforadd[:] 543 544 okfor[OAND] = okforand[:] 545 okfor[OANDAND] = okforbool[:] 546 okfor[OANDNOT] = okforand[:] 547 okfor[ODIV] = okforarith[:] 548 okfor[OEQ] = okforeq[:] 549 okfor[OGE] = okforcmp[:] 550 okfor[OGT] = okforcmp[:] 551 okfor[OLE] = okforcmp[:] 552 okfor[OLT] = okforcmp[:] 553 okfor[OMOD] = okforand[:] 554 okfor[OMUL] = okforarith[:] 555 okfor[ONE] = okforeq[:] 556 okfor[OOR] = okforand[:] 557 okfor[OOROR] = okforbool[:] 558 okfor[OSUB] = okforarith[:] 559 okfor[OXOR] = okforand[:] 560 okfor[OLSH] = okforand[:] 561 okfor[ORSH] = okforand[:] 562 563 // unary 564 okfor[OCOM] = okforand[:] 565 566 okfor[OMINUS] = okforarith[:] 567 okfor[ONOT] = okforbool[:] 568 okfor[OPLUS] = okforarith[:] 569 570 // special 571 okfor[OCAP] = okforcap[:] 572 573 okfor[OLEN] = okforlen[:] 574 575 // comparison 576 iscmp[OLT] = true 577 578 iscmp[OGT] = true 579 iscmp[OGE] = true 580 iscmp[OLE] = true 581 iscmp[OEQ] = true 582 iscmp[ONE] = true 583 584 mpatofix(Maxintval[TINT8], "0x7f") 585 mpatofix(Minintval[TINT8], "-0x80") 586 mpatofix(Maxintval[TINT16], "0x7fff") 587 mpatofix(Minintval[TINT16], "-0x8000") 588 mpatofix(Maxintval[TINT32], "0x7fffffff") 589 mpatofix(Minintval[TINT32], "-0x80000000") 590 mpatofix(Maxintval[TINT64], "0x7fffffffffffffff") 591 mpatofix(Minintval[TINT64], "-0x8000000000000000") 592 593 mpatofix(Maxintval[TUINT8], "0xff") 594 mpatofix(Maxintval[TUINT16], "0xffff") 595 mpatofix(Maxintval[TUINT32], "0xffffffff") 596 mpatofix(Maxintval[TUINT64], "0xffffffffffffffff") 597 598 /* f is valid float if min < f < max. (min and max are not themselves valid.) */ 599 mpatoflt(maxfltval[TFLOAT32], "33554431p103") /* 2^24-1 p (127-23) + 1/2 ulp*/ 600 mpatoflt(minfltval[TFLOAT32], "-33554431p103") 601 mpatoflt(maxfltval[TFLOAT64], "18014398509481983p970") /* 2^53-1 p (1023-52) + 1/2 ulp */ 602 mpatoflt(minfltval[TFLOAT64], "-18014398509481983p970") 603 604 maxfltval[TCOMPLEX64] = maxfltval[TFLOAT32] 605 minfltval[TCOMPLEX64] = minfltval[TFLOAT32] 606 maxfltval[TCOMPLEX128] = maxfltval[TFLOAT64] 607 minfltval[TCOMPLEX128] = minfltval[TFLOAT64] 608 609 /* for walk to use in error messages */ 610 Types[TFUNC] = functype(nil, nil, nil) 611 612 /* types used in front end */ 613 // types[TNIL] got set early in lexinit 614 Types[TIDEAL] = typ(TIDEAL) 615 616 Types[TINTER] = typ(TINTER) 617 618 /* simple aliases */ 619 Simtype[TMAP] = uint8(Tptr) 620 621 Simtype[TCHAN] = uint8(Tptr) 622 Simtype[TFUNC] = uint8(Tptr) 623 Simtype[TUNSAFEPTR] = uint8(Tptr) 624 625 /* pick up the backend thearch.typedefs */ 626 var s1 *Sym 627 var etype int 628 var sameas int 629 var s *Sym 630 for i = range Thearch.Typedefs { 631 s = Lookup(Thearch.Typedefs[i].Name) 632 s1 = Pkglookup(Thearch.Typedefs[i].Name, builtinpkg) 633 634 etype = Thearch.Typedefs[i].Etype 635 if etype < 0 || etype >= len(Types) { 636 Fatal("typeinit: %s bad etype", s.Name) 637 } 638 sameas = Thearch.Typedefs[i].Sameas 639 if sameas < 0 || sameas >= len(Types) { 640 Fatal("typeinit: %s bad sameas", s.Name) 641 } 642 Simtype[etype] = uint8(sameas) 643 minfltval[etype] = minfltval[sameas] 644 maxfltval[etype] = maxfltval[sameas] 645 Minintval[etype] = Minintval[sameas] 646 Maxintval[etype] = Maxintval[sameas] 647 648 t = Types[etype] 649 if t != nil { 650 Fatal("typeinit: %s already defined", s.Name) 651 } 652 653 t = typ(etype) 654 t.Sym = s1 655 656 dowidth(t) 657 Types[etype] = t 658 s1.Def = typenod(t) 659 } 660 661 Array_array = int(Rnd(0, int64(Widthptr))) 662 Array_nel = int(Rnd(int64(Array_array)+int64(Widthptr), int64(Widthint))) 663 Array_cap = int(Rnd(int64(Array_nel)+int64(Widthint), int64(Widthint))) 664 sizeof_Array = int(Rnd(int64(Array_cap)+int64(Widthint), int64(Widthptr))) 665 666 // string is same as slice wo the cap 667 sizeof_String = int(Rnd(int64(Array_nel)+int64(Widthint), int64(Widthptr))) 668 669 dowidth(Types[TSTRING]) 670 dowidth(idealstring) 671 672 itable = typ(Tptr) 673 itable.Type = Types[TUINT8] 674 } 675 676 /* 677 * compute total size of f's in/out arguments. 678 */ 679 func Argsize(t *Type) int { 680 var save Iter 681 var x int64 682 683 w := int64(0) 684 685 fp := Structfirst(&save, Getoutarg(t)) 686 for fp != nil { 687 x = fp.Width + fp.Type.Width 688 if x > w { 689 w = x 690 } 691 fp = structnext(&save) 692 } 693 694 fp = funcfirst(&save, t) 695 for fp != nil { 696 x = fp.Width + fp.Type.Width 697 if x > w { 698 w = x 699 } 700 fp = funcnext(&save) 701 } 702 703 w = (w + int64(Widthptr) - 1) &^ (int64(Widthptr) - 1) 704 if int64(int(w)) != w { 705 Fatal("argsize too big") 706 } 707 return int(w) 708 }