native: initial implementation of C.syscall (#12098)
parent
d14b5d0c11
commit
7a6491b9b0
|
@ -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 {
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue