From 21b89ef327b549dbe133424a571966b77e7ef5be Mon Sep 17 00:00:00 2001 From: Ayke van Laethem Date: Sat, 1 Jan 2022 19:56:40 +0100 Subject: [PATCH] compiler: fix emission of large object layouts Large object layouts don't fit in a pointer-sized integer and therefore need to be stored in a global instead. However, the way the data was stored in these globals was not correct for buffers that don't have pointers near the end. This commit fixes this issue by using math/big FillBytes() instead of Bytes(). This gets the unicode package to compile on AVR. --- compiler/llvm.go | 2 +- compiler/testdata/gc.go | 8 ++++++++ compiler/testdata/gc.ll | 4 ++++ 3 files changed, 13 insertions(+), 1 deletion(-) diff --git a/compiler/llvm.go b/compiler/llvm.go index 9b5d40fc..81bd0b1f 100644 --- a/compiler/llvm.go +++ b/compiler/llvm.go @@ -147,7 +147,7 @@ func (c *compilerContext) createObjectLayout(t llvm.Type, pos token.Pos) llvm.Va // Create the global initializer. bitmapBytes := make([]byte, int(objectSizeWords+7)/8) - copy(bitmapBytes, bitmap.Bytes()) + bitmap.FillBytes(bitmapBytes) var bitmapByteValues []llvm.Value for _, b := range bitmapBytes { bitmapByteValues = append(bitmapByteValues, llvm.ConstInt(c.ctx.Int8Type(), uint64(b), false)) diff --git a/compiler/testdata/gc.go b/compiler/testdata/gc.go index 74e0358a..ecff9f88 100644 --- a/compiler/testdata/gc.go +++ b/compiler/testdata/gc.go @@ -20,6 +20,10 @@ var ( y [60]uintptr z *byte } + struct4 *struct { + x *byte + y [61]uintptr + } slice1 []byte slice2 []*int @@ -50,6 +54,10 @@ func newStruct() { y [60]uintptr z *byte }) + struct4 = new(struct { + x *byte + y [61]uintptr + }) } func newFuncValue() *func() { diff --git a/compiler/testdata/gc.ll b/compiler/testdata/gc.ll index 375763f3..ec66e7c7 100644 --- a/compiler/testdata/gc.ll +++ b/compiler/testdata/gc.ll @@ -17,10 +17,12 @@ target triple = "wasm32-unknown-wasi" @main.struct1 = hidden global {}* null, align 4 @main.struct2 = hidden global { i32, i32 }* null, align 4 @main.struct3 = hidden global { i8*, [60 x i32], i8* }* null, align 4 +@main.struct4 = hidden global { i8*, [61 x i32] }* null, align 4 @main.slice1 = hidden global { i8*, i32, i32 } zeroinitializer, align 8 @main.slice2 = hidden global { i32**, i32, i32 } zeroinitializer, align 8 @main.slice3 = hidden global { { i8*, i32, i32 }*, i32, i32 } zeroinitializer, align 8 @"runtime/gc.layout:62-2000000000000001" = linkonce_odr unnamed_addr constant { i32, [8 x i8] } { i32 62, [8 x i8] c" \00\00\00\00\00\00\01" } +@"runtime/gc.layout:62-0001" = linkonce_odr unnamed_addr constant { i32, [8 x i8] } { i32 62, [8 x i8] c"\00\00\00\00\00\00\00\01" } @"reflect/types.type:basic:complex128" = linkonce_odr constant %runtime.typecodeID { %runtime.typecodeID* null, i32 0, %runtime.interfaceMethodInfo* null, %runtime.typecodeID* @"reflect/types.type:pointer:basic:complex128", i32 0 } @"reflect/types.type:pointer:basic:complex128" = linkonce_odr constant %runtime.typecodeID { %runtime.typecodeID* @"reflect/types.type:basic:complex128", i32 0, %runtime.interfaceMethodInfo* null, %runtime.typecodeID* null, i32 0 } @@ -67,6 +69,8 @@ entry: store i8* %new1, i8** bitcast ({ i32, i32 }** @main.struct2 to i8**), align 4 %new2 = call i8* @runtime.alloc(i32 248, i8* bitcast ({ i32, [8 x i8] }* @"runtime/gc.layout:62-2000000000000001" to i8*), i8* undef, i8* null) #0 store i8* %new2, i8** bitcast ({ i8*, [60 x i32], i8* }** @main.struct3 to i8**), align 4 + %new3 = call i8* @runtime.alloc(i32 248, i8* bitcast ({ i32, [8 x i8] }* @"runtime/gc.layout:62-0001" to i8*), i8* undef, i8* null) #0 + store i8* %new3, i8** bitcast ({ i8*, [61 x i32] }** @main.struct4 to i8**), align 4 ret void }