native: initial implementation of C.syscall (#12098)

pull/12129/head
pancake 2021-10-09 14:01:30 +02:00 committed by GitHub
parent d14b5d0c11
commit 7a6491b9b0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 68 additions and 3 deletions

View File

@ -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 {

View File

@ -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