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) {
|
fn (mut g Gen) mov64(reg Register, val i64) {
|
||||||
match reg {
|
match reg {
|
||||||
|
.eax {
|
||||||
|
g.write8(0xb8)
|
||||||
|
g.write8(0x49)
|
||||||
|
}
|
||||||
.rax {
|
.rax {
|
||||||
g.write8(0x48)
|
g.write8(0x48)
|
||||||
g.write8(0xb8)
|
g.write8(0xb8)
|
||||||
|
@ -208,10 +212,17 @@ fn (mut g Gen) mov64(reg Register, val i64) {
|
||||||
g.write8(0xc7)
|
g.write8(0xc7)
|
||||||
g.write8(0xc3)
|
g.write8(0xc3)
|
||||||
}
|
}
|
||||||
|
.edi {
|
||||||
|
g.write8(0xbe)
|
||||||
|
}
|
||||||
.rsi {
|
.rsi {
|
||||||
g.write8(0x48)
|
g.write8(0x48)
|
||||||
g.write8(0xbe)
|
g.write8(0xbe)
|
||||||
}
|
}
|
||||||
|
.rdi {
|
||||||
|
g.write8(0x48)
|
||||||
|
g.write8(0xbf)
|
||||||
|
}
|
||||||
else {
|
else {
|
||||||
eprintln('unhandled mov64 $reg')
|
eprintln('unhandled mov64 $reg')
|
||||||
}
|
}
|
||||||
|
@ -621,7 +632,7 @@ fn (mut g Gen) mov(reg Register, val int) {
|
||||||
.rcx {
|
.rcx {
|
||||||
g.write8(0xc7)
|
g.write8(0xc7)
|
||||||
}
|
}
|
||||||
.edx {
|
.rdx, .edx {
|
||||||
g.write8(0xba)
|
g.write8(0xba)
|
||||||
}
|
}
|
||||||
.rsi {
|
.rsi {
|
||||||
|
|
|
@ -12,7 +12,7 @@ import v.errors
|
||||||
import v.pref
|
import v.pref
|
||||||
import term
|
import term
|
||||||
|
|
||||||
pub const builtins = ['assert', 'print', 'eprint', 'println', 'eprintln', 'exit']
|
pub const builtins = ['assert', 'print', 'eprint', 'println', 'eprintln', 'exit', 'C.syscall']
|
||||||
|
|
||||||
interface CodeGen {
|
interface CodeGen {
|
||||||
mut:
|
mut:
|
||||||
|
@ -497,6 +497,58 @@ fn (mut g Gen) stmt(node ast.Stmt) {
|
||||||
|
|
||||||
fn C.strtol(str &char, endptr &&char, base int) int
|
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) {
|
fn (mut g Gen) expr(node ast.Expr) {
|
||||||
match node {
|
match node {
|
||||||
ast.ParExpr {
|
ast.ParExpr {
|
||||||
|
@ -507,7 +559,9 @@ fn (mut g Gen) expr(node ast.Expr) {
|
||||||
}
|
}
|
||||||
ast.BoolLiteral {}
|
ast.BoolLiteral {}
|
||||||
ast.CallExpr {
|
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)
|
g.gen_exit(node.args[0].expr)
|
||||||
} else if node.name in ['println', 'print', 'eprintln', 'eprint'] {
|
} else if node.name in ['println', 'print', 'eprintln', 'eprint'] {
|
||||||
expr := node.args[0].expr
|
expr := node.args[0].expr
|
||||||
|
|
Loading…
Reference in New Issue