mirror of
https://github.com/vlang/v.git
synced 2025-09-15 07:22:27 +03:00
889 lines
15 KiB
V
889 lines
15 KiB
V
// Copyright (c) 2023 l-m.dev. All rights reserved.
|
|
// Use of this source code is governed by an MIT license
|
|
// that can be found in the LICENSE file.
|
|
module wasm
|
|
|
|
import v.ast
|
|
|
|
pub fn (mut g Gen) asm_call(node ast.AsmTemplate) {
|
|
// call 'main.test'
|
|
// call 'main.Struct.+'
|
|
//
|
|
// call 'wasi_unstable' 'proc_exit'
|
|
// call 'console' 'log'
|
|
|
|
if node.args.len !in [1, 2] {
|
|
g.v_error('incorrect number of arguments to `${node.name}`', node.pos)
|
|
}
|
|
|
|
arg0 := node.args[0]
|
|
sarg0 := if arg0 is string {
|
|
arg0
|
|
} else if node.args.len == 1 {
|
|
g.v_error('`${node.name}` must accept a string to call', node.pos)
|
|
} else {
|
|
g.v_error('`${node.name}` must accept a namespace for call', node.pos)
|
|
}
|
|
|
|
if node.args.len == 1 {
|
|
g.func.call(sarg0)
|
|
return
|
|
}
|
|
|
|
arg1 := node.args[1]
|
|
sarg1 := if arg1 is string {
|
|
arg1
|
|
} else {
|
|
g.v_error('`${node.name}` must accept a string for call', node.pos)
|
|
}
|
|
|
|
g.func.call_import(sarg0, sarg1)
|
|
}
|
|
|
|
pub fn (mut g Gen) asm_local_get_set_or_tee(node ast.AsmTemplate, vars AsmVars) {
|
|
if node.args.len != 1 {
|
|
g.v_error('incorrect number of arguments to `${node.name}`', node.pos)
|
|
}
|
|
|
|
arg0 := node.args[0]
|
|
alias := match arg0 {
|
|
ast.AsmAlias {
|
|
arg0
|
|
}
|
|
else {
|
|
g.v_error('must reference local by identifier', node.pos)
|
|
}
|
|
}
|
|
|
|
target_var := if alias.name == '__vbp' {
|
|
Var{
|
|
idx: g.bp()
|
|
}
|
|
} else {
|
|
var := vars[alias.name] or { g.v_error('unknown identifier', alias.pos) }
|
|
var
|
|
}
|
|
// -- doesn't work, cgen error
|
|
// else if var := vars[alias.name] {
|
|
// var
|
|
// }
|
|
|
|
if target_var.is_global {
|
|
g.v_error('`${alias.name}` is global, cannot use with this instruction', alias.pos)
|
|
}
|
|
|
|
match node.name {
|
|
'local.get' {
|
|
g.get(target_var)
|
|
}
|
|
'local.set' {
|
|
g.set(target_var)
|
|
}
|
|
'local.tee' {
|
|
g.tee(target_var)
|
|
}
|
|
else {
|
|
panic('unreachable')
|
|
}
|
|
}
|
|
}
|
|
|
|
pub fn (mut g Gen) asm_global_get_or_set(node ast.AsmTemplate, vars AsmVars) {
|
|
if node.args.len != 1 {
|
|
g.v_error('incorrect number of arguments to `${node.name}`', node.pos)
|
|
}
|
|
|
|
arg0 := node.args[0]
|
|
alias := match arg0 {
|
|
ast.AsmAlias {
|
|
arg0
|
|
}
|
|
else {
|
|
g.v_error('must reference global by identifier', node.pos)
|
|
}
|
|
}
|
|
|
|
target_var := if alias.name == '__vsp' {
|
|
Var{
|
|
g_idx: g.sp()
|
|
is_global: true
|
|
}
|
|
} else if alias.name == '__heap_base' {
|
|
Var{
|
|
g_idx: g.hp()
|
|
is_global: true
|
|
}
|
|
} else {
|
|
var := vars[alias.name] or { g.v_error('unknown identifier', alias.pos) }
|
|
var
|
|
}
|
|
|
|
if !target_var.is_global {
|
|
g.v_error('`${alias.name}` is a local, cannot use with this instruction', alias.pos)
|
|
}
|
|
|
|
match node.name {
|
|
'global.get' {
|
|
g.get(target_var)
|
|
}
|
|
'global.set' {
|
|
g.set(target_var)
|
|
}
|
|
else {
|
|
panic('unreachable')
|
|
}
|
|
}
|
|
}
|
|
|
|
pub fn (mut g Gen) asm_literal_arg(node ast.AsmTemplate) {
|
|
// i32.const
|
|
// i64.const
|
|
// f32.const
|
|
// f64.const
|
|
|
|
if node.args.len != 1 {
|
|
g.v_error('incorrect number of arguments to `${node.name}`', node.pos)
|
|
}
|
|
|
|
is_float := node.name[0] == `f`
|
|
arg := node.args[0]
|
|
|
|
if is_float {
|
|
literal := match arg {
|
|
ast.FloatLiteral {
|
|
arg.val
|
|
}
|
|
ast.IntegerLiteral {
|
|
arg.val
|
|
}
|
|
else {
|
|
g.v_error('must supply float value to `${node.name}`', node.pos)
|
|
}
|
|
}
|
|
|
|
match node.name {
|
|
'f32.const' {
|
|
g.func.f32_const(literal.f32())
|
|
}
|
|
'f64.const' {
|
|
g.func.f64_const(literal.f64())
|
|
}
|
|
else {
|
|
panic('unreachable')
|
|
}
|
|
}
|
|
return
|
|
}
|
|
|
|
literal := match arg {
|
|
ast.BoolLiteral {
|
|
if arg.val {
|
|
'1'
|
|
} else {
|
|
'0'
|
|
}
|
|
}
|
|
ast.CharLiteral {
|
|
u32(arg.val.runes()[0]).str() // there is a better way.
|
|
}
|
|
ast.IntegerLiteral {
|
|
arg.val
|
|
}
|
|
else {
|
|
g.v_error('must supply integer-like value to `${node.name}`', node.pos)
|
|
}
|
|
}
|
|
|
|
match node.name {
|
|
'i32.const' {
|
|
g.func.i32_const(i32(literal.int()))
|
|
}
|
|
'i64.const' {
|
|
g.func.i64_const(literal.i64())
|
|
}
|
|
else {
|
|
panic('unreachable')
|
|
}
|
|
}
|
|
}
|
|
|
|
pub fn (mut g Gen) asm_parse_align_offset(node ast.AsmTemplate) (int, int) {
|
|
if node.args.len != 2 {
|
|
g.v_error('incorrect number of arguments to `${node.name}`', node.pos)
|
|
}
|
|
|
|
arg0 := node.args[0]
|
|
arg1 := node.args[1]
|
|
|
|
align := match arg0 {
|
|
ast.IntegerLiteral {
|
|
arg0.val.int()
|
|
}
|
|
else {
|
|
g.v_error('must supply integer value to align', node.pos)
|
|
}
|
|
}
|
|
|
|
offset := match arg1 {
|
|
ast.IntegerLiteral {
|
|
arg1.val.int()
|
|
}
|
|
else {
|
|
g.v_error('must supply integer value to offset', node.pos)
|
|
}
|
|
}
|
|
|
|
return align, offset
|
|
}
|
|
|
|
pub fn (mut g Gen) asm_load_or_store(node ast.AsmTemplate) {
|
|
align, offset := g.asm_parse_align_offset(node)
|
|
|
|
match node.name {
|
|
'i32.load' {
|
|
g.func.load(.i32_t, align, offset)
|
|
}
|
|
'i64.load' {
|
|
g.func.load(.i64_t, align, offset)
|
|
}
|
|
'f32.load' {
|
|
g.func.load(.f32_t, align, offset)
|
|
}
|
|
'f64.load' {
|
|
g.func.load(.f64_t, align, offset)
|
|
}
|
|
'i32.store' {
|
|
g.func.store(.i32_t, align, offset)
|
|
}
|
|
'i64.store' {
|
|
g.func.store(.i64_t, align, offset)
|
|
}
|
|
'f32.store' {
|
|
g.func.store(.f32_t, align, offset)
|
|
}
|
|
'f64.store' {
|
|
g.func.store(.f64_t, align, offset)
|
|
}
|
|
'i32.load8_s' {
|
|
g.func.load8(.i32_t, true, align, offset)
|
|
}
|
|
'i64.load8_s' {
|
|
g.func.load8(.i64_t, true, align, offset)
|
|
}
|
|
'i32.load8_u' {
|
|
g.func.load8(.i32_t, false, align, offset)
|
|
}
|
|
'i64.load8_u' {
|
|
g.func.load8(.i64_t, false, align, offset)
|
|
}
|
|
'i32.load16_s' {
|
|
g.func.load16(.i32_t, true, align, offset)
|
|
}
|
|
'i64.load16_s' {
|
|
g.func.load16(.i64_t, true, align, offset)
|
|
}
|
|
'i32.load16_u' {
|
|
g.func.load16(.i32_t, false, align, offset)
|
|
}
|
|
'i64.load16_u' {
|
|
g.func.load16(.i64_t, false, align, offset)
|
|
}
|
|
'i64.load32_s' {
|
|
g.func.load32_i64(true, align, offset)
|
|
}
|
|
'i64.load32_u' {
|
|
g.func.load32_i64(false, align, offset)
|
|
}
|
|
'i32.store8' {
|
|
g.func.store8(.i32_t, align, offset)
|
|
}
|
|
'i64.store8' {
|
|
g.func.store8(.i64_t, align, offset)
|
|
}
|
|
'i32.store16' {
|
|
g.func.store16(.i32_t, align, offset)
|
|
}
|
|
'i64.store16' {
|
|
g.func.store16(.i64_t, align, offset)
|
|
}
|
|
'i64.store32' {
|
|
g.func.store32_i64(align, offset)
|
|
}
|
|
else {
|
|
panic('unreachable')
|
|
}
|
|
}
|
|
}
|
|
|
|
pub fn (mut g Gen) asm_template(parent ast.AsmStmt, node ast.AsmTemplate, vars AsmVars) {
|
|
if node.is_label || node.is_directive {
|
|
g.v_error("`asm wasm` doesn't support labels or directives", node.pos)
|
|
}
|
|
|
|
match node.name {
|
|
'unreachable' {
|
|
g.func.unreachable()
|
|
}
|
|
'nop' {
|
|
g.func.nop()
|
|
}
|
|
'drop' {
|
|
g.func.drop()
|
|
}
|
|
'return' {
|
|
g.func.c_return()
|
|
}
|
|
'select' {
|
|
g.func.c_select()
|
|
}
|
|
'i32.const' {
|
|
g.asm_literal_arg(node)
|
|
}
|
|
'i64.const' {
|
|
g.asm_literal_arg(node)
|
|
}
|
|
'f32.const' {
|
|
g.asm_literal_arg(node)
|
|
}
|
|
'f64.const' {
|
|
g.asm_literal_arg(node)
|
|
}
|
|
'local.get' {
|
|
g.asm_local_get_set_or_tee(node, vars)
|
|
}
|
|
'local.set' {
|
|
g.asm_local_get_set_or_tee(node, vars)
|
|
}
|
|
'local.tee' {
|
|
g.asm_local_get_set_or_tee(node, vars)
|
|
}
|
|
'global.get' {
|
|
g.asm_global_get_or_set(node, vars)
|
|
}
|
|
'global.set' {
|
|
g.asm_global_get_or_set(node, vars)
|
|
}
|
|
'i32.load' {
|
|
g.asm_load_or_store(node)
|
|
}
|
|
'i64.load' {
|
|
g.asm_load_or_store(node)
|
|
}
|
|
'f32.load' {
|
|
g.asm_load_or_store(node)
|
|
}
|
|
'f64.load' {
|
|
g.asm_load_or_store(node)
|
|
}
|
|
'i32.store' {
|
|
g.asm_load_or_store(node)
|
|
}
|
|
'i64.store' {
|
|
g.asm_load_or_store(node)
|
|
}
|
|
'f32.store' {
|
|
g.asm_load_or_store(node)
|
|
}
|
|
'f64.store' {
|
|
g.asm_load_or_store(node)
|
|
}
|
|
'i32.load8_s' {
|
|
g.asm_load_or_store(node)
|
|
}
|
|
'i64.load8_s' {
|
|
g.asm_load_or_store(node)
|
|
}
|
|
'i32.load8_u' {
|
|
g.asm_load_or_store(node)
|
|
}
|
|
'i64.load8_u' {
|
|
g.asm_load_or_store(node)
|
|
}
|
|
'i32.load16_s' {
|
|
g.asm_load_or_store(node)
|
|
}
|
|
'i64.load16_s' {
|
|
g.asm_load_or_store(node)
|
|
}
|
|
'i32.load16_u' {
|
|
g.asm_load_or_store(node)
|
|
}
|
|
'i64.load16_u' {
|
|
g.asm_load_or_store(node)
|
|
}
|
|
'i64.load32_s' {
|
|
g.asm_load_or_store(node)
|
|
}
|
|
'i64.load32_u' {
|
|
g.asm_load_or_store(node)
|
|
}
|
|
'i32.store8' {
|
|
g.asm_load_or_store(node)
|
|
}
|
|
'i64.store8' {
|
|
g.asm_load_or_store(node)
|
|
}
|
|
'i32.store16' {
|
|
g.asm_load_or_store(node)
|
|
}
|
|
'i64.store16' {
|
|
g.asm_load_or_store(node)
|
|
}
|
|
'i64.store32' {
|
|
g.asm_load_or_store(node)
|
|
}
|
|
'call' {
|
|
g.asm_call(node)
|
|
}
|
|
'i32.add' {
|
|
g.func.add(.i32_t)
|
|
}
|
|
'i32.sub' {
|
|
g.func.sub(.i32_t)
|
|
}
|
|
'i32.mul' {
|
|
g.func.mul(.i32_t)
|
|
}
|
|
'i32.div_s' {
|
|
g.func.div(.i32_t, true)
|
|
}
|
|
'i32.div_u' {
|
|
g.func.div(.i32_t, false)
|
|
}
|
|
'i32.rem_s' {
|
|
g.func.rem(.i32_t, true)
|
|
}
|
|
'i32.rem_u' {
|
|
g.func.rem(.i32_t, false)
|
|
}
|
|
'i64.add' {
|
|
g.func.add(.i64_t)
|
|
}
|
|
'i64.sub' {
|
|
g.func.sub(.i64_t)
|
|
}
|
|
'i64.mul' {
|
|
g.func.mul(.i64_t)
|
|
}
|
|
'i64.div_s' {
|
|
g.func.div(.i64_t, true)
|
|
}
|
|
'i64.div_u' {
|
|
g.func.div(.i64_t, false)
|
|
}
|
|
'i64.rem_s' {
|
|
g.func.rem(.i64_t, true)
|
|
}
|
|
'i64.rem_u' {
|
|
g.func.rem(.i64_t, false)
|
|
}
|
|
'f32.add' {
|
|
g.func.add(.f32_t)
|
|
}
|
|
'f32.sub' {
|
|
g.func.sub(.f32_t)
|
|
}
|
|
'f32.mul' {
|
|
g.func.mul(.f32_t)
|
|
}
|
|
'f32.div' {
|
|
g.func.div(.f32_t, true)
|
|
}
|
|
'f64.add' {
|
|
g.func.add(.f64_t)
|
|
}
|
|
'f64.sub' {
|
|
g.func.sub(.f64_t)
|
|
}
|
|
'f64.mul' {
|
|
g.func.mul(.f64_t)
|
|
}
|
|
'f64.div' {
|
|
g.func.div(.f64_t, true)
|
|
}
|
|
'i32.eqz' {
|
|
g.func.eqz(.i32_t)
|
|
}
|
|
'i32.eq' {
|
|
g.func.eq(.i32_t)
|
|
}
|
|
'i32.ne' {
|
|
g.func.ne(.i32_t)
|
|
}
|
|
'i32.lt_s' {
|
|
g.func.lt(.i32_t, true)
|
|
}
|
|
'i32.lt_u' {
|
|
g.func.lt(.i32_t, false)
|
|
}
|
|
'i32.gt_s' {
|
|
g.func.gt(.i32_t, true)
|
|
}
|
|
'i32.gt_u' {
|
|
g.func.gt(.i32_t, false)
|
|
}
|
|
'i32.le_s' {
|
|
g.func.le(.i32_t, true)
|
|
}
|
|
'i32.le_u' {
|
|
g.func.le(.i32_t, false)
|
|
}
|
|
'i32.ge_s' {
|
|
g.func.ge(.i32_t, true)
|
|
}
|
|
'i32.ge_u' {
|
|
g.func.ge(.i32_t, false)
|
|
}
|
|
'i64.eqz' {
|
|
g.func.eqz(.i64_t)
|
|
}
|
|
'i64.eq' {
|
|
g.func.eq(.i64_t)
|
|
}
|
|
'i64.ne' {
|
|
g.func.ne(.i64_t)
|
|
}
|
|
'i64.lt_s' {
|
|
g.func.lt(.i64_t, true)
|
|
}
|
|
'i64.lt_u' {
|
|
g.func.lt(.i64_t, false)
|
|
}
|
|
'i64.gt_s' {
|
|
g.func.gt(.i64_t, true)
|
|
}
|
|
'i64.gt_u' {
|
|
g.func.gt(.i64_t, false)
|
|
}
|
|
'i64.le_s' {
|
|
g.func.le(.i64_t, true)
|
|
}
|
|
'i64.le_u' {
|
|
g.func.le(.i64_t, false)
|
|
}
|
|
'i64.ge_s' {
|
|
g.func.ge(.i64_t, true)
|
|
}
|
|
'i64.ge_u' {
|
|
g.func.ge(.i64_t, false)
|
|
}
|
|
'f32.eq' {
|
|
g.func.eq(.f32_t)
|
|
}
|
|
'f32.ne' {
|
|
g.func.ne(.f32_t)
|
|
}
|
|
'f32.lt' {
|
|
g.func.lt(.f32_t, true)
|
|
}
|
|
'f32.gt' {
|
|
g.func.gt(.f32_t, true)
|
|
}
|
|
'f32.le' {
|
|
g.func.le(.f32_t, true)
|
|
}
|
|
'f32.ge' {
|
|
g.func.ge(.f32_t, true)
|
|
}
|
|
'f64.eq' {
|
|
g.func.eq(.f64_t)
|
|
}
|
|
'f64.ne' {
|
|
g.func.ne(.f64_t)
|
|
}
|
|
'f64.lt' {
|
|
g.func.lt(.f64_t, true)
|
|
}
|
|
'f64.gt' {
|
|
g.func.gt(.f64_t, true)
|
|
}
|
|
'f64.le' {
|
|
g.func.le(.f64_t, true)
|
|
}
|
|
'f64.ge' {
|
|
g.func.ge(.f64_t, true)
|
|
}
|
|
'i32.and' {
|
|
g.func.b_and(.i32_t)
|
|
}
|
|
'i32.or' {
|
|
g.func.b_or(.i32_t)
|
|
}
|
|
'i32.xor' {
|
|
g.func.b_xor(.i32_t)
|
|
}
|
|
'i32.shl' {
|
|
g.func.b_shl(.i32_t)
|
|
}
|
|
'i32.shr_s' {
|
|
g.func.b_shr(.i32_t, true)
|
|
}
|
|
'i32.shr_u' {
|
|
g.func.b_shr(.i32_t, true)
|
|
}
|
|
'i32.rotl' {
|
|
g.func.rotl(.i32_t)
|
|
}
|
|
'i32.rotr' {
|
|
g.func.rotr(.i32_t)
|
|
}
|
|
'i32.clz' {
|
|
g.func.clz(.i32_t)
|
|
}
|
|
'i32.ctz' {
|
|
g.func.ctz(.i32_t)
|
|
}
|
|
'i32.popcnt' {
|
|
g.func.popcnt(.i32_t)
|
|
}
|
|
'i64.and' {
|
|
g.func.b_and(.i64_t)
|
|
}
|
|
'i64.or' {
|
|
g.func.b_or(.i64_t)
|
|
}
|
|
'i64.xor' {
|
|
g.func.b_xor(.i64_t)
|
|
}
|
|
'i64.shl' {
|
|
g.func.b_shl(.i64_t)
|
|
}
|
|
'i64.shr_s' {
|
|
g.func.b_shr(.i64_t, true)
|
|
}
|
|
'i64.shr_u' {
|
|
g.func.b_shr(.i64_t, false)
|
|
}
|
|
'i64.rotl' {
|
|
g.func.rotl(.i64_t)
|
|
}
|
|
'i64.rotr' {
|
|
g.func.rotr(.i64_t)
|
|
}
|
|
'i64.clz' {
|
|
g.func.clz(.i64_t)
|
|
}
|
|
'i64.ctz' {
|
|
g.func.ctz(.i64_t)
|
|
}
|
|
'i64.popcnt' {
|
|
g.func.popcnt(.i64_t)
|
|
}
|
|
'f32.neg' {
|
|
g.func.neg(.f32_t)
|
|
}
|
|
'f32.ceil' {
|
|
g.func.ceil(.f32_t)
|
|
}
|
|
'f32.floor' {
|
|
g.func.floor(.f32_t)
|
|
}
|
|
'f32.trunc' {
|
|
g.func.trunc(.f32_t)
|
|
}
|
|
'f32.nearest' {
|
|
g.func.nearest(.f32_t)
|
|
}
|
|
'f32.sqrt' {
|
|
g.func.sqrt(.f32_t)
|
|
}
|
|
'f32.min' {
|
|
g.func.min(.f32_t)
|
|
}
|
|
'f32.max' {
|
|
g.func.max(.f32_t)
|
|
}
|
|
'f32.copysign' {
|
|
g.func.copysign(.f32_t)
|
|
}
|
|
'f64.abs' {
|
|
g.func.abs(.f64_t)
|
|
}
|
|
'f64.neg' {
|
|
g.func.neg(.f64_t)
|
|
}
|
|
'f64.ceil' {
|
|
g.func.ceil(.f64_t)
|
|
}
|
|
'f64.floor' {
|
|
g.func.floor(.f64_t)
|
|
}
|
|
'f64.trunc' {
|
|
g.func.trunc(.f64_t)
|
|
}
|
|
'f64.nearest' {
|
|
g.func.nearest(.f64_t)
|
|
}
|
|
'f64.sqrt' {
|
|
g.func.sqrt(.f64_t)
|
|
}
|
|
'f64.min' {
|
|
g.func.min(.f64_t)
|
|
}
|
|
'f64.max' {
|
|
g.func.max(.f64_t)
|
|
}
|
|
'f64.copysign' {
|
|
g.func.copysign(.f64_t)
|
|
}
|
|
'i32.wrap_i64' {
|
|
g.func.cast(.i64_t, false, .i32_t)
|
|
}
|
|
'i32.trunc_f32_s' {
|
|
g.func.cast_trapping(.f32_t, true, .i32_t)
|
|
}
|
|
'i32.trunc_f32_u' {
|
|
g.func.cast_trapping(.f32_t, false, .i32_t)
|
|
}
|
|
'i32.trunc_f64_s' {
|
|
g.func.cast_trapping(.f64_t, true, .i32_t)
|
|
}
|
|
'i32.trunc_f64_u' {
|
|
g.func.cast_trapping(.f64_t, false, .i32_t)
|
|
}
|
|
'i64.extend_i32_s' {
|
|
g.func.cast(.i32_t, true, .i64_t)
|
|
}
|
|
'i64.extend_i32_u' {
|
|
g.func.cast(.i32_t, false, .i64_t)
|
|
}
|
|
'i64.trunc_f32_s' {
|
|
g.func.cast_trapping(.f32_t, true, .i64_t)
|
|
}
|
|
'i64.trunc_f32_u' {
|
|
g.func.cast_trapping(.f32_t, false, .i64_t)
|
|
}
|
|
'i64.trunc_f64_s' {
|
|
g.func.cast_trapping(.f64_t, true, .i64_t)
|
|
}
|
|
'i64.trunc_f64_u' {
|
|
g.func.cast_trapping(.f64_t, false, .i64_t)
|
|
}
|
|
'f32.convert_i32_s' {
|
|
g.func.cast(.i32_t, true, .f32_t)
|
|
}
|
|
'f32.convert_i32_u' {
|
|
g.func.cast(.i32_t, false, .f32_t)
|
|
}
|
|
'f32.convert_i64_s' {
|
|
g.func.cast(.i64_t, true, .f32_t)
|
|
}
|
|
'f32.convert_i64_u' {
|
|
g.func.cast(.i64_t, false, .f32_t)
|
|
}
|
|
'f32.demote_f64' {
|
|
g.func.cast(.f64_t, true, .f32_t)
|
|
}
|
|
'f64.convert_i32_s' {
|
|
g.func.cast(.i32_t, true, .f64_t)
|
|
}
|
|
'f64.convert_i32_u' {
|
|
g.func.cast(.i32_t, false, .f64_t)
|
|
}
|
|
'f64.convert_i64_s' {
|
|
g.func.cast(.i64_t, true, .f64_t)
|
|
}
|
|
'f64.convert_i64_u' {
|
|
g.func.cast(.i64_t, false, .f64_t)
|
|
}
|
|
'f64.promote_f32' {
|
|
g.func.cast(.f32_t, true, .f64_t)
|
|
}
|
|
'i32.reinterpret_f32' {
|
|
g.func.reinterpret(.f32_t)
|
|
}
|
|
'i64.reinterpret_f64' {
|
|
g.func.reinterpret(.f64_t)
|
|
}
|
|
'f32.reinterpret_i32' {
|
|
g.func.reinterpret(.i32_t)
|
|
}
|
|
'f64.reinterpret_i64' {
|
|
g.func.reinterpret(.i64_t)
|
|
}
|
|
'i32.extend8_s' {
|
|
g.func.sign_extend8(.i32_t)
|
|
}
|
|
'i32.extend16_s' {
|
|
g.func.sign_extend16(.i32_t)
|
|
}
|
|
'i64.extend8_s' {
|
|
g.func.sign_extend8(.i64_t)
|
|
}
|
|
'i64.extend16_s' {
|
|
g.func.sign_extend16(.i64_t)
|
|
}
|
|
'i64.extend32_s' {
|
|
g.func.sign_extend32()
|
|
}
|
|
'i32.trunc_sat_f32_s' {
|
|
g.func.cast(.f32_t, true, .i32_t)
|
|
}
|
|
'i32.trunc_sat_f32_u' {
|
|
g.func.cast(.f32_t, false, .i32_t)
|
|
}
|
|
'i32.trunc_sat_f64_s' {
|
|
g.func.cast(.f64_t, true, .i32_t)
|
|
}
|
|
'i32.trunc_sat_f64_u' {
|
|
g.func.cast(.f64_t, false, .i32_t)
|
|
}
|
|
'i64.trunc_sat_f32_s' {
|
|
g.func.cast(.f32_t, true, .i64_t)
|
|
}
|
|
'i64.trunc_sat_f32_u' {
|
|
g.func.cast(.f32_t, false, .i64_t)
|
|
}
|
|
'i64.trunc_sat_f64_s' {
|
|
g.func.cast(.f64_t, true, .i64_t)
|
|
}
|
|
'i64.trunc_sat_f64_u' {
|
|
g.func.cast(.f64_t, false, .i64_t)
|
|
}
|
|
'memory.size' {
|
|
g.func.memory_size()
|
|
}
|
|
'memory.grow' {
|
|
g.func.memory_grow()
|
|
}
|
|
'memory.copy' {
|
|
g.func.memory_copy()
|
|
}
|
|
'memory.fill' {
|
|
g.func.memory_fill()
|
|
}
|
|
// TODO: impl later
|
|
/*
|
|
'ref.null' {
|
|
g.func.ref_null()
|
|
}
|
|
*/
|
|
else {
|
|
g.v_error('unknown opcode', node.pos)
|
|
}
|
|
}
|
|
}
|
|
|
|
type AsmVars = map[string]Var
|
|
|
|
pub fn (mut g Gen) asm_stmt(node ast.AsmStmt) {
|
|
mut vars := AsmVars(map[string]Var{})
|
|
|
|
for var_expr in node.output {
|
|
vars[var_expr.alias] = g.get_var_or_make_from_expr(var_expr.expr, var_expr.typ)
|
|
}
|
|
for var_expr in node.input {
|
|
vars[var_expr.alias] = g.get_var_or_make_from_expr(var_expr.expr, var_expr.typ)
|
|
}
|
|
|
|
if node.clobbered.len != 0 {
|
|
g.v_error('wasm does not support clobber lists', node.pos)
|
|
}
|
|
if node.global_labels.len != 0 || node.local_labels.len != 0 {
|
|
g.v_error('wasm does not support labels', node.pos)
|
|
}
|
|
|
|
for tmpl in node.templates {
|
|
g.asm_template(node, tmpl, vars)
|
|
}
|
|
}
|