github.com/rsc/go@v0.0.0-20150416155037-e040fd465409/src/cmd/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  		Fatal("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  			Fatal("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  			Fatal("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  			Fatal("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.Stackparam != nil {
    75  				f.Nname.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  		Fatal("dowidth without betypeinit")
   115  	}
   116  
   117  	if t == nil {
   118  		return
   119  	}
   120  
   121  	if t.Width > 0 {
   122  		return
   123  	}
   124  
   125  	if t.Width == -2 {
   126  		lno := int(lineno)
   127  		lineno = int32(t.Lineno)
   128  		if t.Broke == 0 {
   129  			t.Broke = 1
   130  			Yyerror("invalid recursive type %v", Tconv(t, 0))
   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 != 0 && 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 := int32(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 = int32(Simtype[t.Etype])
   161  		}
   162  	}
   163  
   164  	w := int64(0)
   165  	switch et {
   166  	default:
   167  		Fatal("dowidth: unknown type: %v", Tconv(t, 0))
   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 == 0 {
   233  			Yyerror("invalid recursive type %v", Tconv(t, 0))
   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  			Fatal("dowidth any")
   241  		}
   242  		w = 1 // anything will do
   243  
   244  	case TSTRING:
   245  		if sizeof_String == 0 {
   246  			Fatal("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 == 0 {
   272  				Yyerror("use of [...] array outside of array literal")
   273  				t.Broke = 1
   274  			}
   275  		} else {
   276  			Fatal("dowidth %v", Tconv(t, 0)) // probably [...]T
   277  		}
   278  
   279  	case TSTRUCT:
   280  		if t.Funarg != 0 {
   281  			Fatal("dowidth fn struct %v", Tconv(t, 0))
   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", Tconv(t1, 0), w)
   307  		}
   308  		t.Align = 1
   309  	}
   310  
   311  	if Widthptr == 4 && w != int64(int32(w)) {
   312  		Yyerror("type %v too large", Tconv(t, 0))
   313  	}
   314  
   315  	t.Width = w
   316  	if t.Align == 0 {
   317  		if w > 8 || w&(w-1) != 0 {
   318  			Fatal("invalid alignment for %v", Tconv(t, 0))
   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  /*
   333   * when a type's width should be known, we call checkwidth
   334   * to compute it.  during a declaration like
   335   *
   336   *	type T *struct { next T }
   337   *
   338   * it is necessary to defer the calculation of the struct width
   339   * until after T has been initialized to be a pointer to that struct.
   340   * similarly, during import processing structs may be used
   341   * before their definition.  in those situations, calling
   342   * defercheckwidth() stops width calculations until
   343   * resumecheckwidth() is called, at which point all the
   344   * checkwidths that were deferred are executed.
   345   * dowidth should only be called when the type's size
   346   * is needed immediately.  checkwidth makes sure the
   347   * size is evaluated eventually.
   348   */
   349  type TypeList struct {
   350  	t    *Type
   351  	next *TypeList
   352  }
   353  
   354  var tlfree *TypeList
   355  
   356  var tlq *TypeList
   357  
   358  func checkwidth(t *Type) {
   359  	if t == nil {
   360  		return
   361  	}
   362  
   363  	// function arg structs should not be checked
   364  	// outside of the enclosing function.
   365  	if t.Funarg != 0 {
   366  		Fatal("checkwidth %v", Tconv(t, 0))
   367  	}
   368  
   369  	if defercalc == 0 {
   370  		dowidth(t)
   371  		return
   372  	}
   373  
   374  	if t.Deferwidth != 0 {
   375  		return
   376  	}
   377  	t.Deferwidth = 1
   378  
   379  	l := tlfree
   380  	if l != nil {
   381  		tlfree = l.next
   382  	} else {
   383  		l = new(TypeList)
   384  	}
   385  
   386  	l.t = t
   387  	l.next = tlq
   388  	tlq = l
   389  }
   390  
   391  func defercheckwidth() {
   392  	// we get out of sync on syntax errors, so don't be pedantic.
   393  	if defercalc != 0 && nerrors == 0 {
   394  		Fatal("defercheckwidth")
   395  	}
   396  	defercalc = 1
   397  }
   398  
   399  func resumecheckwidth() {
   400  	if defercalc == 0 {
   401  		Fatal("resumecheckwidth")
   402  	}
   403  	for l := tlq; l != nil; l = tlq {
   404  		l.t.Deferwidth = 0
   405  		tlq = l.next
   406  		dowidth(l.t)
   407  		l.next = tlfree
   408  		tlfree = l
   409  	}
   410  
   411  	defercalc = 0
   412  }
   413  
   414  func typeinit() {
   415  	if Widthptr == 0 {
   416  		Fatal("typeinit before betypeinit")
   417  	}
   418  
   419  	for i := 0; i < NTYPE; i++ {
   420  		Simtype[i] = uint8(i)
   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  
   434  	dowidth(Types[TUNSAFEPTR])
   435  
   436  	Tptr = TPTR32
   437  	if Widthptr == 8 {
   438  		Tptr = TPTR64
   439  	}
   440  
   441  	for i := TINT8; i <= TUINT64; i++ {
   442  		Isint[i] = true
   443  	}
   444  	Isint[TINT] = true
   445  	Isint[TUINT] = true
   446  	Isint[TUINTPTR] = true
   447  
   448  	Isfloat[TFLOAT32] = true
   449  	Isfloat[TFLOAT64] = true
   450  
   451  	Iscomplex[TCOMPLEX64] = true
   452  	Iscomplex[TCOMPLEX128] = true
   453  
   454  	Isptr[TPTR32] = true
   455  	Isptr[TPTR64] = true
   456  
   457  	isforw[TFORW] = true
   458  
   459  	Issigned[TINT] = true
   460  	Issigned[TINT8] = true
   461  	Issigned[TINT16] = true
   462  	Issigned[TINT32] = true
   463  	Issigned[TINT64] = true
   464  
   465  	/*
   466  	 * initialize okfor
   467  	 */
   468  	for i := 0; i < NTYPE; i++ {
   469  		if Isint[i] || i == TIDEAL {
   470  			okforeq[i] = true
   471  			okforcmp[i] = true
   472  			okforarith[i] = true
   473  			okforadd[i] = true
   474  			okforand[i] = true
   475  			okforconst[i] = true
   476  			issimple[i] = true
   477  			Minintval[i] = new(Mpint)
   478  			Maxintval[i] = new(Mpint)
   479  		}
   480  
   481  		if Isfloat[i] {
   482  			okforeq[i] = true
   483  			okforcmp[i] = true
   484  			okforadd[i] = true
   485  			okforarith[i] = true
   486  			okforconst[i] = true
   487  			issimple[i] = true
   488  			minfltval[i] = newMpflt()
   489  			maxfltval[i] = newMpflt()
   490  		}
   491  
   492  		if Iscomplex[i] {
   493  			okforeq[i] = true
   494  			okforadd[i] = true
   495  			okforarith[i] = true
   496  			okforconst[i] = true
   497  			issimple[i] = true
   498  		}
   499  	}
   500  
   501  	issimple[TBOOL] = true
   502  
   503  	okforadd[TSTRING] = true
   504  
   505  	okforbool[TBOOL] = true
   506  
   507  	okforcap[TARRAY] = true
   508  	okforcap[TCHAN] = true
   509  
   510  	okforconst[TBOOL] = true
   511  	okforconst[TSTRING] = true
   512  
   513  	okforlen[TARRAY] = true
   514  	okforlen[TCHAN] = true
   515  	okforlen[TMAP] = true
   516  	okforlen[TSTRING] = true
   517  
   518  	okforeq[TPTR32] = true
   519  	okforeq[TPTR64] = true
   520  	okforeq[TUNSAFEPTR] = true
   521  	okforeq[TINTER] = true
   522  	okforeq[TCHAN] = true
   523  	okforeq[TSTRING] = true
   524  	okforeq[TBOOL] = true
   525  	okforeq[TMAP] = true    // nil only; refined in typecheck
   526  	okforeq[TFUNC] = true   // nil only; refined in typecheck
   527  	okforeq[TARRAY] = true  // nil slice only; refined in typecheck
   528  	okforeq[TSTRUCT] = true // it's complicated; refined in typecheck
   529  
   530  	okforcmp[TSTRING] = true
   531  
   532  	var i int
   533  	for i = 0; i < len(okfor); i++ {
   534  		okfor[i] = okfornone[:]
   535  	}
   536  
   537  	// binary
   538  	okfor[OADD] = okforadd[:]
   539  
   540  	okfor[OAND] = okforand[:]
   541  	okfor[OANDAND] = okforbool[:]
   542  	okfor[OANDNOT] = okforand[:]
   543  	okfor[ODIV] = okforarith[:]
   544  	okfor[OEQ] = okforeq[:]
   545  	okfor[OGE] = okforcmp[:]
   546  	okfor[OGT] = okforcmp[:]
   547  	okfor[OLE] = okforcmp[:]
   548  	okfor[OLT] = okforcmp[:]
   549  	okfor[OMOD] = okforand[:]
   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] = uint8(Tptr)
   616  
   617  	Simtype[TCHAN] = uint8(Tptr)
   618  	Simtype[TFUNC] = uint8(Tptr)
   619  	Simtype[TUNSAFEPTR] = uint8(Tptr)
   620  
   621  	/* pick up the backend thearch.typedefs */
   622  	var s1 *Sym
   623  	var etype int
   624  	var sameas int
   625  	var s *Sym
   626  	for i = range Thearch.Typedefs {
   627  		s = Lookup(Thearch.Typedefs[i].Name)
   628  		s1 = Pkglookup(Thearch.Typedefs[i].Name, builtinpkg)
   629  
   630  		etype = Thearch.Typedefs[i].Etype
   631  		if etype < 0 || etype >= len(Types) {
   632  			Fatal("typeinit: %s bad etype", s.Name)
   633  		}
   634  		sameas = Thearch.Typedefs[i].Sameas
   635  		if sameas < 0 || sameas >= len(Types) {
   636  			Fatal("typeinit: %s bad sameas", s.Name)
   637  		}
   638  		Simtype[etype] = uint8(sameas)
   639  		minfltval[etype] = minfltval[sameas]
   640  		maxfltval[etype] = maxfltval[sameas]
   641  		Minintval[etype] = Minintval[sameas]
   642  		Maxintval[etype] = Maxintval[sameas]
   643  
   644  		t = Types[etype]
   645  		if t != nil {
   646  			Fatal("typeinit: %s already defined", s.Name)
   647  		}
   648  
   649  		t = typ(etype)
   650  		t.Sym = s1
   651  
   652  		dowidth(t)
   653  		Types[etype] = t
   654  		s1.Def = typenod(t)
   655  	}
   656  
   657  	Array_array = int(Rnd(0, int64(Widthptr)))
   658  	Array_nel = int(Rnd(int64(Array_array)+int64(Widthptr), int64(Widthint)))
   659  	Array_cap = int(Rnd(int64(Array_nel)+int64(Widthint), int64(Widthint)))
   660  	sizeof_Array = int(Rnd(int64(Array_cap)+int64(Widthint), int64(Widthptr)))
   661  
   662  	// string is same as slice wo the cap
   663  	sizeof_String = int(Rnd(int64(Array_nel)+int64(Widthint), int64(Widthptr)))
   664  
   665  	dowidth(Types[TSTRING])
   666  	dowidth(idealstring)
   667  }
   668  
   669  /*
   670   * compute total size of f's in/out arguments.
   671   */
   672  func Argsize(t *Type) int {
   673  	var save Iter
   674  	var x int64
   675  
   676  	w := int64(0)
   677  
   678  	fp := Structfirst(&save, Getoutarg(t))
   679  	for fp != nil {
   680  		x = fp.Width + fp.Type.Width
   681  		if x > w {
   682  			w = x
   683  		}
   684  		fp = structnext(&save)
   685  	}
   686  
   687  	fp = funcfirst(&save, t)
   688  	for fp != nil {
   689  		x = fp.Width + fp.Type.Width
   690  		if x > w {
   691  			w = x
   692  		}
   693  		fp = funcnext(&save)
   694  	}
   695  
   696  	w = (w + int64(Widthptr) - 1) &^ (int64(Widthptr) - 1)
   697  	if int64(int(w)) != w {
   698  		Fatal("argsize too big")
   699  	}
   700  	return int(w)
   701  }