all: add flag to enable i64 parameters in WebAssembly

Этот коммит содержится в:
Konstantin Yegupov 2018-12-25 17:17:32 +00:00 коммит произвёл Ayke van Laethem
родитель dccfae485c
коммит a8dd82538e
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: E97FF5335DFDFDED
3 изменённых файлов: 20 добавлений и 8 удалений

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

@ -3114,9 +3114,11 @@ func (c *Compiler) NonConstGlobals() {
} }
} }
// Replace i64 in an external function with a stack-allocated i64*, to work // When -wasm-abi flag set to "js" (default),
// replace i64 in an external function with a stack-allocated i64*, to work
// around the lack of 64-bit integers in JavaScript (commonly used together with // around the lack of 64-bit integers in JavaScript (commonly used together with
// WebAssembly). Once that's resolved, this pass may be avoided. // WebAssembly). Once that's resolved, this pass may be avoided.
// See also the -wasm-abi= flag
// https://github.com/WebAssembly/design/issues/1172 // https://github.com/WebAssembly/design/issues/1172
func (c *Compiler) ExternalInt64AsPtr() error { func (c *Compiler) ExternalInt64AsPtr() error {
int64Type := c.ctx.Int64Type() int64Type := c.ctx.Int64Type()
@ -3220,7 +3222,8 @@ func (c *Compiler) ExternalInt64AsPtr() error {
c.builder.SetInsertPointAtEnd(entryBlock) c.builder.SetInsertPointAtEnd(entryBlock)
var callParams []llvm.Value var callParams []llvm.Value
if fnType.ReturnType() == int64Type { if fnType.ReturnType() == int64Type {
return errors.New("todo: i64 return value in exported function") return errors.New("not yet implemented: exported function returns i64 with -wasm-abi=js; " +
"see https://tinygo.org/compiler-internals/calling-convention/")
} }
for i, origParam := range fn.Params() { for i, origParam := range fn.Params() {
paramValue := externalFn.Param(i) paramValue := externalFn.Param(i)

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

@ -130,8 +130,8 @@ somewhat compatible with the C calling convention but with a few quirks:
pointers. This avoids some overhead in the C calling convention and makes pointers. This avoids some overhead in the C calling convention and makes
the work of the LLVM optimizers easier. the work of the LLVM optimizers easier.
* The WebAssembly target never exports or imports a ``i64`` (``int64``, * The WebAssembly target by default doesn't export or import ``i64`` (``int64``,
``uint64``) parameter. Instead, it replaces them with ``i64*``, allocating ``uint64``) parameters. Instead, it replaces them with ``i64*``, allocating
the value on the stack. In other words, imported functions are called with a the value on the stack. In other words, imported functions are called with a
64-bit integer on the stack and exported functions must be called with a 64-bit integer on the stack and exported functions must be called with a
pointer to a 64-bit integer somewhere in linear memory. pointer to a 64-bit integer somewhere in linear memory.
@ -144,10 +144,15 @@ somewhat compatible with the C calling convention but with a few quirks:
calling convention workaround may be removed. Also see `this wasm-bindgen calling convention workaround may be removed. Also see `this wasm-bindgen
issue <https://github.com/rustwasm/wasm-bindgen/issues/35>`_. issue <https://github.com/rustwasm/wasm-bindgen/issues/35>`_.
Currently there are also non-browser WebAssembly execution environments
that do not have this limitation. Use the `-wasm-abi=generic` flag to remove
the behavior described above and enable emitting functions with i64
parameters directly.
* The WebAssembly target does not return variables directly that cannot be * The WebAssembly target does not return variables directly that cannot be
handled by JavaScript (``struct``, ``i64``, multiple return values, etc). handled by JavaScript (see above about ``i64``, also ``struct``, multiple
Instead, they are stored into a pointer passed as the first parameter by the return values, etc). Instead, they are stored into a pointer passed as the
caller. first parameter by the caller.
This is the calling convention as implemented by LLVM, with the extension 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. that ``i64`` return values are returned in the same way as aggregate types.

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

@ -36,6 +36,7 @@ type BuildConfig struct {
initInterp bool initInterp bool
cFlags []string cFlags []string
ldFlags []string ldFlags []string
wasmAbi string
} }
// Helper function for Compiler object. // Helper function for Compiler object.
@ -97,7 +98,8 @@ func Compile(pkgName, outpath string, spec *TargetSpec, config *BuildConfig, act
// cannot be represented exactly in JavaScript (JS only has doubles). To // cannot be represented exactly in JavaScript (JS only has doubles). To
// keep functions interoperable, pass int64 types as pointers to // keep functions interoperable, pass int64 types as pointers to
// stack-allocated values. // stack-allocated values.
if strings.HasPrefix(spec.Triple, "wasm") { // Use -wasm-abi=generic to disable this behaviour.
if config.wasmAbi == "js" && strings.HasPrefix(spec.Triple, "wasm") {
err := c.ExternalInt64AsPtr() err := c.ExternalInt64AsPtr()
if err != nil { if err != nil {
return err return err
@ -507,6 +509,7 @@ func main() {
port := flag.String("port", "/dev/ttyACM0", "flash port") port := flag.String("port", "/dev/ttyACM0", "flash port")
cFlags := flag.String("cflags", "", "additional cflags for compiler") cFlags := flag.String("cflags", "", "additional cflags for compiler")
ldFlags := flag.String("ldflags", "", "additional ldflags for linker") ldFlags := flag.String("ldflags", "", "additional ldflags for linker")
wasmAbi := flag.String("wasm-abi", "js", "WebAssembly ABI conventions: js (no i64 params) or generic")
if len(os.Args) < 2 { if len(os.Args) < 2 {
fmt.Fprintln(os.Stderr, "No command-line arguments supplied.") fmt.Fprintln(os.Stderr, "No command-line arguments supplied.")
@ -524,6 +527,7 @@ func main() {
debug: !*nodebug, debug: !*nodebug,
printSizes: *printSize, printSizes: *printSize,
initInterp: *initInterp, initInterp: *initInterp,
wasmAbi: *wasmAbi,
} }
if *cFlags != "" { if *cFlags != "" {