runtime: require explicit GC layouts

This commit is contained in:
Jake Bailey
2026-08-07 10:21:19 -07:00
committed by Ron Evans
parent 1a4cb2032e
commit a7360d5ad3
28 changed files with 279 additions and 108 deletions
+4 -8
View File
@@ -1278,13 +1278,14 @@ func (r *runner) readObjectLayout(layoutValue value) (uint64, *big.Int) {
// integer value, or can be nil.
ptr, err := layoutValue.asPointer(r)
if err == errIntegerAsPointer {
// It's an integer, which means it's a small object or unknown.
// It's an integer, which means it's a small object.
layout := layoutValue.Uint(r)
if layout == 0 {
// Nil pointer, which means the layout is unknown.
return 0, nil
panic("runtime.alloc called without a GC layout")
}
if layout%2 != 1 {
// Conservative layouts are reserved for stack storage and cannot
// reach interpreted heap allocations.
// Sanity check: the least significant bit must be set. This is how
// the runtime can separate pointers from integers.
panic("unexpected layout")
@@ -1331,11 +1332,6 @@ func (r *runner) readObjectLayout(layoutValue value) (uint64, *big.Int) {
// have some additional repetition, for example in the buffer of a slice.
func (r *runner) getLLVMTypeFromLayout(layoutValue value) llvm.Type {
objectSizeWords, bitmap := r.readObjectLayout(layoutValue)
if bitmap == nil {
// No information available.
return llvm.Type{}
}
if bitmap.BitLen() == 0 {
// There are no pointers in this object, so treat this as a raw byte
// buffer. This is important because objects without pointers may have
+5
View File
@@ -11,6 +11,7 @@ target triple = "wasm32--wasi"
@layout3 = global ptr null
@layout4 = global ptr null
@bigobj1 = global ptr null
@pointerFree10 = global ptr null
declare ptr @runtime.alloc(i32, ptr) unnamed_addr
@@ -49,5 +50,9 @@ define internal void @main.init() unnamed_addr {
; Large object that needs to be stored in a separate global.
%bigobj1 = call ptr @runtime.alloc(i32 248, ptr @"runtime/gc.layout:62-2000000000000001")
store ptr %bigobj1, ptr @bigobj1
; Another pointer-free object.
%pointerFree10 = call ptr @runtime.alloc(i32 10, ptr inttoptr (i32 3 to ptr))
store ptr %pointerFree10, ptr @pointerFree10
ret void
}
+2
View File
@@ -10,6 +10,7 @@ target triple = "wasm32--wasi"
@layout3 = local_unnamed_addr global ptr @"main$alloc.6"
@layout4 = local_unnamed_addr global ptr @"main$alloc.7"
@bigobj1 = local_unnamed_addr global ptr @"main$alloc.8"
@pointerFree10 = local_unnamed_addr global ptr @"main$alloc.9"
@"main$alloc" = internal global [12 x i8] zeroinitializer, align 4
@"main$alloc.1" = internal global [7 x i8] zeroinitializer, align 4
@"main$alloc.2" = internal global [3 x i8] zeroinitializer, align 4
@@ -19,6 +20,7 @@ target triple = "wasm32--wasi"
@"main$alloc.6" = internal global { ptr, ptr, ptr, i32, i32, ptr, ptr, i32, i32, i32, i32, i32, i32, ptr, ptr, i32, i32, i32, ptr, ptr, i32, i32, ptr, i32, i32, ptr } zeroinitializer, align 4
@"main$alloc.7" = internal global [3 x { ptr, ptr, ptr, i32, i32, ptr, ptr, i32, i32, i32, i32, i32, i32, ptr, ptr, i32, i32, i32, ptr, ptr, i32, i32, ptr, i32, i32, ptr }] zeroinitializer, align 4
@"main$alloc.8" = internal global { ptr, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, ptr } zeroinitializer, align 4
@"main$alloc.9" = internal global [10 x i8] zeroinitializer, align 4
define void @runtime.initAll() unnamed_addr {
ret void