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