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.
This commit is contained in:
Jake Bailey
2026-07-14 07:07:24 -07:00
committed by Damian Gryski
parent bc35d087c2
commit 3b7c9e24f5
3 changed files with 566 additions and 0 deletions
+1
View File
@@ -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", "", ""})
+120
View File
@@ -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]
}
}
+445
View File
@@ -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 }