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