From 3b7c9e24f5b1c9114fa52e684e31c9f0985c6876 Mon Sep 17 00:00:00 2001 From: Jake Bailey <5341706+jakebailey@users.noreply.github.com> Date: Tue, 14 Jul 2026 07:07:24 -0700 Subject: [PATCH] compiler: add large aggregate IR tests Add compiler coverage for large aggregate parameters and results, including function values, interfaces, maps, channels, selects, deferred calls, goroutines, phis, and multiple results. --- compiler/compiler_test.go | 1 + compiler/testdata/large.go | 120 ++++++++++ compiler/testdata/large.ll | 445 +++++++++++++++++++++++++++++++++++++ 3 files changed, 566 insertions(+) create mode 100644 compiler/testdata/large.go create mode 100644 compiler/testdata/large.ll diff --git a/compiler/compiler_test.go b/compiler/compiler_test.go index a11d4f11d..0219544c7 100644 --- a/compiler/compiler_test.go +++ b/compiler/compiler_test.go @@ -52,6 +52,7 @@ func TestCompiler(t *testing.T) { {"gc.go", "", ""}, {"zeromap.go", "", ""}, {"generics.go", "", ""}, + {"large.go", "", ""}, } if goMinor >= 20 { tests = append(tests, testCase{"go1.20.go", "", ""}) diff --git a/compiler/testdata/large.go b/compiler/testdata/large.go new file mode 100644 index 000000000..5fc9cae84 --- /dev/null +++ b/compiler/testdata/large.go @@ -0,0 +1,120 @@ +package main + +type largeValue [1025]byte + +type largeStruct struct { + value [1025]byte + ptr *byte +} + +type largeInterface interface { + makeLargeValue() largeValue + readLargeValue(largeValue) byte +} + +type largeReceiver largeValue + +func makeLargeValue(value byte) largeValue { + var result largeValue + result[len(result)-1] = value + return result +} + +func makeZeroLargeValue() largeValue { + return largeValue{} +} + +func passZeroLargeValue() byte { + return readLargeValue(largeValue{}) +} + +func readLargeValue(value largeValue) byte { + return value[len(value)-1] +} + +func useLargeValue() byte { + return readLargeValue(makeLargeValue(42)) +} + +func useLargeFunctionValue(fn func(largeValue) byte) byte { + return fn(makeLargeValue(42)) +} + +func (receiver largeReceiver) makeLargeValue() largeValue { + return largeValue(receiver) +} + +func (receiver largeReceiver) readLargeValue(value largeValue) byte { + return value[len(value)-1] +} + +func useLargeInterface(value largeInterface) byte { + return value.readLargeValue(value.makeLargeValue()) +} + +func deferLargeValue(value largeValue) { + defer readLargeValue(value) +} + +func goLargeValue(value largeValue) { + go readLargeValue(value) +} + +func makeLargeResults(value byte) (largeValue, byte) { + return makeLargeValue(value), value +} + +func makeTwoLargeResults(value byte) (largeValue, largeValue) { + return makeLargeValue(value), makeLargeValue(value + 1) +} + +func makeMixedLargeResults(value byte) (largeValue, byte, largeValue) { + return makeLargeValue(value), value + 1, makeLargeValue(value + 2) +} + +func chooseLargeValue(flag bool) largeValue { + value := makeLargeValue(1) + if flag { + value = makeLargeValue(42) + } + return value +} + +func makePointerLargeValue(value *byte) largeStruct { + return largeStruct{ptr: value} +} + +func assertLargeValue(value any) byte { + large, ok := value.(largeValue) + if !ok { + return 0 + } + return large[len(large)-1] +} + +func useLargeMap(key, value largeValue) byte { + values := map[largeValue]largeValue{key: value} + result, ok := values[key] + if !ok { + return 0 + } + return result[len(result)-1] +} + +func useLargeChannel(ch chan largeValue, value largeValue) byte { + ch <- value + result, ok := <-ch + if !ok { + return 0 + } + return result[len(result)-1] +} + +func selectLargeChannel(ch chan largeValue, value largeValue) byte { + select { + case ch <- value: + return 0 + case result := <-ch: + return result[len(result)-1] + } +} diff --git a/compiler/testdata/large.ll b/compiler/testdata/large.ll new file mode 100644 index 000000000..715c3e9a6 --- /dev/null +++ b/compiler/testdata/large.ll @@ -0,0 +1,445 @@ +; ModuleID = 'large.go' +source_filename = "large.go" +target datalayout = "e-m:e-p:32:32-p10:8:8-p20:8:8-i64:64-i128:128-n32:64-S128-ni:1:10:20" +target triple = "wasm32-unknown-wasi" + +%runtime._string = type { ptr, i32 } +%main.largeStruct = type { [1025 x i8], ptr } +%runtime.channelOp = type { ptr, ptr, i32, ptr } +%runtime.chanSelectState = type { ptr, ptr } + +@"runtime/gc.layout:258-000000000000000000000000000000000000000000000000000000000000000002" = linkonce_odr unnamed_addr constant { i32, [33 x i8] } { i32 258, [33 x i8] c"\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\02" } +@"reflect/types.typeid:named:main.largeValue" = external constant i8 +@"main$string" = internal unnamed_addr constant [31 x i8] c"blocking select matched no case", align 1 +@"main$pack" = internal unnamed_addr constant { %runtime._string } { %runtime._string { ptr @"main$string", i32 31 } } +@"reflect/types.type:basic:string" = linkonce_odr constant { i8, ptr } { i8 81, ptr @"reflect/types.type:pointer:basic:string" }, align 4 +@"reflect/types.type:pointer:basic:string" = linkonce_odr constant { i8, i16, ptr } { i8 -43, i16 0, ptr @"reflect/types.type:basic:string" }, align 4 + +declare void @runtime.trackPointer(ptr readonly captures(none), ptr, ptr) #0 + +; Function Attrs: nounwind +define hidden void @main.init(ptr %context) unnamed_addr #1 { +entry: + ret void +} + +; Function Attrs: nounwind +define hidden [1025 x i8] @"(main.largeReceiver).makeLargeValue"([1025 x i8] %receiver, ptr %context) unnamed_addr #1 { +entry: + ret [1025 x i8] %receiver +} + +; Function Attrs: nounwind +define hidden i8 @"(main.largeReceiver).readLargeValue"([1025 x i8] %receiver, [1025 x i8] %value, ptr %context) unnamed_addr #1 { +entry: + %stackalloc = alloca i8, align 1 + %value1 = call align 1 dereferenceable(1025) ptr @runtime.alloc(i32 1025, ptr nonnull inttoptr (i32 3 to ptr), ptr undef) #7 + call void @runtime.trackPointer(ptr nonnull %value1, ptr nonnull %stackalloc, ptr undef) #7 + store [1025 x i8] %value, ptr %value1, align 1 + %0 = getelementptr inbounds nuw i8, ptr %value1, i32 1024 + %1 = load i8, ptr %0, align 1 + ret i8 %1 +} + +; Function Attrs: allockind("alloc,zeroed") allocsize(0) +declare noalias nonnull ptr @runtime.alloc(i32, ptr, ptr) #2 + +; Function Attrs: nounwind +define hidden [1025 x i8] @main.makeLargeValue(i8 %value, ptr %context) unnamed_addr #1 { +entry: + %stackalloc = alloca i8, align 1 + %result = call align 1 dereferenceable(1025) ptr @runtime.alloc(i32 1025, ptr nonnull inttoptr (i32 3 to ptr), ptr undef) #7 + call void @runtime.trackPointer(ptr nonnull %result, ptr nonnull %stackalloc, ptr undef) #7 + %0 = getelementptr inbounds nuw i8, ptr %result, i32 1024 + store i8 %value, ptr %0, align 1 + %1 = load [1025 x i8], ptr %result, align 1 + ret [1025 x i8] %1 +} + +; Function Attrs: nounwind +define hidden [1025 x i8] @main.makeZeroLargeValue(ptr %context) unnamed_addr #1 { +entry: + ret [1025 x i8] zeroinitializer +} + +; Function Attrs: nounwind +define hidden i8 @main.passZeroLargeValue(ptr %context) unnamed_addr #1 { +entry: + %0 = call i8 @main.readLargeValue([1025 x i8] zeroinitializer, ptr undef) + ret i8 %0 +} + +; Function Attrs: nounwind +define hidden i8 @main.readLargeValue([1025 x i8] %value, ptr %context) unnamed_addr #1 { +entry: + %stackalloc = alloca i8, align 1 + %value1 = call align 1 dereferenceable(1025) ptr @runtime.alloc(i32 1025, ptr nonnull inttoptr (i32 3 to ptr), ptr undef) #7 + call void @runtime.trackPointer(ptr nonnull %value1, ptr nonnull %stackalloc, ptr undef) #7 + store [1025 x i8] %value, ptr %value1, align 1 + %0 = getelementptr inbounds nuw i8, ptr %value1, i32 1024 + %1 = load i8, ptr %0, align 1 + ret i8 %1 +} + +; Function Attrs: nounwind +define hidden i8 @main.useLargeValue(ptr %context) unnamed_addr #1 { +entry: + %0 = call [1025 x i8] @main.makeLargeValue(i8 42, ptr undef) + %1 = call i8 @main.readLargeValue([1025 x i8] %0, ptr undef) + ret i8 %1 +} + +; Function Attrs: nounwind +define hidden i8 @main.useLargeFunctionValue(ptr %fn.context, ptr %fn.funcptr, ptr %context) unnamed_addr #1 { +entry: + %0 = call [1025 x i8] @main.makeLargeValue(i8 42, ptr undef) + %1 = icmp eq ptr %fn.funcptr, null + br i1 %1, label %fpcall.throw, label %fpcall.next + +fpcall.next: ; preds = %entry + %2 = call i8 %fn.funcptr([1025 x i8] %0, ptr %fn.context) #7 + ret i8 %2 + +fpcall.throw: ; preds = %entry + call void @runtime.nilPanic(ptr undef) #7 + unreachable +} + +declare void @runtime.nilPanic(ptr) #0 + +; Function Attrs: nounwind +define hidden i8 @main.useLargeInterface(ptr %value.typecode, ptr %value.value, ptr %context) unnamed_addr #1 { +entry: + %0 = call [1025 x i8] @"interface:{main.makeLargeValue:func:{}{named:main.largeValue},main.readLargeValue:func:{named:main.largeValue}{basic:uint8}}.makeLargeValue$invoke"(ptr %value.value, ptr %value.typecode, ptr undef) #7 + %1 = call i8 @"interface:{main.makeLargeValue:func:{}{named:main.largeValue},main.readLargeValue:func:{named:main.largeValue}{basic:uint8}}.readLargeValue$invoke"(ptr %value.value, [1025 x i8] %0, ptr %value.typecode, ptr undef) #7 + ret i8 %1 +} + +declare [1025 x i8] @"interface:{main.makeLargeValue:func:{}{named:main.largeValue},main.readLargeValue:func:{named:main.largeValue}{basic:uint8}}.makeLargeValue$invoke"(ptr, ptr, ptr) #3 + +declare i8 @"interface:{main.makeLargeValue:func:{}{named:main.largeValue},main.readLargeValue:func:{named:main.largeValue}{basic:uint8}}.readLargeValue$invoke"(ptr, [1025 x i8], ptr, ptr) #4 + +; Function Attrs: nounwind +define hidden void @main.deferLargeValue([1025 x i8] %value, ptr %context) unnamed_addr #1 { +entry: + %defer.alloca = alloca { i32, ptr, [1025 x i8] }, align 8 + %deferPtr = alloca ptr, align 4 + store ptr null, ptr %deferPtr, align 4 + %stackalloc = alloca i8, align 1 + %0 = insertvalue { i32, ptr, [1025 x i8] } zeroinitializer, [1025 x i8] %value, 2 + call void @runtime.trackPointer(ptr nonnull %defer.alloca, ptr nonnull %stackalloc, ptr undef) #7 + store { i32, ptr, [1025 x i8] } %0, ptr %defer.alloca, align 4 + store ptr %defer.alloca, ptr %deferPtr, align 4 + br label %rundefers.block + +rundefers.after: ; preds = %rundefers.end + ret void + +rundefers.block: ; preds = %entry + br label %rundefers.loophead + +rundefers.loophead: ; preds = %rundefers.callback0, %rundefers.block + %1 = load ptr, ptr %deferPtr, align 4 + %stackIsNil = icmp eq ptr %1, null + br i1 %stackIsNil, label %rundefers.end, label %rundefers.loop + +rundefers.loop: ; preds = %rundefers.loophead + %stack.next.gep = getelementptr inbounds nuw i8, ptr %1, i32 4 + %stack.next = load ptr, ptr %stack.next.gep, align 4 + store ptr %stack.next, ptr %deferPtr, align 4 + %callback = load i32, ptr %1, align 4 + switch i32 %callback, label %rundefers.default [ + i32 0, label %rundefers.callback0 + ] + +rundefers.callback0: ; preds = %rundefers.loop + %gep = getelementptr inbounds nuw i8, ptr %1, i32 8 + %param = load [1025 x i8], ptr %gep, align 1 + %2 = call i8 @main.readLargeValue([1025 x i8] %param, ptr undef) + br label %rundefers.loophead + +rundefers.default: ; preds = %rundefers.loop + unreachable + +rundefers.end: ; preds = %rundefers.loophead + br label %rundefers.after + +recover: ; No predecessors! + ret void +} + +; Function Attrs: nounwind +define hidden void @main.goLargeValue([1025 x i8] %value, ptr %context) unnamed_addr #1 { +entry: + %stackalloc = alloca i8, align 1 + %0 = call align 1 dereferenceable(1025) ptr @runtime.alloc(i32 1025, ptr nonnull inttoptr (i32 3 to ptr), ptr undef) #7 + call void @runtime.trackPointer(ptr nonnull %0, ptr nonnull %stackalloc, ptr undef) #7 + store [1025 x i8] %value, ptr %0, align 1 + call void @"internal/task.start"(i32 ptrtoint (ptr @"main.readLargeValue$gowrapper" to i32), ptr nonnull %0, i32 65536, ptr undef) #7 + ret void +} + +declare void @runtime.deadlock(ptr) #0 + +; Function Attrs: nounwind +define linkonce_odr void @"main.readLargeValue$gowrapper"(ptr %0) unnamed_addr #5 { +entry: + %1 = load [1025 x i8], ptr %0, align 1 + %2 = call i8 @main.readLargeValue([1025 x i8] %1, ptr undef) + call void @runtime.deadlock(ptr undef) #7 + unreachable +} + +declare void @"internal/task.start"(i32, ptr, i32, ptr) #0 + +; Function Attrs: nounwind +define hidden { [1025 x i8], i8 } @main.makeLargeResults(i8 %value, ptr %context) unnamed_addr #1 { +entry: + %0 = call [1025 x i8] @main.makeLargeValue(i8 %value, ptr undef) + %1 = insertvalue { [1025 x i8], i8 } zeroinitializer, [1025 x i8] %0, 0 + %2 = insertvalue { [1025 x i8], i8 } %1, i8 %value, 1 + ret { [1025 x i8], i8 } %2 +} + +; Function Attrs: nounwind +define hidden { [1025 x i8], [1025 x i8] } @main.makeTwoLargeResults(i8 %value, ptr %context) unnamed_addr #1 { +entry: + %0 = call [1025 x i8] @main.makeLargeValue(i8 %value, ptr undef) + %1 = add i8 %value, 1 + %2 = call [1025 x i8] @main.makeLargeValue(i8 %1, ptr undef) + %3 = insertvalue { [1025 x i8], [1025 x i8] } zeroinitializer, [1025 x i8] %0, 0 + %4 = insertvalue { [1025 x i8], [1025 x i8] } %3, [1025 x i8] %2, 1 + ret { [1025 x i8], [1025 x i8] } %4 +} + +; Function Attrs: nounwind +define hidden { [1025 x i8], i8, [1025 x i8] } @main.makeMixedLargeResults(i8 %value, ptr %context) unnamed_addr #1 { +entry: + %0 = call [1025 x i8] @main.makeLargeValue(i8 %value, ptr undef) + %1 = add i8 %value, 1 + %2 = add i8 %value, 2 + %3 = call [1025 x i8] @main.makeLargeValue(i8 %2, ptr undef) + %4 = insertvalue { [1025 x i8], i8, [1025 x i8] } zeroinitializer, [1025 x i8] %0, 0 + %5 = insertvalue { [1025 x i8], i8, [1025 x i8] } %4, i8 %1, 1 + %6 = insertvalue { [1025 x i8], i8, [1025 x i8] } %5, [1025 x i8] %3, 2 + ret { [1025 x i8], i8, [1025 x i8] } %6 +} + +; Function Attrs: nounwind +define hidden [1025 x i8] @main.chooseLargeValue(i1 %flag, ptr %context) unnamed_addr #1 { +entry: + %0 = call [1025 x i8] @main.makeLargeValue(i8 1, ptr undef) + br i1 %flag, label %if.then, label %if.done + +if.then: ; preds = %entry + %1 = call [1025 x i8] @main.makeLargeValue(i8 42, ptr undef) + br label %if.done + +if.done: ; preds = %if.then, %entry + %2 = phi [1025 x i8] [ %0, %entry ], [ %1, %if.then ] + ret [1025 x i8] %2 +} + +; Function Attrs: nounwind +define hidden %main.largeStruct @main.makePointerLargeValue(ptr dereferenceable_or_null(1) %value, ptr %context) unnamed_addr #1 { +entry: + %stackalloc = alloca i8, align 1 + %complit = call align 4 dereferenceable(1032) ptr @runtime.alloc(i32 1032, ptr nonnull @"runtime/gc.layout:258-000000000000000000000000000000000000000000000000000000000000000002", ptr undef) #7 + call void @runtime.trackPointer(ptr nonnull %complit, ptr nonnull %stackalloc, ptr undef) #7 + br i1 false, label %store.throw, label %store.next + +store.next: ; preds = %entry + %0 = getelementptr inbounds nuw i8, ptr %complit, i32 1028 + store ptr %value, ptr %0, align 4 + %1 = load %main.largeStruct, ptr %complit, align 4 + %2 = extractvalue %main.largeStruct %1, 1 + call void @runtime.trackPointer(ptr %2, ptr nonnull %stackalloc, ptr undef) #7 + ret %main.largeStruct %1 + +store.throw: ; preds = %entry + unreachable +} + +; Function Attrs: nounwind +define hidden i8 @main.assertLargeValue(ptr %value.typecode, ptr %value.value, ptr %context) unnamed_addr #1 { +entry: + %stackalloc = alloca i8, align 1 + %large = call align 1 dereferenceable(1025) ptr @runtime.alloc(i32 1025, ptr nonnull inttoptr (i32 3 to ptr), ptr undef) #7 + call void @runtime.trackPointer(ptr nonnull %large, ptr nonnull %stackalloc, ptr undef) #7 + %typecode = call i1 @runtime.typeAssert(ptr %value.typecode, ptr nonnull @"reflect/types.typeid:named:main.largeValue", ptr undef) #7 + br i1 %typecode, label %typeassert.ok, label %typeassert.next + +typeassert.next: ; preds = %typeassert.ok, %entry + %typeassert.value = phi [1025 x i8] [ zeroinitializer, %entry ], [ %0, %typeassert.ok ] + store [1025 x i8] %typeassert.value, ptr %large, align 1 + br i1 %typecode, label %if.done, label %if.then + +typeassert.ok: ; preds = %entry + %0 = load [1025 x i8], ptr %value.value, align 1 + br label %typeassert.next + +if.done: ; preds = %typeassert.next + %1 = getelementptr inbounds nuw i8, ptr %large, i32 1024 + %2 = load i8, ptr %1, align 1 + ret i8 %2 + +if.then: ; preds = %typeassert.next + ret i8 0 +} + +declare i1 @runtime.typeAssert(ptr, ptr dereferenceable_or_null(1), ptr) #0 + +; Function Attrs: nounwind +define hidden i8 @main.useLargeMap([1025 x i8] %key, [1025 x i8] %value, ptr %context) unnamed_addr #1 { +entry: + %hashmap.key2 = alloca [1025 x i8], align 1 + %hashmap.value1 = alloca [1025 x i8], align 1 + %hashmap.key = alloca [1025 x i8], align 1 + %hashmap.value = alloca [1025 x i8], align 1 + %stackalloc = alloca i8, align 1 + %0 = call ptr @runtime.hashmapMakeGeneric(i32 1025, i32 1025, i32 1, ptr null, ptr nonnull @runtime.hash32, ptr null, ptr nonnull @runtime.memequal, ptr undef) #7 + call void @runtime.trackPointer(ptr %0, ptr nonnull %stackalloc, ptr undef) #7 + call void @llvm.lifetime.start.p0(ptr nonnull %hashmap.value) + store [1025 x i8] %value, ptr %hashmap.value, align 1 + call void @llvm.lifetime.start.p0(ptr nonnull %hashmap.key) + store [1025 x i8] %key, ptr %hashmap.key, align 1 + call void @runtime.hashmapBinarySet(ptr %0, ptr nonnull %hashmap.key, ptr nonnull %hashmap.value, ptr undef) #7 + call void @llvm.lifetime.end.p0(ptr nonnull %hashmap.key) + call void @llvm.lifetime.end.p0(ptr nonnull %hashmap.value) + %result = call align 1 dereferenceable(1025) ptr @runtime.alloc(i32 1025, ptr nonnull inttoptr (i32 3 to ptr), ptr undef) #7 + call void @runtime.trackPointer(ptr nonnull %result, ptr nonnull %stackalloc, ptr undef) #7 + call void @llvm.lifetime.start.p0(ptr nonnull %hashmap.value1) + call void @llvm.lifetime.start.p0(ptr nonnull %hashmap.key2) + store [1025 x i8] %key, ptr %hashmap.key2, align 1 + %1 = call i1 @runtime.hashmapBinaryGet(ptr %0, ptr nonnull %hashmap.key2, ptr nonnull %hashmap.value1, i32 1025, ptr undef) #7 + call void @llvm.lifetime.end.p0(ptr nonnull %hashmap.key2) + %2 = load [1025 x i8], ptr %hashmap.value1, align 1 + call void @llvm.lifetime.end.p0(ptr nonnull %hashmap.value1) + store [1025 x i8] %2, ptr %result, align 1 + br i1 %1, label %if.done, label %if.then + +if.done: ; preds = %entry + %3 = getelementptr inbounds nuw i8, ptr %result, i32 1024 + %4 = load i8, ptr %3, align 1 + ret i8 %4 + +if.then: ; preds = %entry + ret i8 0 +} + +declare i32 @runtime.hash32(ptr, i32, i32, ptr) #0 + +declare i1 @runtime.memequal(ptr, ptr, i32, ptr) #0 + +declare ptr @runtime.hashmapMakeGeneric(i32, i32, i32, ptr, ptr, ptr, ptr, ptr) #0 + +; Function Attrs: nocallback nofree nosync nounwind willreturn memory(argmem: readwrite) +declare void @llvm.lifetime.start.p0(ptr captures(none)) #6 + +declare void @runtime.hashmapBinarySet(ptr dereferenceable_or_null(48), ptr, ptr, ptr) #0 + +; Function Attrs: nocallback nofree nosync nounwind willreturn memory(argmem: readwrite) +declare void @llvm.lifetime.end.p0(ptr captures(none)) #6 + +declare i1 @runtime.hashmapBinaryGet(ptr dereferenceable_or_null(48), ptr, ptr, i32, ptr) #0 + +; Function Attrs: nounwind +define hidden i8 @main.useLargeChannel(ptr dereferenceable_or_null(36) %ch, [1025 x i8] %value, ptr %context) unnamed_addr #1 { +entry: + %chan.op2 = alloca %runtime.channelOp, align 8 + %chan.value1 = alloca [1025 x i8], align 1 + %chan.op = alloca %runtime.channelOp, align 8 + %chan.value = alloca [1025 x i8], align 1 + %stackalloc = alloca i8, align 1 + call void @llvm.lifetime.start.p0(ptr nonnull %chan.value) + store [1025 x i8] %value, ptr %chan.value, align 1 + call void @llvm.lifetime.start.p0(ptr nonnull %chan.op) + call void @runtime.chanSend(ptr %ch, ptr nonnull %chan.value, ptr nonnull %chan.op, ptr undef) #7 + call void @llvm.lifetime.end.p0(ptr nonnull %chan.op) + call void @llvm.lifetime.end.p0(ptr nonnull %chan.value) + %result = call align 1 dereferenceable(1025) ptr @runtime.alloc(i32 1025, ptr nonnull inttoptr (i32 3 to ptr), ptr undef) #7 + call void @runtime.trackPointer(ptr nonnull %result, ptr nonnull %stackalloc, ptr undef) #7 + call void @llvm.lifetime.start.p0(ptr nonnull %chan.value1) + call void @llvm.lifetime.start.p0(ptr nonnull %chan.op2) + %0 = call i1 @runtime.chanRecv(ptr %ch, ptr nonnull %chan.value1, ptr nonnull %chan.op2, ptr undef) #7 + %chan.received = load [1025 x i8], ptr %chan.value1, align 1 + call void @llvm.lifetime.end.p0(ptr nonnull %chan.value1) + call void @llvm.lifetime.end.p0(ptr nonnull %chan.op2) + store [1025 x i8] %chan.received, ptr %result, align 1 + br i1 %0, label %if.done, label %if.then + +if.done: ; preds = %entry + %1 = getelementptr inbounds nuw i8, ptr %result, i32 1024 + %2 = load i8, ptr %1, align 1 + ret i8 %2 + +if.then: ; preds = %entry + ret i8 0 +} + +declare void @runtime.chanSend(ptr dereferenceable_or_null(36), ptr, ptr dereferenceable_or_null(16), ptr) #0 + +declare i1 @runtime.chanRecv(ptr dereferenceable_or_null(36), ptr, ptr dereferenceable_or_null(16), ptr) #0 + +; Function Attrs: nounwind +define hidden i8 @main.selectLargeChannel(ptr dereferenceable_or_null(36) %ch, [1025 x i8] %value, ptr %context) unnamed_addr #1 { +entry: + %select.block.alloca = alloca [2 x %runtime.channelOp], align 8 + %select.states.alloca = alloca [2 x %runtime.chanSelectState], align 8 + %select.recvbuf.alloca = alloca [1025 x i8], align 1 + %select.send.value = alloca [1025 x i8], align 1 + %stackalloc = alloca i8, align 1 + store [1025 x i8] %value, ptr %select.send.value, align 1 + call void @llvm.lifetime.start.p0(ptr nonnull %select.recvbuf.alloca) + call void @llvm.lifetime.start.p0(ptr nonnull %select.states.alloca) + store ptr %ch, ptr %select.states.alloca, align 4 + %select.states.alloca.repack3 = getelementptr inbounds nuw i8, ptr %select.states.alloca, i32 4 + store ptr %select.send.value, ptr %select.states.alloca.repack3, align 4 + %0 = getelementptr inbounds nuw i8, ptr %select.states.alloca, i32 8 + store ptr %ch, ptr %0, align 4 + %.repack5 = getelementptr inbounds nuw i8, ptr %select.states.alloca, i32 12 + store ptr null, ptr %.repack5, align 4 + call void @llvm.lifetime.start.p0(ptr nonnull %select.block.alloca) + %select.result = call { i32, i1 } @runtime.chanSelect(ptr nonnull %select.recvbuf.alloca, ptr nonnull %select.states.alloca, i32 2, i32 2, ptr nonnull %select.block.alloca, i32 2, i32 2, ptr undef) #7 + call void @llvm.lifetime.end.p0(ptr nonnull %select.block.alloca) + call void @llvm.lifetime.end.p0(ptr nonnull %select.states.alloca) + call void @runtime.trackPointer(ptr nonnull %select.recvbuf.alloca, ptr nonnull %stackalloc, ptr undef) #7 + %1 = extractvalue { i32, i1 } %select.result, 0 + %2 = icmp eq i32 %1, 0 + br i1 %2, label %select.body, label %select.next + +select.body: ; preds = %entry + ret i8 0 + +select.next: ; preds = %entry + %3 = icmp eq i32 %1, 1 + br i1 %3, label %select.body1, label %select.next2 + +select.body1: ; preds = %select.next + %result = call align 1 dereferenceable(1025) ptr @runtime.alloc(i32 1025, ptr nonnull inttoptr (i32 3 to ptr), ptr undef) #7 + call void @runtime.trackPointer(ptr nonnull %result, ptr nonnull %stackalloc, ptr undef) #7 + %select.received = load [1025 x i8], ptr %select.recvbuf.alloca, align 1 + store [1025 x i8] %select.received, ptr %result, align 1 + %4 = getelementptr inbounds nuw i8, ptr %result, i32 1024 + %5 = load i8, ptr %4, align 1 + ret i8 %5 + +select.next2: ; preds = %select.next + call void @runtime.trackPointer(ptr nonnull @"reflect/types.type:basic:string", ptr nonnull %stackalloc, ptr undef) #7 + call void @runtime.trackPointer(ptr nonnull @"main$pack", ptr nonnull %stackalloc, ptr undef) #7 + call void @runtime._panic(ptr nonnull @"reflect/types.type:basic:string", ptr nonnull @"main$pack", ptr undef) #7 + unreachable +} + +declare { i32, i1 } @runtime.chanSelect(ptr, ptr, i32, i32, ptr, i32, i32, ptr) #0 + +declare void @runtime._panic(ptr, ptr, ptr) #0 + +attributes #0 = { "target-features"="+bulk-memory,+bulk-memory-opt,+call-indirect-overlong,+mutable-globals,+nontrapping-fptoint,+sign-ext,-multivalue,-reference-types" } +attributes #1 = { nounwind "target-features"="+bulk-memory,+bulk-memory-opt,+call-indirect-overlong,+mutable-globals,+nontrapping-fptoint,+sign-ext,-multivalue,-reference-types" } +attributes #2 = { allockind("alloc,zeroed") allocsize(0) "alloc-family"="runtime.alloc" "target-features"="+bulk-memory,+bulk-memory-opt,+call-indirect-overlong,+mutable-globals,+nontrapping-fptoint,+sign-ext,-multivalue,-reference-types" } +attributes #3 = { "target-features"="+bulk-memory,+bulk-memory-opt,+call-indirect-overlong,+mutable-globals,+nontrapping-fptoint,+sign-ext,-multivalue,-reference-types" "tinygo-invoke"="main.$methods.makeLargeValue:func:{}{named:main.largeValue}" "tinygo-methods"="main.$methods.makeLargeValue:func:{}{named:main.largeValue}; main.$methods.readLargeValue:func:{named:main.largeValue}{basic:uint8}" } +attributes #4 = { "target-features"="+bulk-memory,+bulk-memory-opt,+call-indirect-overlong,+mutable-globals,+nontrapping-fptoint,+sign-ext,-multivalue,-reference-types" "tinygo-invoke"="main.$methods.readLargeValue:func:{named:main.largeValue}{basic:uint8}" "tinygo-methods"="main.$methods.makeLargeValue:func:{}{named:main.largeValue}; main.$methods.readLargeValue:func:{named:main.largeValue}{basic:uint8}" } +attributes #5 = { nounwind "target-features"="+bulk-memory,+bulk-memory-opt,+call-indirect-overlong,+mutable-globals,+nontrapping-fptoint,+sign-ext,-multivalue,-reference-types" "tinygo-gowrapper"="main.readLargeValue" } +attributes #6 = { nocallback nofree nosync nounwind willreturn memory(argmem: readwrite) } +attributes #7 = { nounwind }