func align(x, a int64) int64 {
	y := x + a - 1
	return y - y%a
}
align returns the smallest y >= x such that y % a == 0.
package types
type Sizes interface {
	Alignof(T Type) int64
	Offsetsof(fields []*Var) []int64
	Sizeof(T Type) int64
}
type StdSizes struct {
	WordSize int64  
	MaxAlign int64  
}
func (s *StdSizes) Alignof(T Type) int64 {
	switch t := T.Underlying().(type) {
	case *Array:
		return s.Alignof(t.elem)
	case *Struct:
		max := int64(1)
		for _, f := range t.fields {
			if a := s.Alignof(f.typ); a > max {
				max = a
			}
		}
		return max
	}
	a := s.Sizeof(T)  
	if a < 1 {
		return 1
	}
	if a > s.MaxAlign {
		return s.MaxAlign
	}
	return a
}
func (s *StdSizes) Offsetsof(fields []*Var) []int64 {
	offsets := make([]int64, len(fields))
	var o int64
	for i, f := range fields {
		a := s.Alignof(f.typ)
		o = align(o, a)
		offsets[i] = o
		o += s.Sizeof(f.typ)
	}
	return offsets
}
var basicSizes = [...]byte{
	Bool:       1,
	Int8:       1,
	Int16:      2,
	Int32:      4,
	Int64:      8,
	Uint8:      1,
	Uint16:     2,
	Uint32:     4,
	Uint64:     8,
	Float32:    4,
	Float64:    8,
	Complex64:  8,
	Complex128: 16,
}
func (s *StdSizes) Sizeof(T Type) int64 {
	switch t := T.Underlying().(type) {
	case *Basic:
		assert(isTyped(T))
		k := t.kind
		if int(k) < len(basicSizes) {
			if s := basicSizes[k]; s > 0 {
				return int64(s)
			}
		}
		if k == String {
			return s.WordSize * 2
		}
	case *Array:
		n := t.len
		if n == 0 {
			return 0
		}
		a := s.Alignof(t.elem)
		z := s.Sizeof(t.elem)
		return align(z, a)*(n-1) + z
	case *Slice:
		return s.WordSize * 3
	case *Struct:
		n := t.NumFields()
		if n == 0 {
			return 0
		}
		offsets := t.offsets
		if t.offsets == nil {
			offsets = s.Offsetsof(t.fields)
			t.offsets = offsets
		}
		return offsets[n-1] + s.Sizeof(t.fields[n-1].typ)
	case *Interface:
		return s.WordSize * 2
	}
	return s.WordSize  
}
var stdSizes = StdSizes{8, 8}
func (conf *Config) alignof(T Type) int64 {
	if s := conf.Sizes; s != nil {
		if a := s.Alignof(T); a >= 1 {
			return a
		}
		panic("Config.Sizes.Alignof returned an alignment < 1")
	}
	return stdSizes.Alignof(T)
}
func (conf *Config) offsetsof(T *Struct) []int64 {
	offsets := T.offsets
	if offsets == nil && T.NumFields() > 0 {
		if s := conf.Sizes; s != nil {
			offsets = s.Offsetsof(T.fields)
			if len(offsets) != T.NumFields() {
				panic("Config.Sizes.Offsetsof returned the wrong number of offsets")
			}
			for _, o := range offsets {
				if o < 0 {
					panic("Config.Sizes.Offsetsof returned an offset < 0")
				}
			}
		} else {
			offsets = stdSizes.Offsetsof(T.fields)
		}
		T.offsets = offsets
	}
	return offsets
}
func (conf *Config) offsetof(typ Type, index []int) int64 {
	var o int64
	for _, i := range index {
		s := typ.Underlying().(*Struct)
		o += conf.offsetsof(s)[i]
		typ = s.fields[i].typ
	}
	return o
}
func (conf *Config) sizeof(T Type) int64 {
	if s := conf.Sizes; s != nil {
		if z := s.Sizeof(T); z >= 0 {
			return z
		}
		panic("Config.Sizes.Sizeof returned a size < 0")
	}
	return stdSizes.Sizeof(T)
}