mirror of
https://github.com/golang/go
synced 2024-11-26 08:27:56 -07:00
Separate the alignment of a field from the alignment of the
type of the field. Use the field alignment to compute the size of a structure. This may help 8g but is mainly for gccgo. gccgo maintains the standard C/C++ ABI for structure field alignment. For the i386, this requires that a float64 field in a struct be aligned on a 32-bit boundary, although for efficiency a variable of type float64 or []float64 should be aligned on a 64-bit boundary. I also removed the unused size field from structField. R=r DELTA=117 (75 added, 2 deleted, 40 changed) OCL=26842 CL=26936
This commit is contained in:
parent
aacdc25399
commit
4e84174816
@ -52,10 +52,38 @@ const (
|
|||||||
UintptrKind;
|
UintptrKind;
|
||||||
)
|
)
|
||||||
|
|
||||||
var tmp_interface interface{} // used just to compute sizes of these constants
|
// For sizes and alignments.
|
||||||
|
|
||||||
|
type allTypes struct {
|
||||||
|
xarray []byte;
|
||||||
|
xbool bool;
|
||||||
|
xchan chan byte;
|
||||||
|
xfloat float;
|
||||||
|
xfloat32 float32;
|
||||||
|
xfloat64 float64;
|
||||||
|
xint int;
|
||||||
|
xint16 int16;
|
||||||
|
xint32 int32;
|
||||||
|
xint64 int64;
|
||||||
|
xint8 int8;
|
||||||
|
xinterface interface {};
|
||||||
|
xmap map[byte]byte;
|
||||||
|
xptr *byte;
|
||||||
|
xslice []byte;
|
||||||
|
xstring string;
|
||||||
|
xuint uint;
|
||||||
|
xuint16 uint16;
|
||||||
|
xuint32 uint32;
|
||||||
|
xuint64 uint64;
|
||||||
|
xuint8 uint8;
|
||||||
|
xuintptr uintptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
var x allTypes
|
||||||
|
|
||||||
const (
|
const (
|
||||||
ptrsize = unsafe.Sizeof(&tmp_interface);
|
ptrsize = unsafe.Sizeof(&x);
|
||||||
interfacesize = unsafe.Sizeof(tmp_interface);
|
interfacesize = unsafe.Sizeof(x.xinterface);
|
||||||
)
|
)
|
||||||
|
|
||||||
var missingString = "$missing$" // syntactic name for undefined type names
|
var missingString = "$missing$" // syntactic name for undefined type names
|
||||||
@ -74,6 +102,8 @@ type Type interface {
|
|||||||
String() string;
|
String() string;
|
||||||
// The number of bytes needed to store a value; analogous to unsafe.Sizeof().
|
// The number of bytes needed to store a value; analogous to unsafe.Sizeof().
|
||||||
Size() int;
|
Size() int;
|
||||||
|
// The alignment of a value of this type when used as a field in a struct.
|
||||||
|
FieldAlign() int;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fields and methods common to all types
|
// Fields and methods common to all types
|
||||||
@ -109,11 +139,16 @@ func (c *commonType) Size() int {
|
|||||||
// -- Basic
|
// -- Basic
|
||||||
|
|
||||||
type basicType struct {
|
type basicType struct {
|
||||||
commonType
|
commonType;
|
||||||
|
fieldAlign int;
|
||||||
}
|
}
|
||||||
|
|
||||||
func newBasicType(name string, kind int, size int) Type {
|
func newBasicType(name string, kind int, size int, fieldAlign int) Type {
|
||||||
return &basicType{ commonType{kind, name, name, size} }
|
return &basicType{ commonType{kind, name, name, size}, fieldAlign }
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *basicType) FieldAlign() int {
|
||||||
|
return t.fieldAlign
|
||||||
}
|
}
|
||||||
|
|
||||||
// Prebuilt basic Type objects representing the predeclared basic types.
|
// Prebuilt basic Type objects representing the predeclared basic types.
|
||||||
@ -121,25 +156,24 @@ func newBasicType(name string, kind int, size int) Type {
|
|||||||
// Missing represents types whose representation cannot be discovered; usually an error.
|
// Missing represents types whose representation cannot be discovered; usually an error.
|
||||||
// DotDotDot represents the pseudo-type of a ... parameter.
|
// DotDotDot represents the pseudo-type of a ... parameter.
|
||||||
var (
|
var (
|
||||||
Missing = newBasicType(missingString, MissingKind, 1);
|
Missing = newBasicType(missingString, MissingKind, 1, 1);
|
||||||
empty interface{};
|
DotDotDot = newBasicType(dotDotDotString, DotDotDotKind, unsafe.Sizeof(x.xinterface), unsafe.Alignof(x.xinterface));
|
||||||
DotDotDot = newBasicType(dotDotDotString, DotDotDotKind, unsafe.Sizeof(empty));
|
Bool = newBasicType("bool", BoolKind, unsafe.Sizeof(x.xbool), unsafe.Alignof(x.xbool));
|
||||||
Bool = newBasicType("bool", BoolKind, unsafe.Sizeof(true));
|
Int = newBasicType("int", IntKind, unsafe.Sizeof(x.xint), unsafe.Alignof(x.xint));
|
||||||
Int = newBasicType("int", IntKind, unsafe.Sizeof(int(0)));
|
Int8 = newBasicType("int8", Int8Kind, unsafe.Sizeof(x.xint8), unsafe.Alignof(x.xint8));
|
||||||
Int8 = newBasicType("int8", Int8Kind, 1);
|
Int16 = newBasicType("int16", Int16Kind, unsafe.Sizeof(x.xint16), unsafe.Alignof(x.xint16));
|
||||||
Int16 = newBasicType("int16", Int16Kind, 2);
|
Int32 = newBasicType("int32", Int32Kind, unsafe.Sizeof(x.xint32), unsafe.Alignof(x.xint32));
|
||||||
Int32 = newBasicType("int32", Int32Kind, 4);
|
Int64 = newBasicType("int64", Int64Kind, unsafe.Sizeof(x.xint64), unsafe.Alignof(x.xint64));
|
||||||
Int64 = newBasicType("int64", Int64Kind, 8);
|
Uint = newBasicType("uint", UintKind, unsafe.Sizeof(x.xuint), unsafe.Alignof(x.xuint));
|
||||||
Uint = newBasicType("uint", UintKind, unsafe.Sizeof(uint(0)));
|
Uint8 = newBasicType("uint8", Uint8Kind, unsafe.Sizeof(x.xuint8), unsafe.Alignof(x.xuint8));
|
||||||
Uint8 = newBasicType("uint8", Uint8Kind, 1);
|
Uint16 = newBasicType("uint16", Uint16Kind, unsafe.Sizeof(x.xuint16), unsafe.Alignof(x.xuint16));
|
||||||
Uint16 = newBasicType("uint16", Uint16Kind, 2);
|
Uint32 = newBasicType("uint32", Uint32Kind, unsafe.Sizeof(x.xuint32), unsafe.Alignof(x.xuint32));
|
||||||
Uint32 = newBasicType("uint32", Uint32Kind, 4);
|
Uint64 = newBasicType("uint64", Uint64Kind, unsafe.Sizeof(x.xuint64), unsafe.Alignof(x.xuint64));
|
||||||
Uint64 = newBasicType("uint64", Uint64Kind, 8);
|
Uintptr = newBasicType("uintptr", UintptrKind, unsafe.Sizeof(x.xuintptr), unsafe.Alignof(x.xuintptr));
|
||||||
Uintptr = newBasicType("uintptr", UintptrKind, unsafe.Sizeof(uintptr(0)));
|
Float = newBasicType("float", FloatKind, unsafe.Sizeof(x.xfloat), unsafe.Alignof(x.xfloat));
|
||||||
Float = newBasicType("float", FloatKind, unsafe.Sizeof(float(0)));
|
Float32 = newBasicType("float32", Float32Kind, unsafe.Sizeof(x.xfloat32), unsafe.Alignof(x.xfloat32));
|
||||||
Float32 = newBasicType("float32", Float32Kind, 4);
|
Float64 = newBasicType("float64", Float64Kind, unsafe.Sizeof(x.xfloat64), unsafe.Alignof(x.xfloat64));
|
||||||
Float64 = newBasicType("float64", Float64Kind, 8);
|
String = newBasicType("string", StringKind, unsafe.Sizeof(x.xstring), unsafe.Alignof(x.xstring));
|
||||||
String = newBasicType("string", StringKind, unsafe.Sizeof(""));
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// Stub types allow us to defer evaluating type names until needed.
|
// Stub types allow us to defer evaluating type names until needed.
|
||||||
@ -178,6 +212,10 @@ func newPtrTypeStruct(name, typestring string, sub *stubType) *ptrTypeStruct {
|
|||||||
return &ptrTypeStruct{ commonType{PtrKind, typestring, name, ptrsize}, sub}
|
return &ptrTypeStruct{ commonType{PtrKind, typestring, name, ptrsize}, sub}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (t *ptrTypeStruct) FieldAlign() int {
|
||||||
|
return unsafe.Alignof(x.xptr);
|
||||||
|
}
|
||||||
|
|
||||||
func (t *ptrTypeStruct) Sub() Type {
|
func (t *ptrTypeStruct) Sub() Type {
|
||||||
return t.sub.Get()
|
return t.sub.Get()
|
||||||
}
|
}
|
||||||
@ -205,11 +243,18 @@ func newArrayTypeStruct(name, typestring string, open bool, len int, elem *stubT
|
|||||||
|
|
||||||
func (t *arrayTypeStruct) Size() int {
|
func (t *arrayTypeStruct) Size() int {
|
||||||
if t.isslice {
|
if t.isslice {
|
||||||
return ptrsize*2 // open arrays are 2-word headers
|
return unsafe.Sizeof(x.xslice);
|
||||||
}
|
}
|
||||||
return t.len * t.elem.Get().Size();
|
return t.len * t.elem.Get().Size();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (t *arrayTypeStruct) FieldAlign() int {
|
||||||
|
if t.isslice {
|
||||||
|
return unsafe.Alignof(x.xslice);
|
||||||
|
}
|
||||||
|
return t.elem.Get().FieldAlign();
|
||||||
|
}
|
||||||
|
|
||||||
func (t *arrayTypeStruct) IsSlice() bool {
|
func (t *arrayTypeStruct) IsSlice() bool {
|
||||||
return t.isslice
|
return t.isslice
|
||||||
}
|
}
|
||||||
@ -244,6 +289,10 @@ func newMapTypeStruct(name, typestring string, key, elem *stubType) *mapTypeStru
|
|||||||
return &mapTypeStruct{ commonType{MapKind, typestring, name, ptrsize}, key, elem}
|
return &mapTypeStruct{ commonType{MapKind, typestring, name, ptrsize}, key, elem}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (t *mapTypeStruct) FieldAlign() int {
|
||||||
|
return unsafe.Alignof(x.xmap);
|
||||||
|
}
|
||||||
|
|
||||||
func (t *mapTypeStruct) Key() Type {
|
func (t *mapTypeStruct) Key() Type {
|
||||||
return t.key.Get()
|
return t.key.Get()
|
||||||
}
|
}
|
||||||
@ -278,6 +327,10 @@ func newChanTypeStruct(name, typestring string, dir int, elem *stubType) *chanTy
|
|||||||
return &chanTypeStruct{ commonType{ChanKind, typestring, name, ptrsize}, elem, dir}
|
return &chanTypeStruct{ commonType{ChanKind, typestring, name, ptrsize}, elem, dir}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (t *chanTypeStruct) FieldAlign() int {
|
||||||
|
return unsafe.Alignof(x.xchan);
|
||||||
|
}
|
||||||
|
|
||||||
func (t *chanTypeStruct) Dir() int {
|
func (t *chanTypeStruct) Dir() int {
|
||||||
return t.dir
|
return t.dir
|
||||||
}
|
}
|
||||||
@ -302,40 +355,51 @@ type structField struct {
|
|||||||
name string;
|
name string;
|
||||||
typ *stubType;
|
typ *stubType;
|
||||||
tag string;
|
tag string;
|
||||||
size int;
|
|
||||||
offset int;
|
offset int;
|
||||||
}
|
}
|
||||||
|
|
||||||
type structTypeStruct struct {
|
type structTypeStruct struct {
|
||||||
commonType;
|
commonType;
|
||||||
field []structField;
|
field []structField;
|
||||||
|
fieldAlign int;
|
||||||
}
|
}
|
||||||
|
|
||||||
func newStructTypeStruct(name, typestring string, field []structField) *structTypeStruct {
|
func newStructTypeStruct(name, typestring string, field []structField) *structTypeStruct {
|
||||||
return &structTypeStruct{ commonType{StructKind, typestring, name, 0}, field}
|
return &structTypeStruct{ commonType{StructKind, typestring, name, 0}, field, 0}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *structTypeStruct) FieldAlign() int {
|
||||||
|
t.Size(); // Compute size and alignment.
|
||||||
|
return t.fieldAlign
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: not portable; depends on 6g
|
|
||||||
func (t *structTypeStruct) Size() int {
|
func (t *structTypeStruct) Size() int {
|
||||||
if t.size > 0 {
|
if t.size > 0 {
|
||||||
return t.size
|
return t.size
|
||||||
}
|
}
|
||||||
size := 0;
|
size := 0;
|
||||||
structalignmask := 7; // BUG: we know structs are 8-aligned
|
structalign := 0;
|
||||||
for i := 0; i < len(t.field); i++ {
|
for i := 0; i < len(t.field); i++ {
|
||||||
elemsize := t.field[i].typ.Get().Size();
|
typ := t.field[i].typ.Get();
|
||||||
// pad until at (elemsize mod 8) boundary
|
elemsize := typ.Size();
|
||||||
align := elemsize - 1;
|
align := typ.FieldAlign() - 1;
|
||||||
if align > structalignmask {
|
if align > structalign {
|
||||||
align = structalignmask
|
structalign = align
|
||||||
}
|
}
|
||||||
if align > 0 {
|
if align > 0 {
|
||||||
size = (size + align) & ^align;
|
size = (size + align) &^ align;
|
||||||
}
|
}
|
||||||
t.field[i].offset = size;
|
t.field[i].offset = size;
|
||||||
size += elemsize;
|
size += elemsize;
|
||||||
}
|
}
|
||||||
size = (size + structalignmask) & ^(structalignmask);
|
if (structalign > 0) {
|
||||||
|
// TODO: In the PPC64 ELF ABI, floating point fields
|
||||||
|
// in a struct are aligned to a 4-byte boundary, but
|
||||||
|
// if the first field in the struct is a 64-bit float,
|
||||||
|
// the whole struct is aligned to an 8-byte boundary.
|
||||||
|
size = (size + structalign) &^ structalign;
|
||||||
|
t.fieldAlign = structalign + 1;
|
||||||
|
}
|
||||||
t.size = size;
|
t.size = size;
|
||||||
return size;
|
return size;
|
||||||
}
|
}
|
||||||
@ -372,6 +436,10 @@ func newInterfaceTypeStruct(name, typestring string, field []structField) *inter
|
|||||||
return &interfaceTypeStruct{ commonType{InterfaceKind, typestring, name, interfacesize}, field }
|
return &interfaceTypeStruct{ commonType{InterfaceKind, typestring, name, interfacesize}, field }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (t *interfaceTypeStruct) FieldAlign() int {
|
||||||
|
return unsafe.Alignof(x.xinterface);
|
||||||
|
}
|
||||||
|
|
||||||
func (t *interfaceTypeStruct) Field(i int) (name string, typ Type, tag string, offset int) {
|
func (t *interfaceTypeStruct) Field(i int) (name string, typ Type, tag string, offset int) {
|
||||||
return t.field[i].name, t.field[i].typ.Get(), "", 0
|
return t.field[i].name, t.field[i].typ.Get(), "", 0
|
||||||
}
|
}
|
||||||
@ -401,6 +469,11 @@ func newFuncTypeStruct(name, typestring string, in, out *structTypeStruct) *func
|
|||||||
return &funcTypeStruct{ commonType{FuncKind, typestring, name, 0}, in, out }
|
return &funcTypeStruct{ commonType{FuncKind, typestring, name, 0}, in, out }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (t *funcTypeStruct) FieldAlign() int {
|
||||||
|
panic("reflect.type: func.FieldAlign(): cannot happen");
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
func (t *funcTypeStruct) Size() int {
|
func (t *funcTypeStruct) Size() int {
|
||||||
panic("reflect.type: func.Size(): cannot happen");
|
panic("reflect.type: func.Size(): cannot happen");
|
||||||
return 0
|
return 0
|
||||||
@ -861,7 +934,7 @@ func (p *typeParser) Type(name string) *stubType {
|
|||||||
if name != "" {
|
if name != "" {
|
||||||
// Need to make a copy because we are renaming a basic type
|
// Need to make a copy because we are renaming a basic type
|
||||||
b := s.Get();
|
b := s.Get();
|
||||||
s = newStubType(name, newBasicType(name, b.Kind(), b.Size()));
|
s = newStubType(name, newBasicType(name, b.Kind(), b.Size(), b.FieldAlign()));
|
||||||
}
|
}
|
||||||
return s
|
return s
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user