From 7a6491b9b0c818dc24eb4e7a7ce87535a080b864 Mon Sep 17 00:00:00 2001 From: pancake Date: Sat, 9 Oct 2021 14:01:30 +0200 Subject: [PATCH] native: initial implementation of C.syscall (#12098) --- vlib/v/gen/native/amd64.v | 13 ++++++++- vlib/v/gen/native/gen.v | 58 +++++++++++++++++++++++++++++++++++++-- 2 files changed, 68 insertions(+), 3 deletions(-) diff --git a/vlib/v/gen/native/amd64.v b/vlib/v/gen/native/amd64.v index 7ee4e7e421..b256f734f2 100644 --- a/vlib/v/gen/native/amd64.v +++ b/vlib/v/gen/native/amd64.v @@ -194,6 +194,10 @@ fn (mut g Gen) jmp(addr i64) { */ fn (mut g Gen) mov64(reg Register, val i64) { match reg { + .eax { + g.write8(0xb8) + g.write8(0x49) + } .rax { g.write8(0x48) g.write8(0xb8) @@ -208,10 +212,17 @@ fn (mut g Gen) mov64(reg Register, val i64) { g.write8(0xc7) g.write8(0xc3) } + .edi { + g.write8(0xbe) + } .rsi { g.write8(0x48) g.write8(0xbe) } + .rdi { + g.write8(0x48) + g.write8(0xbf) + } else { eprintln('unhandled mov64 $reg') } @@ -621,7 +632,7 @@ fn (mut g Gen) mov(reg Register, val int) { .rcx { g.write8(0xc7) } - .edx { + .rdx, .edx { g.write8(0xba) } .rsi { diff --git a/vlib/v/gen/native/gen.v b/vlib/v/gen/native/gen.v index 8859790882..c7c93056e8 100644 --- a/vlib/v/gen/native/gen.v +++ b/vlib/v/gen/native/gen.v @@ -12,7 +12,7 @@ import v.errors import v.pref import term -pub const builtins = ['assert', 'print', 'eprint', 'println', 'eprintln', 'exit'] +pub const builtins = ['assert', 'print', 'eprint', 'println', 'eprintln', 'exit', 'C.syscall'] interface CodeGen { mut: @@ -497,6 +497,58 @@ fn (mut g Gen) stmt(node ast.Stmt) { fn C.strtol(str &char, endptr &&char, base int) int +fn (mut g Gen) gen_syscall(node ast.CallExpr) { + mut i := 0 + mut ra := [Register.rax, .rdi, .rsi, .rdx] + for i < node.args.len { + expr := node.args[i].expr + if i >= ra.len { + g.warning('Too many arguments for syscall', node.pos) + return + } + match expr { + ast.IntegerLiteral { + g.mov(ra[i], expr.val.int()) + } + ast.BoolLiteral { + g.mov(ra[i], if expr.val { 1 } else { 0 }) + } + ast.SelectorExpr { + mut done := false + if expr.field_name == 'str' { + match expr.expr { + ast.StringLiteral { + s := expr.expr.val.replace('\\n', '\n') + g.allocate_string(s, 2) + g.mov64(ra[i], 1) + done = true + } + else {} + } + } + if !done { + g.v_error('Unknown selector in syscall argument type $expr', node.pos) + } + } + ast.StringLiteral { + if expr.language != .c { + g.warning('C.syscall expects c"string" or "string".str, C backend will crash', + node.pos) + } + s := expr.val.replace('\\n', '\n') + g.allocate_string(s, 2) + g.mov64(ra[i], 1) + } + else { + g.v_error('Unknown syscall $expr.type_name() argument type $expr', node.pos) + return + } + } + i++ + } + g.syscall() +} + fn (mut g Gen) expr(node ast.Expr) { match node { ast.ParExpr { @@ -507,7 +559,9 @@ fn (mut g Gen) expr(node ast.Expr) { } ast.BoolLiteral {} ast.CallExpr { - if node.name == 'exit' { + if node.name == 'C.syscall' { + g.gen_syscall(node) + } else if node.name == 'exit' { g.gen_exit(node.args[0].expr) } else if node.name in ['println', 'print', 'eprintln', 'eprint'] { expr := node.args[0].expr