compiler: disallow exporting functions that have their address taken

This simplifies the ABI a lot and makes future changes easier.
In the future, determining which functions need a context parameter
should be moved from IR generation into an optimization pass, avoiding
the need for recursively scanning the Go SSA.
Этот коммит содержится в:
Ayke van Laethem 2018-12-01 17:31:36 +01:00
родитель da0a02d128
коммит e54a1c4dc0
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: E97FF5335DFDFDED
2 изменённых файлов: 3 добавлений и 17 удалений

Просмотреть файл

@ -2280,6 +2280,9 @@ func (c *Compiler) parseExpr(frame *Frame, expr ssa.Value) (llvm.Value, error) {
return c.builder.CreateGEP(val, indices, ""), nil
case *ssa.Function:
fn := c.ir.GetFunction(expr)
if fn.IsExported() {
return llvm.Value{}, c.makeError(expr.Pos(), "cannot use an exported function as value")
}
ptr := fn.LLVMFn
if c.ir.FunctionNeedsContext(fn) {
// Create closure for function pointer.

Просмотреть файл

@ -155,23 +155,6 @@ somewhat compatible with the C calling convention but with a few quirks:
This is the calling convention as implemented by LLVM, with the extension
that ``i64`` return values are returned in the same way as aggregate types.
* Some functions have an extra context parameter appended at the end of the
argument list. This only happens when both of these conditions hold:
* The address of the function is taken, for example when passing the
function as function pointer to another function or storing it in a
global variable.
* This function or another function somewhere in the compiled code has the
exact same signature and is used in a closure or bound method. Signature
matching is very strict: it is based on Go types including named types
and return types, although parameter names or the function name itself
are not included in the match.
Whether a function needs this is determined by `FunctionNeedsContext
<https://godoc.org/github.com/aykevl/tinygo/ir#Program.FunctionNeedsContext>`_,
which bases itself on analysis done by AnalyseFunctionPointers.
* Blocking functions have a coroutine pointer prepended to the argument list,
see `src/runtime/scheduler.go
<https://github.com/aykevl/tinygo/blob/master/src/runtime/scheduler.go>`_