From f2465992533adcf9f98dfea359aba9171a80902f Mon Sep 17 00:00:00 2001 From: Ayke van Laethem Date: Sat, 14 Dec 2024 12:36:17 +0100 Subject: [PATCH] compiler: report error instead of crashing on missing function body This can happen with generic functions, see: https://github.com/tinygo-org/tinygo/issues/4486 --- compiler/symbol.go | 15 +++++++++++++-- testdata/errors/compiler.go | 11 +++++++++++ 2 files changed, 24 insertions(+), 2 deletions(-) diff --git a/compiler/symbol.go b/compiler/symbol.go index 93c27803e2..ff7ef05508 100644 --- a/compiler/symbol.go +++ b/compiler/symbol.go @@ -231,6 +231,15 @@ func (c *compilerContext) getFunction(fn *ssa.Function) (llvm.Type, llvm.Value) } } + // Build the function if needed. + c.maybeCreateSyntheticFunction(fn, llvmFn) + + return fnType, llvmFn +} + +// If this is a synthetic function (such as a generic function or a wrapper), +// create it now. +func (c *compilerContext) maybeCreateSyntheticFunction(fn *ssa.Function, llvmFn llvm.Value) { // Synthetic functions are functions that do not appear in the source code, // they are artificially constructed. Usually they are wrapper functions // that are not referenced anywhere except in a SSA call instruction so @@ -238,6 +247,10 @@ func (c *compilerContext) getFunction(fn *ssa.Function) (llvm.Type, llvm.Value) // The exception is the package initializer, which does appear in the // *ssa.Package members and so shouldn't be created here. if fn.Synthetic != "" && fn.Synthetic != "package initializer" && fn.Synthetic != "generic function" && fn.Synthetic != "range-over-func yield" { + if len(fn.Blocks) == 0 { + c.addError(fn.Pos(), "missing function body") + return + } irbuilder := c.ctx.NewBuilder() b := newBuilder(c, irbuilder, fn) b.createFunction() @@ -245,8 +258,6 @@ func (c *compilerContext) getFunction(fn *ssa.Function) (llvm.Type, llvm.Value) llvmFn.SetLinkage(llvm.LinkOnceODRLinkage) llvmFn.SetUnnamedAddr(true) } - - return fnType, llvmFn } // getFunctionInfo returns information about a function that is not directly diff --git a/testdata/errors/compiler.go b/testdata/errors/compiler.go index 3332c7c2f2..88559103fa 100644 --- a/testdata/errors/compiler.go +++ b/testdata/errors/compiler.go @@ -7,6 +7,17 @@ func foo() { //go:align 7 var global int +// Test for https://github.com/tinygo-org/tinygo/issues/4486 +type genericType[T any] struct{} + +func (genericType[T]) methodWithoutBody() + +func callMethodWithoutBody() { + msg := &genericType[int]{} + msg.methodWithoutBody() +} + // ERROR: # command-line-arguments // ERROR: compiler.go:4:6: can only use //go:wasmimport on declarations // ERROR: compiler.go:8:5: global variable alignment must be a positive power of two +// ERROR: compiler.go:13:23: missing function body