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  }