all: add flag to enable i64 parameters in WebAssembly
Этот коммит содержится в:
родитель
dccfae485c
коммит
a8dd82538e
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.
|
||||||
|
|
6
main.go
6
main.go
|
@ -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 != "" {
|
||||||
|
|
Загрузка…
Создание таблицы
Сослаться в новой задаче