runtime: move *task.DeferFrame here
This is a refactor that makes the next commit simpler. Perhaps it should have been like this from the beginning but I didn't like all the casts.
Этот коммит содержится в:
родитель
49e22fe678
коммит
159f0051bb
7 изменённых файлов: 45 добавлений и 50 удалений
|
@ -71,7 +71,7 @@ func (b *builder) deferInitFunc() {
|
||||||
// possibly broken by the C alloca function).
|
// possibly broken by the C alloca function).
|
||||||
// The frame pointer is _not_ saved, because it is marked as clobbered
|
// The frame pointer is _not_ saved, because it is marked as clobbered
|
||||||
// in the setjmp-like inline assembly.
|
// 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")
|
b.deferFrame = b.CreateAlloca(deferFrameType, "deferframe.buf")
|
||||||
stackPointer := b.readStackPointer()
|
stackPointer := b.readStackPointer()
|
||||||
b.createRuntimeCall("setupDeferFrame", []llvm.Value{b.deferFrame, stackPointer}, "")
|
b.createRuntimeCall("setupDeferFrame", []llvm.Value{b.deferFrame, stackPointer}, "")
|
||||||
|
|
4
compiler/testdata/channel.ll
предоставленный
4
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.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 } }
|
%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.gcData" = type { i8* }
|
||||||
%"internal/task.state" = type { i32, i8*, %"internal/task.stackState", i1 }
|
%"internal/task.state" = type { i32, i8*, %"internal/task.stackState", i1 }
|
||||||
%"internal/task.stackState" = type { i32, i32 }
|
%"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* }
|
%runtime.chanSelectState = type { %runtime.channel*, i8* }
|
||||||
|
|
||||||
declare noalias nonnull i8* @runtime.alloc(i32, i8*, i8*)
|
declare noalias nonnull i8* @runtime.alloc(i32, i8*, i8*)
|
||||||
|
|
38
compiler/testdata/defer-cortex-m-qemu.ll
предоставленный
38
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"
|
target triple = "thumbv7m-unknown-unknown-eabi"
|
||||||
|
|
||||||
%runtime._defer = type { i32, %runtime._defer* }
|
%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* }
|
%runtime._interface = type { i32, i8* }
|
||||||
|
|
||||||
declare noalias nonnull i8* @runtime.alloc(i32, i8*, i8*) #0
|
declare noalias nonnull i8* @runtime.alloc(i32, i8*, i8*) #0
|
||||||
|
@ -23,16 +23,16 @@ entry:
|
||||||
%defer.alloca = alloca { i32, %runtime._defer* }, align 4
|
%defer.alloca = alloca { i32, %runtime._defer* }, align 4
|
||||||
%deferPtr = alloca %runtime._defer*, align 4
|
%deferPtr = alloca %runtime._defer*, align 4
|
||||||
store %runtime._defer* null, %runtime._defer** %deferPtr, 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()
|
%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
|
%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
|
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
|
%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
|
store %runtime._defer* null, %runtime._defer** %defer.alloca.repack16, align 4
|
||||||
%1 = bitcast %runtime._defer** %deferPtr to { i32, %runtime._defer* }**
|
%1 = bitcast %runtime._defer** %deferPtr to { i32, %runtime._defer* }**
|
||||||
store { i32, %runtime._defer* }* %defer.alloca, { i32, %runtime._defer* }** %1, align 4
|
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
|
%setjmp.result = icmp eq i32 %setjmp, 0
|
||||||
br i1 %setjmp.result, label %2, label %lpad
|
br i1 %setjmp.result, label %2, label %lpad
|
||||||
|
|
||||||
|
@ -56,7 +56,7 @@ rundefers.loop: ; preds = %rundefers.loophead
|
||||||
]
|
]
|
||||||
|
|
||||||
rundefers.callback0: ; preds = %rundefers.loop
|
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
|
%setjmp.result2 = icmp eq i32 %setjmp1, 0
|
||||||
br i1 %setjmp.result2, label %4, label %lpad
|
br i1 %setjmp.result2, label %4, label %lpad
|
||||||
|
|
||||||
|
@ -68,11 +68,11 @@ rundefers.default: ; preds = %rundefers.loop
|
||||||
unreachable
|
unreachable
|
||||||
|
|
||||||
rundefers.end: ; preds = %rundefers.loophead
|
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
|
ret void
|
||||||
|
|
||||||
recover: ; preds = %rundefers.end3
|
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
|
ret void
|
||||||
|
|
||||||
lpad: ; preds = %rundefers.callback012, %rundefers.callback0, %entry
|
lpad: ; preds = %rundefers.callback012, %rundefers.callback0, %entry
|
||||||
|
@ -94,7 +94,7 @@ rundefers.loop5: ; preds = %rundefers.loophead6
|
||||||
]
|
]
|
||||||
|
|
||||||
rundefers.callback012: ; preds = %rundefers.loop5
|
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
|
%setjmp.result15 = icmp eq i32 %setjmp14, 0
|
||||||
br i1 %setjmp.result15, label %6, label %lpad
|
br i1 %setjmp.result15, label %6, label %lpad
|
||||||
|
|
||||||
|
@ -112,7 +112,7 @@ rundefers.end3: ; preds = %rundefers.loophead6
|
||||||
; Function Attrs: nofree nosync nounwind willreturn
|
; Function Attrs: nofree nosync nounwind willreturn
|
||||||
declare i8* @llvm.stacksave() #2
|
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
|
; Function Attrs: nounwind
|
||||||
define hidden void @"main.deferSimple$1"(i8* %context) unnamed_addr #1 {
|
define hidden void @"main.deferSimple$1"(i8* %context) unnamed_addr #1 {
|
||||||
|
@ -121,7 +121,7 @@ entry:
|
||||||
ret void
|
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
|
declare void @runtime.printint32(i32, i8*) #0
|
||||||
|
|
||||||
|
@ -132,9 +132,9 @@ entry:
|
||||||
%defer.alloca = alloca { i32, %runtime._defer* }, align 4
|
%defer.alloca = alloca { i32, %runtime._defer* }, align 4
|
||||||
%deferPtr = alloca %runtime._defer*, align 4
|
%deferPtr = alloca %runtime._defer*, align 4
|
||||||
store %runtime._defer* null, %runtime._defer** %deferPtr, 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()
|
%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
|
%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
|
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
|
%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
|
store { i32, %runtime._defer* }* %defer.alloca, { i32, %runtime._defer* }** %2, align 4
|
||||||
%3 = bitcast %runtime._defer** %deferPtr to { i32, %runtime._defer* }**
|
%3 = bitcast %runtime._defer** %deferPtr to { i32, %runtime._defer* }**
|
||||||
store { i32, %runtime._defer* }* %defer.alloca2, { i32, %runtime._defer* }** %3, align 4
|
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
|
%setjmp.result = icmp eq i32 %setjmp, 0
|
||||||
br i1 %setjmp.result, label %4, label %lpad
|
br i1 %setjmp.result, label %4, label %lpad
|
||||||
|
|
||||||
|
@ -173,7 +173,7 @@ rundefers.loop: ; preds = %rundefers.loophead
|
||||||
]
|
]
|
||||||
|
|
||||||
rundefers.callback0: ; preds = %rundefers.loop
|
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
|
%setjmp.result5 = icmp eq i32 %setjmp4, 0
|
||||||
br i1 %setjmp.result5, label %6, label %lpad
|
br i1 %setjmp.result5, label %6, label %lpad
|
||||||
|
|
||||||
|
@ -182,7 +182,7 @@ rundefers.callback0: ; preds = %rundefers.loop
|
||||||
br label %rundefers.loophead
|
br label %rundefers.loophead
|
||||||
|
|
||||||
rundefers.callback1: ; preds = %rundefers.loop
|
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
|
%setjmp.result8 = icmp eq i32 %setjmp7, 0
|
||||||
br i1 %setjmp.result8, label %7, label %lpad
|
br i1 %setjmp.result8, label %7, label %lpad
|
||||||
|
|
||||||
|
@ -194,11 +194,11 @@ rundefers.default: ; preds = %rundefers.loop
|
||||||
unreachable
|
unreachable
|
||||||
|
|
||||||
rundefers.end: ; preds = %rundefers.loophead
|
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
|
ret void
|
||||||
|
|
||||||
recover: ; preds = %rundefers.end9
|
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
|
ret void
|
||||||
|
|
||||||
lpad: ; preds = %rundefers.callback122, %rundefers.callback018, %rundefers.callback1, %rundefers.callback0, %entry
|
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
|
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
|
%setjmp.result21 = icmp eq i32 %setjmp20, 0
|
||||||
br i1 %setjmp.result21, label %9, label %lpad
|
br i1 %setjmp.result21, label %9, label %lpad
|
||||||
|
|
||||||
|
@ -230,7 +230,7 @@ rundefers.callback018: ; preds = %rundefers.loop11
|
||||||
br label %rundefers.loophead12
|
br label %rundefers.loophead12
|
||||||
|
|
||||||
rundefers.callback122: ; preds = %rundefers.loop11
|
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
|
%setjmp.result25 = icmp eq i32 %setjmp24, 0
|
||||||
br i1 %setjmp.result25, label %10, label %lpad
|
br i1 %setjmp.result25, label %10, label %lpad
|
||||||
|
|
||||||
|
|
4
compiler/testdata/goroutine-cortex-m-qemu-tasks.ll
предоставленный
4
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.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 } }
|
%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.gcData" = type {}
|
||||||
%"internal/task.state" = type { i32, i32* }
|
%"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* }
|
%runtime.chanSelectState = type { %runtime.channel*, i8* }
|
||||||
|
|
||||||
@"main$string" = internal unnamed_addr constant [4 x i8] c"test", align 1
|
@"main$string" = internal unnamed_addr constant [4 x i8] c"test", align 1
|
||||||
|
|
4
compiler/testdata/goroutine-wasm-asyncify.ll
предоставленный
4
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.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 } }
|
%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.gcData" = type { i8* }
|
||||||
%"internal/task.state" = type { i32, i8*, %"internal/task.stackState", i1 }
|
%"internal/task.state" = type { i32, i8*, %"internal/task.stackState", i1 }
|
||||||
%"internal/task.stackState" = type { i32, i32 }
|
%"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* }
|
%runtime.chanSelectState = type { %runtime.channel*, i8* }
|
||||||
|
|
||||||
@"main$string" = internal unnamed_addr constant [4 x i8] c"test", align 1
|
@"main$string" = internal unnamed_addr constant [4 x i8] c"test", align 1
|
||||||
|
|
|
@ -23,19 +23,7 @@ type Task struct {
|
||||||
|
|
||||||
// DeferFrame stores a pointer to the (stack allocated) defer frame of the
|
// DeferFrame stores a pointer to the (stack allocated) defer frame of the
|
||||||
// goroutine that is used for the recover builtin.
|
// goroutine that is used for the recover builtin.
|
||||||
DeferFrame *DeferFrame
|
DeferFrame unsafe.Pointer
|
||||||
}
|
|
||||||
|
|
||||||
// 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
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// getGoroutineStackSize is a compiler intrinsic that returns the stack size for
|
// getGoroutineStackSize is a compiler intrinsic that returns the stack size for
|
||||||
|
|
|
@ -13,16 +13,29 @@ func trap()
|
||||||
// Inline assembly stub. It is essentially C longjmp but modified a bit for the
|
// 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.
|
// purposes of TinyGo. It restores the stack pointer and jumps to the given pc.
|
||||||
//export tinygo_longjmp
|
//export tinygo_longjmp
|
||||||
func tinygo_longjmp(frame *task.DeferFrame)
|
func tinygo_longjmp(frame *deferFrame)
|
||||||
|
|
||||||
// Compiler intrinsic.
|
// Compiler intrinsic.
|
||||||
// Returns whether recover is supported on the current architecture.
|
// Returns whether recover is supported on the current architecture.
|
||||||
func supportsRecover() bool
|
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.
|
// Builtin function panic(msg), used as a compiler intrinsic.
|
||||||
func _panic(message interface{}) {
|
func _panic(message interface{}) {
|
||||||
if supportsRecover() {
|
if supportsRecover() {
|
||||||
frame := task.Current().DeferFrame
|
frame := (*deferFrame)(task.Current().DeferFrame)
|
||||||
if frame != nil {
|
if frame != nil {
|
||||||
frame.PanicValue = message
|
frame.PanicValue = message
|
||||||
frame.Panicking = true
|
frame.Panicking = true
|
||||||
|
@ -49,12 +62,12 @@ func runtimePanic(msg string) {
|
||||||
// that will be used.
|
// that will be used.
|
||||||
//go:inline
|
//go:inline
|
||||||
//go:nobounds
|
//go:nobounds
|
||||||
func setupDeferFrame(frame *task.DeferFrame, jumpSP unsafe.Pointer) {
|
func setupDeferFrame(frame *deferFrame, jumpSP unsafe.Pointer) {
|
||||||
currentTask := task.Current()
|
currentTask := task.Current()
|
||||||
frame.Previous = currentTask.DeferFrame
|
frame.Previous = (*deferFrame)(currentTask.DeferFrame)
|
||||||
frame.JumpSP = jumpSP
|
frame.JumpSP = jumpSP
|
||||||
frame.Panicking = false
|
frame.Panicking = false
|
||||||
currentTask.DeferFrame = frame
|
currentTask.DeferFrame = unsafe.Pointer(frame)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Called right before the return instruction. It pops the defer frame from the
|
// 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.
|
// still panicking.
|
||||||
//go:inline
|
//go:inline
|
||||||
//go:nobounds
|
//go:nobounds
|
||||||
func destroyDeferFrame(frame *task.DeferFrame) {
|
func destroyDeferFrame(frame *deferFrame) {
|
||||||
task.Current().DeferFrame = frame.Previous
|
task.Current().DeferFrame = unsafe.Pointer(frame.Previous)
|
||||||
if frame.Panicking {
|
if frame.Panicking {
|
||||||
// We're still panicking!
|
// We're still panicking!
|
||||||
// Re-raise the panic now.
|
// 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
|
// TODO: somehow check that recover() is called directly by a deferred
|
||||||
// function in a panicking goroutine. Maybe this can be done by comparing
|
// function in a panicking goroutine. Maybe this can be done by comparing
|
||||||
// the frame pointer?
|
// the frame pointer?
|
||||||
frame := task.Current().DeferFrame
|
frame := (*deferFrame)(task.Current().DeferFrame)
|
||||||
if useParentFrame {
|
if useParentFrame {
|
||||||
// Don't recover panic from the current frame (which can't be panicking
|
// Don't recover panic from the current frame (which can't be panicking
|
||||||
// already), but instead from the previous frame.
|
// already), but instead from the previous frame.
|
||||||
|
|
Загрузка…
Создание таблицы
Сослаться в новой задаче