arm: automatically determine stack sizes

This is a big change that will determine the stack size for many
goroutines automatically. Functions that aren't recursive and don't call
function pointers can in many cases have an automatically determined
worst case stack size. This is useful, as the stack size is usually much
lower than the previous hardcoded default of 1024 bytes: somewhere
around 200-500 bytes is common.

A side effect of this change is that the default stack sizes (including
the stack size for other architectures such as AVR) can now be changed
in the config JSON file, making it tunable per application.
This commit is contained in:
Ayke van Laethem
2020-07-18 13:36:28 +02:00
committed by Ron Evans
parent a761f556ff
commit a21a039ac7
27 changed files with 416 additions and 77 deletions
+4 -4
View File
@@ -4,7 +4,7 @@ target triple = "armv7m-none-eabi"
%"internal/task.state" = type { i8* }
%"internal/task.Task" = type { %"internal/task.Task", i8*, i32, %"internal/task.state" }
declare void @"internal/task.start"(i32, i8*, i8*, i8*)
declare void @"internal/task.start"(i32, i8*, i32, i8*, i8*)
declare void @"internal/task.Pause"(i8*, i8*)
declare void @runtime.scheduler(i8*, i8*)
@@ -102,9 +102,9 @@ define void @sleepGoroutine(i8*, i8* %parentHandle) {
define void @progMain(i8*, i8* %parentHandle) {
entry:
; Call a sync func in a goroutine.
call void @"internal/task.start"(i32 ptrtoint (void (i8*, i8*)* @doNothing to i32), i8* undef, i8* undef, i8* null)
call void @"internal/task.start"(i32 ptrtoint (void (i8*, i8*)* @doNothing to i32), i8* undef, i32 undef, i8* undef, i8* null)
; Call an async func in a goroutine.
call void @"internal/task.start"(i32 ptrtoint (void (i8*, i8*)* @sleepGoroutine to i32), i8* undef, i8* undef, i8* null)
call void @"internal/task.start"(i32 ptrtoint (void (i8*, i8*)* @sleepGoroutine to i32), i8* undef, i32 undef, i8* undef, i8* null)
; Sleep a bit.
call void @sleep(i64 2000000, i8* undef, i8* null)
; Done.
@@ -114,7 +114,7 @@ entry:
; Entrypoint of runtime.
define void @main() {
entry:
call void @"internal/task.start"(i32 ptrtoint (void (i8*, i8*)* @progMain to i32), i8* undef, i8* undef, i8* null)
call void @"internal/task.start"(i32 ptrtoint (void (i8*, i8*)* @progMain to i32), i8* undef, i32 undef, i8* undef, i8* null)
call void @runtime.scheduler(i8* undef, i8* null)
ret void
}
+1 -1
View File
@@ -4,7 +4,7 @@ target triple = "armv7m-none-eabi"
%"internal/task.Task" = type { %"internal/task.Task", i8*, i32, %"internal/task.state" }
%"internal/task.state" = type { i8* }
declare void @"internal/task.start"(i32, i8*, i8*, i8*)
declare void @"internal/task.start"(i32, i8*, i32, i8*, i8*)
declare void @"internal/task.Pause"(i8*, i8*)
+2 -2
View File
@@ -14,7 +14,7 @@ target triple = "wasm32-unknown-unknown-wasm"
declare i32 @runtime.getFuncPtr(i8*, i32, %runtime.typecodeID*, i8*, i8*)
declare void @"internal/task.start"(i32, i8*, i8*, i8*)
declare void @"internal/task.start"(i32, i8*, i32, i8*, i8*)
declare void @runtime.nilPanic(i8*, i8*)
@@ -67,6 +67,6 @@ fpcall.next:
define void @sleepFuncValue(i8*, i32, i8* nocapture readnone %context, i8* nocapture readnone %parentHandle) {
entry:
%2 = call i32 @runtime.getFuncPtr(i8* %0, i32 %1, %runtime.typecodeID* @"reflect/types.type:func:{basic:int}{}", i8* undef, i8* null)
call void @"internal/task.start"(i32 %2, i8* null, i8* undef, i8* null)
call void @"internal/task.start"(i32 %2, i8* null, i32 undef, i8* undef, i8* null)
ret void
}
+3 -3
View File
@@ -14,7 +14,7 @@ target triple = "wasm32-unknown-unknown-wasm"
declare i32 @runtime.getFuncPtr(i8*, i32, %runtime.typecodeID*, i8*, i8*)
declare void @"internal/task.start"(i32, i8*, i8*, i8*)
declare void @"internal/task.start"(i32, i8*, i32, i8*, i8*)
declare void @runtime.nilPanic(i8*, i8*)
@@ -97,11 +97,11 @@ func.nil: ; preds = %entry
unreachable
func.call1: ; preds = %entry
call void @"internal/task.start"(i32 ptrtoint (void (i32, i8*, i8*)* @"main$1" to i32), i8* null, i8* undef, i8* null)
call void @"internal/task.start"(i32 ptrtoint (void (i32, i8*, i8*)* @"main$1" to i32), i8* null, i32 undef, i8* undef, i8* null)
br label %func.next
func.call2: ; preds = %entry
call void @"internal/task.start"(i32 ptrtoint (void (i32, i8*, i8*)* @"main$2" to i32), i8* null, i8* undef, i8* null)
call void @"internal/task.start"(i32 ptrtoint (void (i32, i8*, i8*)* @"main$2" to i32), i8* null, i32 undef, i8* undef, i8* null)
br label %func.next
func.next: ; preds = %func.call2, %func.call1
+15
View File
@@ -0,0 +1,15 @@
target datalayout = "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64"
target triple = "armv7m-none-eabi"
declare i32 @"internal/task.getGoroutineStackSize"(i32, i8*, i8*)
declare void @"runtime.run$1$gowrapper"(i8*)
declare void @"internal/task.start"(i32, i8*, i32)
define void @Reset_Handler() {
entry:
%stacksize = call i32 @"internal/task.getGoroutineStackSize"(i32 ptrtoint (void (i8*)* @"runtime.run$1$gowrapper" to i32), i8* undef, i8* undef)
call void @"internal/task.start"(i32 ptrtoint (void (i8*)* @"runtime.run$1$gowrapper" to i32), i8* undef, i32 %stacksize)
ret void
}
+17
View File
@@ -0,0 +1,17 @@
target datalayout = "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64"
target triple = "armv7m-none-eabi"
@"internal/task.stackSizes" = global [1 x i32] [i32 1024], section ".tinygo_stacksizes"
declare i32 @"internal/task.getGoroutineStackSize"(i32, i8*, i8*)
declare void @"runtime.run$1$gowrapper"(i8*)
declare void @"internal/task.start"(i32, i8*, i32)
define void @Reset_Handler() {
entry:
%stacksize1 = load i32, i32* getelementptr inbounds ([1 x i32], [1 x i32]* @"internal/task.stackSizes", i32 0, i32 0)
call void @"internal/task.start"(i32 ptrtoint (void (i8*)* @"runtime.run$1$gowrapper" to i32), i8* undef, i32 %stacksize1)
ret void
}