diff --git a/compiler/compiler.go b/compiler/compiler.go index 75aed427..3e8f18da 100644 --- a/compiler/compiler.go +++ b/compiler/compiler.go @@ -234,10 +234,15 @@ func Sizes(machine llvm.TargetMachine) types.Sizes { panic("unknown pointer size") } + // Construct a complex128 type because that's likely the type with the + // biggest alignment on most/all ABIs. + ctx := llvm.NewContext() + defer ctx.Dispose() + complex128Type := ctx.StructType([]llvm.Type{ctx.DoubleType(), ctx.DoubleType()}, false) return &stdSizes{ IntSize: int64(intWidth / 8), PtrSize: int64(targetData.PointerSize()), - MaxAlign: int64(targetData.PrefTypeAlignment(targetData.IntPtrType())), + MaxAlign: int64(targetData.ABITypeAlignment(complex128Type)), } } diff --git a/testdata/reflect.go b/testdata/reflect.go index 7e21abdc..7cc5fa7b 100644 --- a/testdata/reflect.go +++ b/testdata/reflect.go @@ -170,6 +170,19 @@ func main() { assertSize(reflect.TypeOf(new(int)).Size() == unsafe.Sizeof(new(int)), "*int") assertSize(reflect.TypeOf(zeroFunc).Size() == unsafe.Sizeof(zeroFunc), "func()") + // Test that offset is correctly calculated. + // This doesn't just test reflect but also (indirectly) that unsafe.Alignof + // works correctly. + s := struct { + small1 byte + big1 int64 + small2 byte + big2 int64 + }{} + st := reflect.TypeOf(s) + println("offset for int64 matches:", st.Field(1).Offset-st.Field(0).Offset == uintptr(unsafe.Pointer(&s.big1))-uintptr(unsafe.Pointer(&s.small1))) + println("offset for complex128 matches:", st.Field(3).Offset-st.Field(2).Offset == uintptr(unsafe.Pointer(&s.big2))-uintptr(unsafe.Pointer(&s.small2))) + // SetBool rv := reflect.ValueOf(new(bool)).Elem() rv.SetBool(true) diff --git a/testdata/reflect.txt b/testdata/reflect.txt index 4ef44cdb..c07fc01d 100644 --- a/testdata/reflect.txt +++ b/testdata/reflect.txt @@ -401,6 +401,8 @@ float32 4 32 float64 8 64 complex64 8 64 complex128 16 128 +offset for int64 matches: true +offset for complex128 matches: true type assertion succeeded for unreferenced type struct tags