Commit 93831d25 authored by Rob Pike's avatar Rob Pike

rename variables for clarity.

add test for structure alignment/offset.

R=gri
DELTA=49  (35 added, 0 deleted, 14 changed)
OCL=28068
CL=28068
parent 625866a9
...@@ -6,7 +6,8 @@ package reflect ...@@ -6,7 +6,8 @@ package reflect
import ( import (
"reflect"; "reflect";
"testing" "testing";
"unsafe";
) )
var doprint bool = false var doprint bool = false
...@@ -472,3 +473,37 @@ func TestDeepEqualComplexStructInequality(t *testing.T) { ...@@ -472,3 +473,37 @@ func TestDeepEqualComplexStructInequality(t *testing.T) {
t.Error("DeepEqual(complex different) = true, want false"); t.Error("DeepEqual(complex different) = true, want false");
} }
} }
func check2ndField(x interface{}, offs uintptr, t *testing.T) {
s := reflect.NewValue(x).(reflect.StructValue);
name, ftype, tag, reflect_offset := s.Type().(reflect.StructType).Field(1);
if uintptr(reflect_offset) != offs {
t.Error("mismatched offsets in structure alignment:", reflect_offset, offs);
}
}
// Check that structure alignment & offsets viewed through reflect agree with those
// from the compiler itself.
func TestAlignment(t *testing.T) {
type T1inner struct {
a int
}
type T1 struct {
T1inner;
f int;
}
type T2inner struct {
a, b int
}
type T2 struct {
T2inner;
f int;
}
x := T1{T1inner{2}, 17};
check2ndField(x, uintptr(unsafe.Pointer(&x.f)) - uintptr(unsafe.Pointer(&x)), t);
x1 := T2{T2inner{2, 3}, 17};
check2ndField(x1, uintptr(unsafe.Pointer(&x1.f)) - uintptr(unsafe.Pointer(&x1)), t);
}
...@@ -86,7 +86,7 @@ var ( ...@@ -86,7 +86,7 @@ var (
) )
const ( const (
minStructAlign = unsafe.Sizeof(minStruct) - 1; minStructAlignMask = unsafe.Sizeof(minStruct) - 1;
ptrsize = unsafe.Sizeof(&x); ptrsize = unsafe.Sizeof(&x);
interfacesize = unsafe.Sizeof(x.xinterface); interfacesize = unsafe.Sizeof(x.xinterface);
) )
...@@ -383,31 +383,31 @@ func (t *structTypeStruct) Size() int { ...@@ -383,31 +383,31 @@ func (t *structTypeStruct) Size() int {
return t.size return t.size
} }
size := 0; size := 0;
structalign := 0; structAlignMask := 0;
for i := 0; i < len(t.field); i++ { for i := 0; i < len(t.field); i++ {
typ := t.field[i].typ.Get(); typ := t.field[i].typ.Get();
elemsize := typ.Size(); elemsize := typ.Size();
align := typ.FieldAlign() - 1; alignMask := typ.FieldAlign() - 1;
if align > structalign { if alignMask > structAlignMask {
structalign = align structAlignMask = alignMask
} }
if align > 0 { if alignMask > 0 {
size = (size + align) &^ align; size = (size + alignMask) &^ alignMask;
} }
t.field[i].offset = size; t.field[i].offset = size;
size += elemsize; size += elemsize;
} }
if (structalign > 0) { if (structAlignMask > 0) {
// 6g etc. always aligns structs to a minimum size, typically int64 // 6g etc. always aligns structs to a minimum size, typically int64
if structalign < minStructAlign { if structAlignMask < minStructAlignMask {
structalign = minStructAlign structAlignMask = minStructAlignMask
} }
// TODO: In the PPC64 ELF ABI, floating point fields // TODO: In the PPC64 ELF ABI, floating point fields
// in a struct are aligned to a 4-byte boundary, but // in a struct are aligned to a 4-byte boundary, but
// if the first field in the struct is a 64-bit float, // if the first field in the struct is a 64-bit float,
// the whole struct is aligned to an 8-byte boundary. // the whole struct is aligned to an 8-byte boundary.
size = (size + structalign) &^ structalign; size = (size + structAlignMask) &^ structAlignMask;
t.fieldAlign = structalign + 1; t.fieldAlign = structAlignMask + 1;
} }
t.size = size; t.size = size;
return size; return size;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment