diff --git a/compiler/defer.go b/compiler/defer.go index 74910f5f..6c69bd51 100644 --- a/compiler/defer.go +++ b/compiler/defer.go @@ -71,7 +71,7 @@ func (b *builder) deferInitFunc() { // possibly broken by the C alloca function). // The frame pointer is _not_ saved, because it is marked as clobbered // in the setjmp-like inline assembly. - deferFrameType := b.getLLVMType(b.program.ImportedPackage("internal/task").Members["DeferFrame"].Type()) + deferFrameType := b.getLLVMRuntimeType("deferFrame") b.deferFrame = b.CreateAlloca(deferFrameType, "deferframe.buf") stackPointer := b.readStackPointer() b.createRuntimeCall("setupDeferFrame", []llvm.Value{b.deferFrame, stackPointer}, "") diff --git a/compiler/testdata/channel.ll b/compiler/testdata/channel.ll index 6467a400..c5682459 100644 --- a/compiler/testdata/channel.ll +++ b/compiler/testdata/channel.ll @@ -5,12 +5,10 @@ target triple = "wasm32-unknown-wasi" %runtime.channel = type { i32, i32, i8, %runtime.channelBlockedList*, i32, i32, i32, i8* } %runtime.channelBlockedList = type { %runtime.channelBlockedList*, %"internal/task.Task"*, %runtime.chanSelectState*, { %runtime.channelBlockedList*, i32, i32 } } -%"internal/task.Task" = type { %"internal/task.Task"*, i8*, i64, %"internal/task.gcData", %"internal/task.state", %"internal/task.DeferFrame"* } +%"internal/task.Task" = type { %"internal/task.Task"*, i8*, i64, %"internal/task.gcData", %"internal/task.state", i8* } %"internal/task.gcData" = type { i8* } %"internal/task.state" = type { i32, i8*, %"internal/task.stackState", i1 } %"internal/task.stackState" = type { i32, i32 } -%"internal/task.DeferFrame" = type { i8*, i8*, %"internal/task.DeferFrame"*, i1, %runtime._interface } -%runtime._interface = type { i32, i8* } %runtime.chanSelectState = type { %runtime.channel*, i8* } declare noalias nonnull i8* @runtime.alloc(i32, i8*, i8*) diff --git a/compiler/testdata/defer-cortex-m-qemu.ll b/compiler/testdata/defer-cortex-m-qemu.ll index e7c3e853..9c6ddab3 100644 --- a/compiler/testdata/defer-cortex-m-qemu.ll +++ b/compiler/testdata/defer-cortex-m-qemu.ll @@ -4,7 +4,7 @@ target datalayout = "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64" target triple = "thumbv7m-unknown-unknown-eabi" %runtime._defer = type { i32, %runtime._defer* } -%"internal/task.DeferFrame" = type { i8*, i8*, %"internal/task.DeferFrame"*, i1, %runtime._interface } +%runtime.deferFrame = type { i8*, i8*, %runtime.deferFrame*, i1, %runtime._interface } %runtime._interface = type { i32, i8* } declare noalias nonnull i8* @runtime.alloc(i32, i8*, i8*) #0 @@ -23,16 +23,16 @@ entry: %defer.alloca = alloca { i32, %runtime._defer* }, align 4 %deferPtr = alloca %runtime._defer*, align 4 store %runtime._defer* null, %runtime._defer** %deferPtr, align 4 - %deferframe.buf = alloca %"internal/task.DeferFrame", align 4 + %deferframe.buf = alloca %runtime.deferFrame, align 4 %0 = call i8* @llvm.stacksave() - call void @runtime.setupDeferFrame(%"internal/task.DeferFrame"* nonnull %deferframe.buf, i8* %0, i8* undef) #3 + call void @runtime.setupDeferFrame(%runtime.deferFrame* nonnull %deferframe.buf, i8* %0, i8* undef) #3 %defer.alloca.repack = getelementptr inbounds { i32, %runtime._defer* }, { i32, %runtime._defer* }* %defer.alloca, i32 0, i32 0 store i32 0, i32* %defer.alloca.repack, align 4 %defer.alloca.repack16 = getelementptr inbounds { i32, %runtime._defer* }, { i32, %runtime._defer* }* %defer.alloca, i32 0, i32 1 store %runtime._defer* null, %runtime._defer** %defer.alloca.repack16, align 4 %1 = bitcast %runtime._defer** %deferPtr to { i32, %runtime._defer* }** store { i32, %runtime._defer* }* %defer.alloca, { i32, %runtime._defer* }** %1, align 4 - %setjmp = call i32 asm "\0Amovs r0, #0\0Amov r2, pc\0Astr r2, [r1, #4]", "={r0},{r1},~{r1},~{r2},~{r3},~{r4},~{r5},~{r6},~{r7},~{r8},~{r9},~{r10},~{r11},~{r12},~{lr},~{q0},~{q1},~{q2},~{q3},~{q4},~{q5},~{q6},~{q7},~{q8},~{q9},~{q10},~{q11},~{q12},~{q13},~{q14},~{q15},~{cpsr},~{memory}"(%"internal/task.DeferFrame"* nonnull %deferframe.buf) #4 + %setjmp = call i32 asm "\0Amovs r0, #0\0Amov r2, pc\0Astr r2, [r1, #4]", "={r0},{r1},~{r1},~{r2},~{r3},~{r4},~{r5},~{r6},~{r7},~{r8},~{r9},~{r10},~{r11},~{r12},~{lr},~{q0},~{q1},~{q2},~{q3},~{q4},~{q5},~{q6},~{q7},~{q8},~{q9},~{q10},~{q11},~{q12},~{q13},~{q14},~{q15},~{cpsr},~{memory}"(%runtime.deferFrame* nonnull %deferframe.buf) #4 %setjmp.result = icmp eq i32 %setjmp, 0 br i1 %setjmp.result, label %2, label %lpad @@ -56,7 +56,7 @@ rundefers.loop: ; preds = %rundefers.loophead ] rundefers.callback0: ; preds = %rundefers.loop - %setjmp1 = call i32 asm "\0Amovs r0, #0\0Amov r2, pc\0Astr r2, [r1, #4]", "={r0},{r1},~{r1},~{r2},~{r3},~{r4},~{r5},~{r6},~{r7},~{r8},~{r9},~{r10},~{r11},~{r12},~{lr},~{q0},~{q1},~{q2},~{q3},~{q4},~{q5},~{q6},~{q7},~{q8},~{q9},~{q10},~{q11},~{q12},~{q13},~{q14},~{q15},~{cpsr},~{memory}"(%"internal/task.DeferFrame"* nonnull %deferframe.buf) #4 + %setjmp1 = call i32 asm "\0Amovs r0, #0\0Amov r2, pc\0Astr r2, [r1, #4]", "={r0},{r1},~{r1},~{r2},~{r3},~{r4},~{r5},~{r6},~{r7},~{r8},~{r9},~{r10},~{r11},~{r12},~{lr},~{q0},~{q1},~{q2},~{q3},~{q4},~{q5},~{q6},~{q7},~{q8},~{q9},~{q10},~{q11},~{q12},~{q13},~{q14},~{q15},~{cpsr},~{memory}"(%runtime.deferFrame* nonnull %deferframe.buf) #4 %setjmp.result2 = icmp eq i32 %setjmp1, 0 br i1 %setjmp.result2, label %4, label %lpad @@ -68,11 +68,11 @@ rundefers.default: ; preds = %rundefers.loop unreachable rundefers.end: ; preds = %rundefers.loophead - call void @runtime.destroyDeferFrame(%"internal/task.DeferFrame"* nonnull %deferframe.buf, i8* undef) #3 + call void @runtime.destroyDeferFrame(%runtime.deferFrame* nonnull %deferframe.buf, i8* undef) #3 ret void recover: ; preds = %rundefers.end3 - call void @runtime.destroyDeferFrame(%"internal/task.DeferFrame"* nonnull %deferframe.buf, i8* undef) #3 + call void @runtime.destroyDeferFrame(%runtime.deferFrame* nonnull %deferframe.buf, i8* undef) #3 ret void lpad: ; preds = %rundefers.callback012, %rundefers.callback0, %entry @@ -94,7 +94,7 @@ rundefers.loop5: ; preds = %rundefers.loophead6 ] rundefers.callback012: ; preds = %rundefers.loop5 - %setjmp14 = call i32 asm "\0Amovs r0, #0\0Amov r2, pc\0Astr r2, [r1, #4]", "={r0},{r1},~{r1},~{r2},~{r3},~{r4},~{r5},~{r6},~{r7},~{r8},~{r9},~{r10},~{r11},~{r12},~{lr},~{q0},~{q1},~{q2},~{q3},~{q4},~{q5},~{q6},~{q7},~{q8},~{q9},~{q10},~{q11},~{q12},~{q13},~{q14},~{q15},~{cpsr},~{memory}"(%"internal/task.DeferFrame"* nonnull %deferframe.buf) #4 + %setjmp14 = call i32 asm "\0Amovs r0, #0\0Amov r2, pc\0Astr r2, [r1, #4]", "={r0},{r1},~{r1},~{r2},~{r3},~{r4},~{r5},~{r6},~{r7},~{r8},~{r9},~{r10},~{r11},~{r12},~{lr},~{q0},~{q1},~{q2},~{q3},~{q4},~{q5},~{q6},~{q7},~{q8},~{q9},~{q10},~{q11},~{q12},~{q13},~{q14},~{q15},~{cpsr},~{memory}"(%runtime.deferFrame* nonnull %deferframe.buf) #4 %setjmp.result15 = icmp eq i32 %setjmp14, 0 br i1 %setjmp.result15, label %6, label %lpad @@ -112,7 +112,7 @@ rundefers.end3: ; preds = %rundefers.loophead6 ; Function Attrs: nofree nosync nounwind willreturn declare i8* @llvm.stacksave() #2 -declare void @runtime.setupDeferFrame(%"internal/task.DeferFrame"* dereferenceable_or_null(24), i8*, i8*) #0 +declare void @runtime.setupDeferFrame(%runtime.deferFrame* dereferenceable_or_null(24), i8*, i8*) #0 ; Function Attrs: nounwind define hidden void @"main.deferSimple$1"(i8* %context) unnamed_addr #1 { @@ -121,7 +121,7 @@ entry: ret void } -declare void @runtime.destroyDeferFrame(%"internal/task.DeferFrame"* dereferenceable_or_null(24), i8*) #0 +declare void @runtime.destroyDeferFrame(%runtime.deferFrame* dereferenceable_or_null(24), i8*) #0 declare void @runtime.printint32(i32, i8*) #0 @@ -132,9 +132,9 @@ entry: %defer.alloca = alloca { i32, %runtime._defer* }, align 4 %deferPtr = alloca %runtime._defer*, align 4 store %runtime._defer* null, %runtime._defer** %deferPtr, align 4 - %deferframe.buf = alloca %"internal/task.DeferFrame", align 4 + %deferframe.buf = alloca %runtime.deferFrame, align 4 %0 = call i8* @llvm.stacksave() - call void @runtime.setupDeferFrame(%"internal/task.DeferFrame"* nonnull %deferframe.buf, i8* %0, i8* undef) #3 + call void @runtime.setupDeferFrame(%runtime.deferFrame* nonnull %deferframe.buf, i8* %0, i8* undef) #3 %defer.alloca.repack = getelementptr inbounds { i32, %runtime._defer* }, { i32, %runtime._defer* }* %defer.alloca, i32 0, i32 0 store i32 0, i32* %defer.alloca.repack, align 4 %defer.alloca.repack26 = getelementptr inbounds { i32, %runtime._defer* }, { i32, %runtime._defer* }* %defer.alloca, i32 0, i32 1 @@ -148,7 +148,7 @@ entry: store { i32, %runtime._defer* }* %defer.alloca, { i32, %runtime._defer* }** %2, align 4 %3 = bitcast %runtime._defer** %deferPtr to { i32, %runtime._defer* }** store { i32, %runtime._defer* }* %defer.alloca2, { i32, %runtime._defer* }** %3, align 4 - %setjmp = call i32 asm "\0Amovs r0, #0\0Amov r2, pc\0Astr r2, [r1, #4]", "={r0},{r1},~{r1},~{r2},~{r3},~{r4},~{r5},~{r6},~{r7},~{r8},~{r9},~{r10},~{r11},~{r12},~{lr},~{q0},~{q1},~{q2},~{q3},~{q4},~{q5},~{q6},~{q7},~{q8},~{q9},~{q10},~{q11},~{q12},~{q13},~{q14},~{q15},~{cpsr},~{memory}"(%"internal/task.DeferFrame"* nonnull %deferframe.buf) #4 + %setjmp = call i32 asm "\0Amovs r0, #0\0Amov r2, pc\0Astr r2, [r1, #4]", "={r0},{r1},~{r1},~{r2},~{r3},~{r4},~{r5},~{r6},~{r7},~{r8},~{r9},~{r10},~{r11},~{r12},~{lr},~{q0},~{q1},~{q2},~{q3},~{q4},~{q5},~{q6},~{q7},~{q8},~{q9},~{q10},~{q11},~{q12},~{q13},~{q14},~{q15},~{cpsr},~{memory}"(%runtime.deferFrame* nonnull %deferframe.buf) #4 %setjmp.result = icmp eq i32 %setjmp, 0 br i1 %setjmp.result, label %4, label %lpad @@ -173,7 +173,7 @@ rundefers.loop: ; preds = %rundefers.loophead ] rundefers.callback0: ; preds = %rundefers.loop - %setjmp4 = call i32 asm "\0Amovs r0, #0\0Amov r2, pc\0Astr r2, [r1, #4]", "={r0},{r1},~{r1},~{r2},~{r3},~{r4},~{r5},~{r6},~{r7},~{r8},~{r9},~{r10},~{r11},~{r12},~{lr},~{q0},~{q1},~{q2},~{q3},~{q4},~{q5},~{q6},~{q7},~{q8},~{q9},~{q10},~{q11},~{q12},~{q13},~{q14},~{q15},~{cpsr},~{memory}"(%"internal/task.DeferFrame"* nonnull %deferframe.buf) #4 + %setjmp4 = call i32 asm "\0Amovs r0, #0\0Amov r2, pc\0Astr r2, [r1, #4]", "={r0},{r1},~{r1},~{r2},~{r3},~{r4},~{r5},~{r6},~{r7},~{r8},~{r9},~{r10},~{r11},~{r12},~{lr},~{q0},~{q1},~{q2},~{q3},~{q4},~{q5},~{q6},~{q7},~{q8},~{q9},~{q10},~{q11},~{q12},~{q13},~{q14},~{q15},~{cpsr},~{memory}"(%runtime.deferFrame* nonnull %deferframe.buf) #4 %setjmp.result5 = icmp eq i32 %setjmp4, 0 br i1 %setjmp.result5, label %6, label %lpad @@ -182,7 +182,7 @@ rundefers.callback0: ; preds = %rundefers.loop br label %rundefers.loophead rundefers.callback1: ; preds = %rundefers.loop - %setjmp7 = call i32 asm "\0Amovs r0, #0\0Amov r2, pc\0Astr r2, [r1, #4]", "={r0},{r1},~{r1},~{r2},~{r3},~{r4},~{r5},~{r6},~{r7},~{r8},~{r9},~{r10},~{r11},~{r12},~{lr},~{q0},~{q1},~{q2},~{q3},~{q4},~{q5},~{q6},~{q7},~{q8},~{q9},~{q10},~{q11},~{q12},~{q13},~{q14},~{q15},~{cpsr},~{memory}"(%"internal/task.DeferFrame"* nonnull %deferframe.buf) #4 + %setjmp7 = call i32 asm "\0Amovs r0, #0\0Amov r2, pc\0Astr r2, [r1, #4]", "={r0},{r1},~{r1},~{r2},~{r3},~{r4},~{r5},~{r6},~{r7},~{r8},~{r9},~{r10},~{r11},~{r12},~{lr},~{q0},~{q1},~{q2},~{q3},~{q4},~{q5},~{q6},~{q7},~{q8},~{q9},~{q10},~{q11},~{q12},~{q13},~{q14},~{q15},~{cpsr},~{memory}"(%runtime.deferFrame* nonnull %deferframe.buf) #4 %setjmp.result8 = icmp eq i32 %setjmp7, 0 br i1 %setjmp.result8, label %7, label %lpad @@ -194,11 +194,11 @@ rundefers.default: ; preds = %rundefers.loop unreachable rundefers.end: ; preds = %rundefers.loophead - call void @runtime.destroyDeferFrame(%"internal/task.DeferFrame"* nonnull %deferframe.buf, i8* undef) #3 + call void @runtime.destroyDeferFrame(%runtime.deferFrame* nonnull %deferframe.buf, i8* undef) #3 ret void recover: ; preds = %rundefers.end9 - call void @runtime.destroyDeferFrame(%"internal/task.DeferFrame"* nonnull %deferframe.buf, i8* undef) #3 + call void @runtime.destroyDeferFrame(%runtime.deferFrame* nonnull %deferframe.buf, i8* undef) #3 ret void lpad: ; preds = %rundefers.callback122, %rundefers.callback018, %rundefers.callback1, %rundefers.callback0, %entry @@ -221,7 +221,7 @@ rundefers.loop11: ; preds = %rundefers.loophead1 ] rundefers.callback018: ; preds = %rundefers.loop11 - %setjmp20 = call i32 asm "\0Amovs r0, #0\0Amov r2, pc\0Astr r2, [r1, #4]", "={r0},{r1},~{r1},~{r2},~{r3},~{r4},~{r5},~{r6},~{r7},~{r8},~{r9},~{r10},~{r11},~{r12},~{lr},~{q0},~{q1},~{q2},~{q3},~{q4},~{q5},~{q6},~{q7},~{q8},~{q9},~{q10},~{q11},~{q12},~{q13},~{q14},~{q15},~{cpsr},~{memory}"(%"internal/task.DeferFrame"* nonnull %deferframe.buf) #4 + %setjmp20 = call i32 asm "\0Amovs r0, #0\0Amov r2, pc\0Astr r2, [r1, #4]", "={r0},{r1},~{r1},~{r2},~{r3},~{r4},~{r5},~{r6},~{r7},~{r8},~{r9},~{r10},~{r11},~{r12},~{lr},~{q0},~{q1},~{q2},~{q3},~{q4},~{q5},~{q6},~{q7},~{q8},~{q9},~{q10},~{q11},~{q12},~{q13},~{q14},~{q15},~{cpsr},~{memory}"(%runtime.deferFrame* nonnull %deferframe.buf) #4 %setjmp.result21 = icmp eq i32 %setjmp20, 0 br i1 %setjmp.result21, label %9, label %lpad @@ -230,7 +230,7 @@ rundefers.callback018: ; preds = %rundefers.loop11 br label %rundefers.loophead12 rundefers.callback122: ; preds = %rundefers.loop11 - %setjmp24 = call i32 asm "\0Amovs r0, #0\0Amov r2, pc\0Astr r2, [r1, #4]", "={r0},{r1},~{r1},~{r2},~{r3},~{r4},~{r5},~{r6},~{r7},~{r8},~{r9},~{r10},~{r11},~{r12},~{lr},~{q0},~{q1},~{q2},~{q3},~{q4},~{q5},~{q6},~{q7},~{q8},~{q9},~{q10},~{q11},~{q12},~{q13},~{q14},~{q15},~{cpsr},~{memory}"(%"internal/task.DeferFrame"* nonnull %deferframe.buf) #4 + %setjmp24 = call i32 asm "\0Amovs r0, #0\0Amov r2, pc\0Astr r2, [r1, #4]", "={r0},{r1},~{r1},~{r2},~{r3},~{r4},~{r5},~{r6},~{r7},~{r8},~{r9},~{r10},~{r11},~{r12},~{lr},~{q0},~{q1},~{q2},~{q3},~{q4},~{q5},~{q6},~{q7},~{q8},~{q9},~{q10},~{q11},~{q12},~{q13},~{q14},~{q15},~{cpsr},~{memory}"(%runtime.deferFrame* nonnull %deferframe.buf) #4 %setjmp.result25 = icmp eq i32 %setjmp24, 0 br i1 %setjmp.result25, label %10, label %lpad diff --git a/compiler/testdata/goroutine-cortex-m-qemu-tasks.ll b/compiler/testdata/goroutine-cortex-m-qemu-tasks.ll index 72170b34..36b6d96d 100644 --- a/compiler/testdata/goroutine-cortex-m-qemu-tasks.ll +++ b/compiler/testdata/goroutine-cortex-m-qemu-tasks.ll @@ -5,11 +5,9 @@ target triple = "thumbv7m-unknown-unknown-eabi" %runtime.channel = type { i32, i32, i8, %runtime.channelBlockedList*, i32, i32, i32, i8* } %runtime.channelBlockedList = type { %runtime.channelBlockedList*, %"internal/task.Task"*, %runtime.chanSelectState*, { %runtime.channelBlockedList*, i32, i32 } } -%"internal/task.Task" = type { %"internal/task.Task"*, i8*, i64, %"internal/task.gcData", %"internal/task.state", %"internal/task.DeferFrame"* } +%"internal/task.Task" = type { %"internal/task.Task"*, i8*, i64, %"internal/task.gcData", %"internal/task.state", i8* } %"internal/task.gcData" = type {} %"internal/task.state" = type { i32, i32* } -%"internal/task.DeferFrame" = type { i8*, i8*, %"internal/task.DeferFrame"*, i1, %runtime._interface } -%runtime._interface = type { i32, i8* } %runtime.chanSelectState = type { %runtime.channel*, i8* } @"main$string" = internal unnamed_addr constant [4 x i8] c"test", align 1 diff --git a/compiler/testdata/goroutine-wasm-asyncify.ll b/compiler/testdata/goroutine-wasm-asyncify.ll index 8abc6247..2ffc597d 100644 --- a/compiler/testdata/goroutine-wasm-asyncify.ll +++ b/compiler/testdata/goroutine-wasm-asyncify.ll @@ -5,12 +5,10 @@ target triple = "wasm32-unknown-wasi" %runtime.channel = type { i32, i32, i8, %runtime.channelBlockedList*, i32, i32, i32, i8* } %runtime.channelBlockedList = type { %runtime.channelBlockedList*, %"internal/task.Task"*, %runtime.chanSelectState*, { %runtime.channelBlockedList*, i32, i32 } } -%"internal/task.Task" = type { %"internal/task.Task"*, i8*, i64, %"internal/task.gcData", %"internal/task.state", %"internal/task.DeferFrame"* } +%"internal/task.Task" = type { %"internal/task.Task"*, i8*, i64, %"internal/task.gcData", %"internal/task.state", i8* } %"internal/task.gcData" = type { i8* } %"internal/task.state" = type { i32, i8*, %"internal/task.stackState", i1 } %"internal/task.stackState" = type { i32, i32 } -%"internal/task.DeferFrame" = type { i8*, i8*, %"internal/task.DeferFrame"*, i1, %runtime._interface } -%runtime._interface = type { i32, i8* } %runtime.chanSelectState = type { %runtime.channel*, i8* } @"main$string" = internal unnamed_addr constant [4 x i8] c"test", align 1 diff --git a/src/internal/task/task.go b/src/internal/task/task.go index 3b1bb200..c4573909 100644 --- a/src/internal/task/task.go +++ b/src/internal/task/task.go @@ -23,19 +23,7 @@ type Task struct { // DeferFrame stores a pointer to the (stack allocated) defer frame of the // goroutine that is used for the recover builtin. - DeferFrame *DeferFrame -} - -// DeferFrame is a stack allocated object that stores information for the -// current "defer frame", which is used in functions that use the `defer` -// keyword. -// The compiler knows the JumpPC struct offset. -type DeferFrame struct { - JumpSP unsafe.Pointer // stack pointer to return to - JumpPC unsafe.Pointer // pc to return to - Previous *DeferFrame // previous recover buffer pointer - Panicking bool // true iff this defer frame is panicking - PanicValue interface{} // panic value, might be nil for panic(nil) for example + DeferFrame unsafe.Pointer } // getGoroutineStackSize is a compiler intrinsic that returns the stack size for diff --git a/src/runtime/panic.go b/src/runtime/panic.go index 143f53df..c9914527 100644 --- a/src/runtime/panic.go +++ b/src/runtime/panic.go @@ -13,16 +13,29 @@ func trap() // Inline assembly stub. It is essentially C longjmp but modified a bit for the // purposes of TinyGo. It restores the stack pointer and jumps to the given pc. //export tinygo_longjmp -func tinygo_longjmp(frame *task.DeferFrame) +func tinygo_longjmp(frame *deferFrame) // Compiler intrinsic. // Returns whether recover is supported on the current architecture. func supportsRecover() bool +// DeferFrame is a stack allocated object that stores information for the +// current "defer frame", which is used in functions that use the `defer` +// keyword. +// The compiler knows about the JumpPC struct offset, so it should not be moved +// without also updating compiler/defer.go. +type deferFrame struct { + JumpSP unsafe.Pointer // stack pointer to return to + JumpPC unsafe.Pointer // pc to return to + Previous *deferFrame // previous recover buffer pointer + Panicking bool // true iff this defer frame is panicking + PanicValue interface{} // panic value, might be nil for panic(nil) for example +} + // Builtin function panic(msg), used as a compiler intrinsic. func _panic(message interface{}) { if supportsRecover() { - frame := task.Current().DeferFrame + frame := (*deferFrame)(task.Current().DeferFrame) if frame != nil { frame.PanicValue = message frame.Panicking = true @@ -49,12 +62,12 @@ func runtimePanic(msg string) { // that will be used. //go:inline //go:nobounds -func setupDeferFrame(frame *task.DeferFrame, jumpSP unsafe.Pointer) { +func setupDeferFrame(frame *deferFrame, jumpSP unsafe.Pointer) { currentTask := task.Current() - frame.Previous = currentTask.DeferFrame + frame.Previous = (*deferFrame)(currentTask.DeferFrame) frame.JumpSP = jumpSP frame.Panicking = false - currentTask.DeferFrame = frame + currentTask.DeferFrame = unsafe.Pointer(frame) } // Called right before the return instruction. It pops the defer frame from the @@ -62,8 +75,8 @@ func setupDeferFrame(frame *task.DeferFrame, jumpSP unsafe.Pointer) { // still panicking. //go:inline //go:nobounds -func destroyDeferFrame(frame *task.DeferFrame) { - task.Current().DeferFrame = frame.Previous +func destroyDeferFrame(frame *deferFrame) { + task.Current().DeferFrame = unsafe.Pointer(frame.Previous) if frame.Panicking { // We're still panicking! // Re-raise the panic now. @@ -83,7 +96,7 @@ func _recover(useParentFrame bool) interface{} { // TODO: somehow check that recover() is called directly by a deferred // function in a panicking goroutine. Maybe this can be done by comparing // the frame pointer? - frame := task.Current().DeferFrame + frame := (*deferFrame)(task.Current().DeferFrame) if useParentFrame { // Don't recover panic from the current frame (which can't be panicking // already), but instead from the previous frame.