docs: move calling convention documentation here
Этот коммит содержится в:
родитель
85d5fe7643
коммит
c7cf6f0e82
2 изменённых файлов: 69 добавлений и 30 удалений
|
@ -5,32 +5,11 @@ import (
|
|||
"golang.org/x/tools/go/ssa"
|
||||
)
|
||||
|
||||
// This file implements the calling convention used by Go.
|
||||
// The calling convention is like the C calling convention (or, whatever LLVM
|
||||
// makes of it) with the following modifications:
|
||||
// * Struct parameters are fully expanded to individual fields (recursively),
|
||||
// when the number of fields (combined) is 3 or less.
|
||||
// Examples:
|
||||
// {i8*, i32} -> i8*, i32
|
||||
// {{i8*, i32}, i16} -> i8*, i32, i16
|
||||
// {{i64}} -> i64
|
||||
// {} ->
|
||||
// {i8*, i32, i8, i8} -> {i8*, i32, i8, i8}
|
||||
// Note that all native Go data types that don't exist in LLVM (string,
|
||||
// slice, interface, fat function pointer) can be expanded this way, making
|
||||
// the work of LLVM optimizers easier.
|
||||
// * Closures have an extra context paramter appended at the end of the
|
||||
// argument list.
|
||||
// * Blocking functions have a coroutine pointer prepended to the argument
|
||||
// list, see src/runtime/scheduler.go for details.
|
||||
// For a description of the calling convention in prose, see docs/internals.rst
|
||||
// or the online version of this document:
|
||||
// https://tinygo.readthedocs.io/en/latest/internals.html#calling-convention
|
||||
//
|
||||
// Some further notes:
|
||||
// * Function pointers are lowered to either a raw function pointer or a
|
||||
// closure struct: { i8*, function pointer }
|
||||
// The function pointer type depends on whether the exact same signature is
|
||||
// used anywhere else in the program for a call that needs a context
|
||||
// (closures, bound methods). If it isn't, it is lowered to a raw function
|
||||
// pointer.
|
||||
// * Defer statements are implemented by transforming the function in the
|
||||
// following way:
|
||||
// * Creating an alloca in the entry block that contains a pointer
|
||||
|
|
|
@ -79,12 +79,12 @@ interface
|
|||
|
||||
function pointer
|
||||
A function pointer has two representations: a literal function pointer and a
|
||||
tuple of ``{context, function pointer}``. Which representation is chosen
|
||||
depends on the AnalyseFunctionPointers pass in `ir/passes.go
|
||||
<https://github.com/aykevl/tinygo/blob/master/ir/passes.go>`_: it tries to
|
||||
use a raw function pointer but will use a function pointer with context if
|
||||
there is a closure or bound method somewhere in the program with the exact
|
||||
same signature.
|
||||
fat function pointer in the form of ``{context, function pointer}``. Which
|
||||
representation is chosen depends on the AnalyseFunctionPointers pass in
|
||||
`ir/passes.go <https://github.com/aykevl/tinygo/blob/master/ir/passes.go>`_:
|
||||
it tries to use a raw function pointer but will use a fat function pointer
|
||||
if there is a closure or bound method somewhere in the program with the
|
||||
exact same signature.
|
||||
|
||||
goroutine
|
||||
A goroutine is a linked list of `LLVM coroutines
|
||||
|
@ -101,6 +101,66 @@ goroutine
|
|||
consumption.
|
||||
|
||||
|
||||
Calling convention
|
||||
------------------
|
||||
|
||||
Go uses a stack-based calling convention and passes a pointer to the argument
|
||||
list as the first argument in the function. There were/are `plans to switch to a
|
||||
register-based calling convention <https://github.com/golang/go/issues/18597>`_
|
||||
but they're now on hold.
|
||||
|
||||
.. highlight:: llvm
|
||||
|
||||
TinyGo, however, uses a register based calling convention. In fact it is
|
||||
somewhat compatible with the C calling convention but with a few quirks:
|
||||
|
||||
* Struct parameters are split into separate arguments, if the number of fields
|
||||
(after flattening recursively) is 3 or lower. This is similar to the `Swift
|
||||
calling convention
|
||||
<https://github.com/apple/swift/blob/master/docs/CallingConvention.rst#physical-conventions>`_.
|
||||
In the case of TinyGo, the size of each field does not matter, a field can
|
||||
even be an array. ::
|
||||
|
||||
{i8*, i32} -> i8*, i32
|
||||
{{i8*, i32}, i16} -> i8*, i32, i16
|
||||
{{i64}} -> i64
|
||||
{} ->
|
||||
{i8*, i32, i8, i8} -> {i8*, i32, i8, i8}
|
||||
{{i8*, i32, i8}, i8} -> {i8*, i32, i8, i8}
|
||||
|
||||
Note that all native Go data types that are lowered to aggregate types in
|
||||
LLVM are expanded this way: ``string``, slices, interfaces, and fat function
|
||||
pointers. This avoids some overhead in the C calling convention and makes
|
||||
the work of the LLVM optimizers easier.
|
||||
|
||||
* 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>`_
|
||||
for details. Whether a function is blocking is determined by the
|
||||
AnalyseBlockingRecursive pass.
|
||||
|
||||
This calling convention may change in the future. Changes will be documented
|
||||
here. However, even though it may change, it is expected that function
|
||||
signatures that only contain integers and pointers will remain stable.
|
||||
|
||||
|
||||
Pipeline
|
||||
--------
|
||||
|
||||
|
|
Загрузка…
Создание таблицы
Сослаться в новой задаче