Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions builder/sizes_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,9 +42,9 @@ func TestBinarySize(t *testing.T) {
// This is a small number of very diverse targets that we want to test.
tests := []sizeTest{
// microcontrollers
{"hifive1b", "examples/echo", 3699, 297, 0, 2252},
{"microbit", "examples/serial", 2736, 356, 8, 2248},
{"wioterminal", "examples/pininterrupt", 7960, 1652, 132, 7480},
{"hifive1b", "examples/echo", 3760, 352, 0, 2252},
{"microbit", "examples/serial", 2761, 395, 8, 2248},
{"wioterminal", "examples/pininterrupt", 7990, 1710, 132, 7480},

// TODO: also check wasm. Right now this is difficult, because
// wasm binaries are run through wasm-opt and therefore the
Expand Down
16 changes: 16 additions & 0 deletions compiler/compiler.go
Original file line number Diff line number Diff line change
Expand Up @@ -2032,6 +2032,22 @@ func (b *builder) createFunctionCall(instr *ssa.CallCommon) (llvm.Value, error)
for _, param := range instr.Args {
params = append(params, b.getValue(param, getPos(instr)))
}
if fn := instr.StaticCallee(); fn != nil {
switch b.getFunctionInfo(fn).linkName {
case "runtime.runtimePanic":
if len(params) == 1 && params[0].IsConstant() {
errType := b.program.ImportedPackage("runtime").Members["plainError"].(*ssa.Type).Type()
err := b.createMakeInterface(params[0], errType, instr.Pos())
return b.createRuntimeCall("runtimePanicValue", []llvm.Value{err, params[0]}, ""), nil
}
case "runtime.runtimePanicAt":
if len(params) == 2 && params[1].IsConstant() {
errType := b.program.ImportedPackage("runtime").Members["plainError"].(*ssa.Type).Type()
err := b.createMakeInterface(params[1], errType, instr.Pos())
return b.createRuntimeCall("runtimePanicAtMsg", []llvm.Value{params[0], err, params[1]}, ""), nil
}
}
}

// Try to call the function directly for trivially static calls.
var callee, context llvm.Value
Expand Down
17 changes: 17 additions & 0 deletions main_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,23 @@ func TestBuild(t *testing.T) {
runTestWithConfig("print.go", t, opts, nil, nil)
})

t.Run("gc=none-runtime-panic", func(t *testing.T) {
t.Parallel()
opts := optionsFromTarget("cortex-m-qemu", sema)
opts.GC = "none"
opts.Scheduler = "none"
config, err := builder.NewConfig(&opts)
if err != nil {
t.Fatal(err)
}
err = Build("testdata/trivialpanic.go", t.TempDir()+"/trivialpanic", config)
if err != nil {
w := &bytes.Buffer{}
diagnostics.CreateDiagnostics(err).WriteTo(w, "")
t.Fatal(w.String())
}
})

t.Run("ldflags", func(t *testing.T) {
t.Parallel()
opts := optionsFromTarget("", sema)
Expand Down
15 changes: 13 additions & 2 deletions src/runtime/panic.go
Original file line number Diff line number Diff line change
Expand Up @@ -84,12 +84,20 @@ func panicOrGoexit(message interface{}, panicking panicState) {

// Cause a runtime panic, which is (currently) always a string.
func runtimePanic(msg string) {
// As long as this function is inined, llvm.returnaddress(0) will return
// As long as this function is inlined, llvm.returnaddress(0) will return
// something sensible.
runtimePanicAt(returnAddress(0), msg)
}
Comment on lines 85 to 90

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmmm yeah

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is a more invasive change that could do this, not sure how people would like it, though 😄


func runtimePanicAt(addr unsafe.Pointer, msg string) {
runtimePanicAtMsg(addr, nil, msg)
}
Comment on lines 92 to +94

func runtimePanicValue(err interface{}, msg string) {
runtimePanicAtMsg(returnAddress(0), err, msg)
}

func runtimePanicAtMsg(addr unsafe.Pointer, err interface{}, msg string) {
if panicStrategy() == tinygo.PanicStrategyTrap {
trap()
}
Expand All @@ -98,7 +106,10 @@ func runtimePanicAt(addr unsafe.Pointer, msg string) {
if frame != nil {
// Use the normal panic mechanism so that this runtime error
// can be recovered with recover().
frame.PanicValue = plainError(msg)
if err == nil {
err = plainError(msg)
}
frame.PanicValue = err
frame.Panicking = panicTrue
tinygo_longjmp(frame)
// unreachable
Expand Down
Loading