mirror of
https://github.com/vlang/v.git
synced 2023-08-10 21:13:21 +03:00
native: move functions out of amd64.v (#18857)
This commit is contained in:
parent
a9a94cfd51
commit
3081919a8f
@ -530,7 +530,9 @@ fn (mut c Amd64) movabs(r Register, val i64) {
|
||||
c.g.println('movabs ${reg}, ${val}')
|
||||
}
|
||||
|
||||
fn (mut c Amd64) mov_deref(reg Amd64Register, regptr Amd64Register, typ ast.Type) {
|
||||
fn (mut c Amd64) mov_deref(r Register, rptr Register, typ ast.Type) {
|
||||
reg := r as Amd64Register
|
||||
regptr := rptr as Amd64Register
|
||||
size := c.g.get_type_size(typ)
|
||||
if size !in [1, 2, 4, 8] {
|
||||
c.g.n_error('Invalid size on dereferencing')
|
||||
@ -1038,7 +1040,8 @@ pub fn (mut c Amd64) sub(reg Amd64Register, val int) {
|
||||
c.g.println('sub ${reg},${val.hex2()}')
|
||||
}
|
||||
|
||||
pub fn (mut c Amd64) add(reg Amd64Register, val int) {
|
||||
pub fn (mut c Amd64) add(r Register, val int) {
|
||||
reg := r as Amd64Register
|
||||
c.g.write8(0x48)
|
||||
if reg == .rax {
|
||||
c.g.write8(0x05)
|
||||
@ -1556,7 +1559,9 @@ fn (mut c Amd64) add_reg(a Amd64Register, b Amd64Register) {
|
||||
c.g.println('add ${a}, ${b}')
|
||||
}
|
||||
|
||||
fn (mut c Amd64) mov_reg_amd64(a Amd64Register, b Amd64Register) {
|
||||
fn (mut c Amd64) mov_reg(a_reg Register, b_reg Register) {
|
||||
a := a_reg as Amd64Register
|
||||
b := b_reg as Amd64Register
|
||||
if int(a) <= int(Amd64Register.r15) && int(b) <= int(Amd64Register.r15) {
|
||||
c.g.write8(0x48 + if int(a) >= int(Amd64Register.r8) { 1 } else { 0 } +
|
||||
if int(b) >= int(Amd64Register.r8) { 4 } else { 0 })
|
||||
@ -1568,10 +1573,6 @@ fn (mut c Amd64) mov_reg_amd64(a Amd64Register, b Amd64Register) {
|
||||
c.g.println('mov ${a}, ${b}')
|
||||
}
|
||||
|
||||
fn (mut c Amd64) mov_reg(a Register, b Register) {
|
||||
c.mov_reg_amd64(a as Amd64Register, b as Amd64Register)
|
||||
}
|
||||
|
||||
fn (mut c Amd64) add_store(a Amd64Register, b Amd64Register, size Size) {
|
||||
if size == ._16 {
|
||||
c.g.write8(0x66)
|
||||
@ -1727,17 +1728,17 @@ pub fn (mut c Amd64) call_fn(node ast.CallExpr) {
|
||||
if c.g.table.sym(args[i].typ).kind == .struct_ && !args[i].typ.is_ptr() {
|
||||
match args_size[i] {
|
||||
1...8 {
|
||||
c.mov_deref(.rax, .rax, ast.i64_type_idx)
|
||||
c.mov_deref(Amd64Register.rax, Amd64Register.rax, ast.i64_type_idx)
|
||||
if args_size[i] != 8 {
|
||||
c.movabs(Amd64Register.rdx, i64((u64(1) << (args_size[i] * 8)) - 1))
|
||||
c.bitand_reg(.rax, .rdx)
|
||||
}
|
||||
}
|
||||
9...16 {
|
||||
c.add(.rax, 8)
|
||||
c.mov_deref(.rdx, .rax, ast.i64_type_idx)
|
||||
c.add(Amd64Register.rax, 8)
|
||||
c.mov_deref(Amd64Register.rdx, Amd64Register.rax, ast.i64_type_idx)
|
||||
c.sub(.rax, 8)
|
||||
c.mov_deref(.rax, .rax, ast.i64_type_idx)
|
||||
c.mov_deref(Amd64Register.rax, Amd64Register.rax, ast.i64_type_idx)
|
||||
if args_size[i] != 16 {
|
||||
c.movabs(Amd64Register.rbx, i64((u64(1) << ((args_size[i] - 8) * 8)) - 1))
|
||||
c.bitand_reg(.rdx, .rbx)
|
||||
@ -1762,9 +1763,9 @@ pub fn (mut c Amd64) call_fn(node ast.CallExpr) {
|
||||
c.push(Amd64Register.rax)
|
||||
}
|
||||
else {
|
||||
c.add(.rax, args_size[i] - ((args_size[i] + 7) % 8 + 1))
|
||||
c.add(Amd64Register.rax, args_size[i] - ((args_size[i] + 7) % 8 + 1))
|
||||
for _ in 0 .. (args_size[i] + 7) / 8 {
|
||||
c.mov_deref(.rdx, .rax, ast.i64_type_idx)
|
||||
c.mov_deref(Amd64Register.rdx, Amd64Register.rax, ast.i64_type_idx)
|
||||
c.push(Amd64Register.rdx)
|
||||
c.sub(.rax, 8)
|
||||
}
|
||||
@ -1855,55 +1856,6 @@ fn (mut c Amd64) call_builtin(name Builtin) i64 {
|
||||
return call_addr
|
||||
}
|
||||
|
||||
fn (mut c Amd64) gen_concat_expr(node ast.ConcatExpr) {
|
||||
typ := node.return_type
|
||||
ts := c.g.table.sym(typ)
|
||||
size := c.g.get_type_size(typ)
|
||||
// construct a struct variable contains the return value
|
||||
var := LocalVar{
|
||||
offset: c.g.allocate_by_type('', typ)
|
||||
typ: typ
|
||||
}
|
||||
// zero fill
|
||||
mut left := if size >= 16 {
|
||||
c.mov(Amd64Register.rax, 0)
|
||||
c.mov(Amd64Register.rcx, size / 8)
|
||||
c.lea_var_to_reg(Amd64Register.rdi, var.offset)
|
||||
c.g.write([u8(0xf3), 0x48, 0xab])
|
||||
c.g.println('rep stosq')
|
||||
size % 8
|
||||
} else {
|
||||
size
|
||||
}
|
||||
if left >= 8 {
|
||||
c.mov_int_to_var(var, 0, offset: size - left, typ: ast.i64_type_idx)
|
||||
left -= 8
|
||||
}
|
||||
if left >= 4 {
|
||||
c.mov_int_to_var(var, 0, offset: size - left, typ: ast.int_type_idx)
|
||||
left -= 4
|
||||
}
|
||||
if left >= 2 {
|
||||
c.mov_int_to_var(var, 0, offset: size - left, typ: ast.i16_type_idx)
|
||||
left -= 2
|
||||
}
|
||||
if left == 1 {
|
||||
c.mov_int_to_var(var, 0, offset: size - left, typ: ast.i8_type_idx)
|
||||
}
|
||||
// store exprs to the variable
|
||||
for i, expr in node.vals {
|
||||
offset := c.g.structs[typ.idx()].offsets[i]
|
||||
c.g.expr(expr)
|
||||
// TODO expr not on rax
|
||||
c.mov_reg_to_var(var, c.main_reg(),
|
||||
offset: offset
|
||||
typ: ts.mr_info().types[i]
|
||||
)
|
||||
}
|
||||
// store the multi return struct value
|
||||
c.lea_var_to_reg(c.main_reg(), var.offset)
|
||||
}
|
||||
|
||||
fn (mut c Amd64) assign_struct_var(ident_var IdentVar, typ ast.Type, s int) {
|
||||
// struct types bigger are passed around as a pointer in rax.
|
||||
// we need to dereference and copy the contents one after the other
|
||||
@ -1917,48 +1869,48 @@ fn (mut c Amd64) assign_struct_var(ident_var IdentVar, typ ast.Type, s int) {
|
||||
|
||||
mut offset := 0
|
||||
for size >= 8 {
|
||||
c.mov_deref(.rbx, .rax, ast.u64_type_idx)
|
||||
c.mov_deref(Amd64Register.rbx, Amd64Register.rax, ast.u64_type_idx)
|
||||
c.mov_reg_to_var(var, Amd64Register.rbx,
|
||||
offset: offset
|
||||
typ: ast.u64_type_idx
|
||||
)
|
||||
c.add(.rax, 8)
|
||||
c.add(Amd64Register.rax, 8)
|
||||
|
||||
size -= 8
|
||||
offset += 8
|
||||
}
|
||||
|
||||
if size >= 4 {
|
||||
c.mov_deref(.rbx, .rax, ast.u32_type_idx)
|
||||
c.mov_deref(Amd64Register.rbx, Amd64Register.rax, ast.u32_type_idx)
|
||||
c.mov_reg_to_var(var, Amd64Register.rbx,
|
||||
offset: offset
|
||||
typ: ast.u32_type_idx
|
||||
)
|
||||
c.add(.rax, 4)
|
||||
c.add(Amd64Register.rax, 4)
|
||||
|
||||
size -= 4
|
||||
offset += 4
|
||||
}
|
||||
|
||||
if size >= 2 {
|
||||
c.mov_deref(.rbx, .rax, ast.u16_type_idx)
|
||||
c.mov_deref(Amd64Register.rbx, Amd64Register.rax, ast.u16_type_idx)
|
||||
c.mov_reg_to_var(var, Amd64Register.rbx,
|
||||
offset: offset
|
||||
typ: ast.u16_type_idx
|
||||
)
|
||||
c.add(.rax, 2)
|
||||
c.add(Amd64Register.rax, 2)
|
||||
|
||||
size -= 2
|
||||
offset += 2
|
||||
}
|
||||
|
||||
if size == 1 {
|
||||
c.mov_deref(.rbx, .rax, ast.u8_type_idx)
|
||||
c.mov_deref(Amd64Register.rbx, Amd64Register.rax, ast.u8_type_idx)
|
||||
c.mov_reg_to_var(var, Amd64Register.rbx,
|
||||
offset: offset
|
||||
typ: ast.u8_type_idx
|
||||
)
|
||||
c.add(.rax, 1)
|
||||
c.add(Amd64Register.rax, 1)
|
||||
|
||||
size--
|
||||
offset++
|
||||
@ -1996,7 +1948,7 @@ fn (mut c Amd64) assign_int(node ast.AssignStmt, i int, name string, ident ast.I
|
||||
match node.op {
|
||||
.plus_assign {
|
||||
c.mov_var_to_reg(Amd64Register.rax, ident)
|
||||
c.add(.rax, int_lit.val.int())
|
||||
c.add(Amd64Register.rax, int_lit.val.int())
|
||||
c.mov_reg_to_var(ident, Amd64Register.rax)
|
||||
}
|
||||
.minus_assign {
|
||||
@ -2177,7 +2129,7 @@ fn (mut c Amd64) assign_right_expr(node ast.AssignStmt, i int, right ast.Expr, n
|
||||
c.lea_var_to_reg(Amd64Register.rax, dest)
|
||||
c.mov_var_to_reg(Amd64Register.rdi, ie_ident)
|
||||
c.add_reg(.rax, .rdi)
|
||||
c.mov_deref(.rax, .rax, ast.i64_type_idx)
|
||||
c.mov_deref(Amd64Register.rax, Amd64Register.rax, ast.i64_type_idx)
|
||||
} else {
|
||||
c.g.n_error('only integers and idents can be used as indexes')
|
||||
}
|
||||
@ -2287,16 +2239,16 @@ fn (mut c Amd64) return_stmt(node ast.Return) {
|
||||
match ts.kind {
|
||||
.struct_, .multi_return {
|
||||
if size <= 8 {
|
||||
c.mov_deref(.rax, .rax, ast.i64_type_idx)
|
||||
c.mov_deref(Amd64Register.rax, Amd64Register.rax, ast.i64_type_idx)
|
||||
if size != 8 {
|
||||
c.movabs(Amd64Register.rbx, i64((u64(1) << (size * 8)) - 1))
|
||||
c.bitand_reg(.rax, .rbx)
|
||||
}
|
||||
} else if size <= 16 {
|
||||
c.add(.rax, 8)
|
||||
c.mov_deref(.rdx, .rax, ast.i64_type_idx)
|
||||
c.add(Amd64Register.rax, 8)
|
||||
c.mov_deref(Amd64Register.rdx, Amd64Register.rax, ast.i64_type_idx)
|
||||
c.sub(.rax, 8)
|
||||
c.mov_deref(.rax, .rax, ast.i64_type_idx)
|
||||
c.mov_deref(Amd64Register.rax, Amd64Register.rax, ast.i64_type_idx)
|
||||
if size != 16 {
|
||||
c.movabs(Amd64Register.rbx, i64((u64(1) << ((size - 8) * 8)) - 1))
|
||||
c.bitand_reg(.rdx, .rbx)
|
||||
@ -2308,17 +2260,17 @@ fn (mut c Amd64) return_stmt(node ast.Return) {
|
||||
typ: ast.i64_type_idx
|
||||
})
|
||||
for i in 0 .. size / 8 {
|
||||
c.mov_deref(.rcx, .rax, ast.i64_type_idx)
|
||||
c.mov_deref(Amd64Register.rcx, Amd64Register.rax, ast.i64_type_idx)
|
||||
c.mov_store(.rdx, .rcx, ._64)
|
||||
if i != size / 8 - 1 {
|
||||
c.add(.rax, 8)
|
||||
c.add(.rdx, 8)
|
||||
c.add(Amd64Register.rax, 8)
|
||||
c.add(Amd64Register.rdx, 8)
|
||||
}
|
||||
}
|
||||
if size % 8 != 0 {
|
||||
c.add(.rax, size % 8)
|
||||
c.add(.rdx, size % 8)
|
||||
c.mov_deref(.rcx, .rax, ast.i64_type_idx)
|
||||
c.add(Amd64Register.rax, size % 8)
|
||||
c.add(Amd64Register.rdx, size % 8)
|
||||
c.mov_deref(Amd64Register.rcx, Amd64Register.rax, ast.i64_type_idx)
|
||||
c.mov_store(.rdx, .rcx, ._64)
|
||||
}
|
||||
c.mov_var_to_reg(c.main_reg(), LocalVar{
|
||||
@ -2340,32 +2292,9 @@ fn (mut c Amd64) return_stmt(node ast.Return) {
|
||||
offset: c.g.allocate_by_type('', typ)
|
||||
typ: typ
|
||||
}
|
||||
// zero fill
|
||||
mut left := if size >= 16 {
|
||||
c.mov(Amd64Register.rax, 0)
|
||||
c.mov(Amd64Register.rcx, size / 8)
|
||||
c.lea_var_to_reg(Amd64Register.rdi, var.offset)
|
||||
c.g.write([u8(0xf3), 0x48, 0xab])
|
||||
c.g.println('rep stosq')
|
||||
size % 8
|
||||
} else {
|
||||
size
|
||||
}
|
||||
if left >= 8 {
|
||||
c.mov_int_to_var(var, 0, offset: size - left, typ: ast.i64_type_idx)
|
||||
left -= 8
|
||||
}
|
||||
if left >= 4 {
|
||||
c.mov_int_to_var(var, 0, offset: size - left, typ: ast.int_type_idx)
|
||||
left -= 4
|
||||
}
|
||||
if left >= 2 {
|
||||
c.mov_int_to_var(var, 0, offset: size - left, typ: ast.i16_type_idx)
|
||||
left -= 2
|
||||
}
|
||||
if left == 1 {
|
||||
c.mov_int_to_var(var, 0, offset: size - left, typ: ast.i8_type_idx)
|
||||
}
|
||||
|
||||
c.zero_fill(size, var)
|
||||
|
||||
// store exprs to the variable
|
||||
for i, expr in node.exprs {
|
||||
offset := c.g.structs[typ.idx()].offsets[i]
|
||||
@ -2377,16 +2306,16 @@ fn (mut c Amd64) return_stmt(node ast.Return) {
|
||||
c.lea_var_to_reg(Amd64Register.rax, var.offset)
|
||||
if c.g.pref.arch == .amd64 {
|
||||
if size <= 8 {
|
||||
c.mov_deref(.rax, .rax, ast.i64_type_idx)
|
||||
c.mov_deref(Amd64Register.rax, Amd64Register.rax, ast.i64_type_idx)
|
||||
if size != 8 {
|
||||
c.movabs(Amd64Register.rbx, i64((u64(1) << (size * 8)) - 1))
|
||||
c.bitand_reg(.rax, .rbx)
|
||||
}
|
||||
} else if size <= 16 {
|
||||
c.add(.rax, 8)
|
||||
c.mov_deref(.rdx, .rax, ast.i64_type_idx)
|
||||
c.sub(.rax, 8)
|
||||
c.mov_deref(.rax, .rax, ast.i64_type_idx)
|
||||
c.add(Amd64Register.rax, 8)
|
||||
c.mov_deref(Amd64Register.rdx, Amd64Register.rax, ast.i64_type_idx)
|
||||
c.sub(Amd64Register.rax, 8)
|
||||
c.mov_deref(Amd64Register.rax, Amd64Register.rax, ast.i64_type_idx)
|
||||
if size != 16 {
|
||||
c.movabs(Amd64Register.rbx, i64((u64(1) << ((size - 8) * 8)) - 1))
|
||||
c.bitand_reg(.rdx, .rbx)
|
||||
@ -2398,17 +2327,17 @@ fn (mut c Amd64) return_stmt(node ast.Return) {
|
||||
typ: ast.i64_type_idx
|
||||
})
|
||||
for i in 0 .. size / 8 {
|
||||
c.mov_deref(.rcx, .rax, ast.i64_type_idx)
|
||||
c.mov_deref(Amd64Register.rcx, Amd64Register.rax, ast.i64_type_idx)
|
||||
c.mov_store(.rdx, .rcx, ._64)
|
||||
if i != size / 8 - 1 {
|
||||
c.add(.rax, 8)
|
||||
c.add(.rdx, 8)
|
||||
c.add(Amd64Register.rax, 8)
|
||||
c.add(Amd64Register.rdx, 8)
|
||||
}
|
||||
}
|
||||
if size % 8 != 0 {
|
||||
c.add(.rax, size % 8)
|
||||
c.add(.rdx, size % 8)
|
||||
c.mov_deref(.rcx, .rax, ast.i64_type_idx)
|
||||
c.add(Amd64Register.rax, size % 8)
|
||||
c.add(Amd64Register.rdx, size % 8)
|
||||
c.mov_deref(Amd64Register.rcx, Amd64Register.rax, ast.i64_type_idx)
|
||||
c.mov_store(.rdx, .rcx, ._64)
|
||||
}
|
||||
c.mov_var_to_reg(c.main_reg(), LocalVar{
|
||||
@ -2441,32 +2370,9 @@ fn (mut c Amd64) multi_assign_stmt(node ast.AssignStmt) {
|
||||
var := LocalVar{
|
||||
offset: c.g.stack_var_pos
|
||||
}
|
||||
// zero fill
|
||||
mut left := if size >= 16 {
|
||||
c.mov(Amd64Register.rax, 0)
|
||||
c.mov(Amd64Register.rcx, size / 8)
|
||||
c.lea_var_to_reg(Amd64Register.rdi, var.offset)
|
||||
c.g.write([u8(0xf3), 0x48, 0xab])
|
||||
c.g.println('rep stosq')
|
||||
size % 8
|
||||
} else {
|
||||
size
|
||||
}
|
||||
if left >= 8 {
|
||||
c.mov_int_to_var(var, 0, offset: size - left, typ: ast.i64_type_idx)
|
||||
left -= 8
|
||||
}
|
||||
if left >= 4 {
|
||||
c.mov_int_to_var(var, 0, offset: size - left, typ: ast.int_type_idx)
|
||||
left -= 4
|
||||
}
|
||||
if left >= 2 {
|
||||
c.mov_int_to_var(var, 0, offset: size - left, typ: ast.i16_type_idx)
|
||||
left -= 2
|
||||
}
|
||||
if left == 1 {
|
||||
c.mov_int_to_var(var, 0, offset: size - left, typ: ast.i8_type_idx)
|
||||
}
|
||||
|
||||
c.zero_fill(size, var)
|
||||
|
||||
// store exprs to the variable
|
||||
for i, expr in node.right {
|
||||
offset := multi_return.offsets[i]
|
||||
@ -2493,14 +2399,14 @@ fn (mut c Amd64) multi_assign_stmt(node ast.AssignStmt) {
|
||||
}
|
||||
}
|
||||
if offset != current_offset {
|
||||
c.add(.rdx, offset - current_offset)
|
||||
c.add(Amd64Register.rdx, offset - current_offset)
|
||||
current_offset = offset
|
||||
}
|
||||
c.gen_left_value(node.left[i])
|
||||
c.g.gen_left_value(node.left[i])
|
||||
left_type := node.left_types[i]
|
||||
right_type := node.right_types[i]
|
||||
if c.g.is_register_type(right_type) {
|
||||
c.mov_deref(.rcx, .rdx, right_type)
|
||||
c.mov_deref(Amd64Register.rcx, Amd64Register.rdx, right_type)
|
||||
} else if node.right_types[i].is_pure_float() {
|
||||
c.mov_deref_sse(.xmm0, .rdx, right_type)
|
||||
}
|
||||
@ -2580,7 +2486,7 @@ fn (mut c Amd64) assign_stmt(node ast.AssignStmt) {
|
||||
if left is ast.Ident && node.op == .decl_assign {
|
||||
c.g.allocate_by_type((left as ast.Ident).name, typ)
|
||||
}
|
||||
c.gen_left_value(left)
|
||||
c.g.gen_left_value(left)
|
||||
c.push(Amd64Register.rax)
|
||||
c.g.expr(right)
|
||||
c.pop(.rdx)
|
||||
@ -2643,43 +2549,43 @@ fn (mut c Amd64) assign_stmt(node ast.AssignStmt) {
|
||||
size := c.g.get_type_size(typ)
|
||||
if size >= 8 {
|
||||
for j in 0 .. size / 8 {
|
||||
c.mov_deref(.rcx, .rdx, ast.u64_type_idx)
|
||||
c.mov_deref(Amd64Register.rcx, Amd64Register.rdx, ast.u64_type_idx)
|
||||
c.mov_store(.rax, .rcx, ._64)
|
||||
offset := if j == size / 8 - 1 && size % 8 != 0 {
|
||||
size % 8
|
||||
} else {
|
||||
8
|
||||
}
|
||||
c.add(.rax, offset)
|
||||
c.add(.rdx, offset)
|
||||
c.add(Amd64Register.rax, offset)
|
||||
c.add(Amd64Register.rdx, offset)
|
||||
}
|
||||
if size % 8 != 0 {
|
||||
c.mov_deref(.rcx, .rdx, ast.u64_type_idx)
|
||||
c.mov_deref(Amd64Register.rcx, Amd64Register.rdx, ast.u64_type_idx)
|
||||
c.mov_store(.rax, .rcx, ._64)
|
||||
}
|
||||
} else {
|
||||
mut left_size := if size >= 4 {
|
||||
c.mov_deref(.rcx, .rdx, ast.u32_type_idx)
|
||||
c.mov_deref(Amd64Register.rcx, Amd64Register.rdx, ast.u32_type_idx)
|
||||
c.mov_store(.rax, .rcx, ._32)
|
||||
if size > 4 {
|
||||
c.add(.rax, 4)
|
||||
c.add(.rdx, 4)
|
||||
c.add(Amd64Register.rax, 4)
|
||||
c.add(Amd64Register.rdx, 4)
|
||||
}
|
||||
size - 4
|
||||
} else {
|
||||
size
|
||||
}
|
||||
if left_size >= 2 {
|
||||
c.mov_deref(.rcx, .rdx, ast.u16_type_idx)
|
||||
c.mov_deref(Amd64Register.rcx, Amd64Register.rdx, ast.u16_type_idx)
|
||||
c.mov_store(.rax, .rcx, ._16)
|
||||
if left_size > 2 {
|
||||
c.add(.rax, 2)
|
||||
c.add(.rdx, 2)
|
||||
c.add(Amd64Register.rax, 2)
|
||||
c.add(Amd64Register.rdx, 2)
|
||||
}
|
||||
left_size -= 2
|
||||
}
|
||||
if left_size == 1 {
|
||||
c.mov_deref(.rcx, .rdx, ast.u8_type_idx)
|
||||
c.mov_deref(Amd64Register.rcx, Amd64Register.rdx, ast.u8_type_idx)
|
||||
c.mov_store(.rax, .rcx, ._8)
|
||||
}
|
||||
}
|
||||
@ -2719,35 +2625,6 @@ fn (mut c Amd64) cset_op(op token.Kind) {
|
||||
}
|
||||
}
|
||||
|
||||
fn (mut c Amd64) gen_left_value(node ast.Expr) {
|
||||
match node {
|
||||
ast.Ident {
|
||||
offset := c.g.get_var_offset(node.name)
|
||||
c.lea_var_to_reg(Amd64Register.rax, offset)
|
||||
}
|
||||
ast.SelectorExpr {
|
||||
c.g.expr(node.expr)
|
||||
offset := c.g.get_field_offset(node.expr_type, node.field_name)
|
||||
if offset != 0 {
|
||||
c.add(.rax, offset)
|
||||
}
|
||||
}
|
||||
ast.StructInit, ast.ArrayInit {
|
||||
c.g.expr(node)
|
||||
}
|
||||
ast.IndexExpr {} // TODO
|
||||
ast.PrefixExpr {
|
||||
if node.op != .mul {
|
||||
c.g.n_error('Unsupported left value')
|
||||
}
|
||||
c.g.expr(node.right)
|
||||
}
|
||||
else {
|
||||
c.g.n_error('Unsupported left value')
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn (mut c Amd64) prefix_expr(node ast.PrefixExpr) {
|
||||
match node.op {
|
||||
.minus {
|
||||
@ -2766,11 +2643,11 @@ fn (mut c Amd64) prefix_expr(node ast.PrefixExpr) {
|
||||
}
|
||||
}
|
||||
.amp {
|
||||
c.gen_left_value(node.right)
|
||||
c.g.gen_left_value(node.right)
|
||||
}
|
||||
.mul {
|
||||
c.g.expr(node.right)
|
||||
c.mov_deref(.rax, .rax, node.right_type.deref())
|
||||
c.mov_deref(Amd64Register.rax, Amd64Register.rax, node.right_type.deref())
|
||||
}
|
||||
.not {
|
||||
c.g.expr(node.right)
|
||||
@ -3072,29 +2949,6 @@ fn (mut c Amd64) gen_asm_stmt(asm_node ast.AsmStmt) {
|
||||
}
|
||||
}
|
||||
|
||||
fn (mut c Amd64) gen_selector_expr(expr ast.SelectorExpr) {
|
||||
c.g.expr(expr.expr)
|
||||
offset := c.g.get_field_offset(expr.expr_type, expr.field_name)
|
||||
c.add(.rax, offset)
|
||||
c.mov_deref(.rax, .rax, expr.typ)
|
||||
}
|
||||
|
||||
fn (mut c Amd64) gen_assert(assert_node ast.AssertStmt) {
|
||||
mut cjmp_addr := 0
|
||||
ane := assert_node.expr
|
||||
label := c.g.labels.new_label()
|
||||
cjmp_addr = c.g.condition(ane, true)
|
||||
c.g.labels.patches << LabelPatch{
|
||||
id: label
|
||||
pos: cjmp_addr
|
||||
}
|
||||
c.g.println('; jump to label ${label}')
|
||||
c.g.expr(assert_node.expr)
|
||||
c.trap()
|
||||
c.g.labels.addrs[label] = c.g.pos()
|
||||
c.g.println('; label ${label}')
|
||||
}
|
||||
|
||||
fn (mut c Amd64) cjmp_notop(op token.Kind) int {
|
||||
return match op {
|
||||
.gt {
|
||||
@ -3345,6 +3199,34 @@ pub fn (mut c Amd64) allocate_var(name string, size int, initial_val int) int {
|
||||
return c.g.stack_var_pos
|
||||
}
|
||||
|
||||
fn (mut c Amd64) zero_fill(size int, var LocalVar) {
|
||||
mut left := if size >= 16 {
|
||||
c.mov(Amd64Register.rax, 0)
|
||||
c.mov(Amd64Register.rcx, size / 8)
|
||||
c.lea_var_to_reg(Amd64Register.rdi, var.offset)
|
||||
c.g.write([u8(0xf3), 0x48, 0xab])
|
||||
c.g.println('rep stosq')
|
||||
size % 8
|
||||
} else {
|
||||
size
|
||||
}
|
||||
if left >= 8 {
|
||||
c.mov_int_to_var(var, 0, offset: size - left, typ: ast.i64_type_idx)
|
||||
left -= 8
|
||||
}
|
||||
if left >= 4 {
|
||||
c.mov_int_to_var(var, 0, offset: size - left, typ: ast.int_type_idx)
|
||||
left -= 4
|
||||
}
|
||||
if left >= 2 {
|
||||
c.mov_int_to_var(var, 0, offset: size - left, typ: ast.i16_type_idx)
|
||||
left -= 2
|
||||
}
|
||||
if left == 1 {
|
||||
c.mov_int_to_var(var, 0, offset: size - left, typ: ast.i8_type_idx)
|
||||
}
|
||||
}
|
||||
|
||||
fn (mut c Amd64) init_struct(var Var, init ast.StructInit) {
|
||||
match var {
|
||||
ast.Ident {
|
||||
@ -3366,32 +3248,7 @@ fn (mut c Amd64) init_struct(var Var, init ast.StructInit) {
|
||||
typ := c.g.unwrap(var.typ)
|
||||
size := c.g.get_type_size(typ)
|
||||
|
||||
// zero fill
|
||||
mut left := if size >= 16 {
|
||||
c.mov(Amd64Register.rax, 0)
|
||||
c.mov(Amd64Register.rcx, size / 8)
|
||||
c.lea_var_to_reg(Amd64Register.rdi, var.offset)
|
||||
c.g.write([u8(0xf3), 0x48, 0xab])
|
||||
c.g.println('rep stosq')
|
||||
size % 8
|
||||
} else {
|
||||
size
|
||||
}
|
||||
if left >= 8 {
|
||||
c.mov_int_to_var(var, 0, offset: size - left, typ: ast.i64_type_idx)
|
||||
left -= 8
|
||||
}
|
||||
if left >= 4 {
|
||||
c.mov_int_to_var(var, 0, offset: size - left, typ: ast.int_type_idx)
|
||||
left -= 4
|
||||
}
|
||||
if left >= 2 {
|
||||
c.mov_int_to_var(var, 0, offset: size - left, typ: ast.i16_type_idx)
|
||||
left -= 2
|
||||
}
|
||||
if left == 1 {
|
||||
c.mov_int_to_var(var, 0, offset: size - left, typ: ast.i8_type_idx)
|
||||
}
|
||||
c.zero_fill(size, var)
|
||||
|
||||
ts := c.g.table.sym(typ)
|
||||
match ts.info {
|
||||
@ -3506,11 +3363,11 @@ fn (mut c Amd64) convert_int_to_string(a Register, b Register) {
|
||||
r2 := b as Amd64Register
|
||||
|
||||
if r1 != .rax {
|
||||
c.mov_reg_amd64(.rax, r1)
|
||||
c.mov_reg(Amd64Register.rax, r1)
|
||||
}
|
||||
|
||||
if r2 != .rdi {
|
||||
c.mov_reg_amd64(.rdi, r2)
|
||||
c.mov_reg(Amd64Register.rdi, r2)
|
||||
}
|
||||
|
||||
// check if value in rax is zero
|
||||
@ -3566,7 +3423,7 @@ fn (mut c Amd64) convert_int_to_string(a Register, b Register) {
|
||||
c.g.labels.addrs[skip_minus_label] = c.g.pos()
|
||||
c.g.println('; label ${skip_minus_label}')
|
||||
|
||||
c.mov_reg_amd64(.r12, .rdi) // copy the buffer position to r12
|
||||
c.mov_reg(Amd64Register.r12, Amd64Register.rdi) // copy the buffer position to r12
|
||||
|
||||
loop_label := c.g.labels.new_label()
|
||||
loop_start := c.g.pos()
|
||||
@ -3608,7 +3465,7 @@ fn (mut c Amd64) convert_int_to_string(a Register, b Register) {
|
||||
|
||||
// after all was converted, reverse the string
|
||||
reg := c.g.get_builtin_arg_reg(.reverse_string, 0) as Amd64Register
|
||||
c.mov_reg_amd64(reg, .r12)
|
||||
c.mov_reg(reg, Amd64Register.r12)
|
||||
c.g.call_builtin(.reverse_string)
|
||||
|
||||
c.g.labels.addrs[end_label] = c.g.pos()
|
||||
@ -3619,7 +3476,7 @@ fn (mut c Amd64) reverse_string(r Register) {
|
||||
reg := r as Amd64Register
|
||||
|
||||
if reg != .rdi {
|
||||
c.mov_reg_amd64(.rdi, reg)
|
||||
c.mov_reg(Amd64Register.rdi, reg)
|
||||
}
|
||||
|
||||
c.mov(Amd64Register.eax, 0)
|
||||
@ -3630,7 +3487,7 @@ fn (mut c Amd64) reverse_string(r Register) {
|
||||
c.g.write8(0xff)
|
||||
c.g.println('lea rcx, [rax-0x1]')
|
||||
|
||||
c.mov_reg_amd64(.rsi, .rdi)
|
||||
c.mov_reg(Amd64Register.rsi, Amd64Register.rdi)
|
||||
|
||||
c.g.write8(0xf2)
|
||||
c.g.write8(0xae)
|
||||
|
@ -430,10 +430,6 @@ fn (mut c Arm64) gen_asm_stmt(asm_node ast.AsmStmt) {
|
||||
panic('Arm64.gen_asm_stmt() not implemented')
|
||||
}
|
||||
|
||||
fn (mut c Arm64) gen_assert(assert_node ast.AssertStmt) {
|
||||
panic('Arm64.gen_assert() not implemented')
|
||||
}
|
||||
|
||||
fn (mut c Arm64) infloop() {
|
||||
c.g.write32(u8(0x14))
|
||||
c.g.println('jmp $$')
|
||||
@ -515,12 +511,12 @@ fn (mut c Arm64) call(addr int) i64 {
|
||||
panic('Arm64.call() not implemented')
|
||||
}
|
||||
|
||||
fn (mut c Arm64) call_addr_at(addr int, at i64) i64 {
|
||||
panic('Arm64.call_addr_at() not implemented')
|
||||
fn (mut c Arm64) zero_fill(size int, var LocalVar) {
|
||||
panic('Arm64.zero_fill() not implemented')
|
||||
}
|
||||
|
||||
fn (mut c Arm64) gen_concat_expr(expr ast.ConcatExpr) {
|
||||
panic('Arm64.gen_concat_expr() not implemented')
|
||||
fn (mut c Arm64) call_addr_at(addr int, at i64) i64 {
|
||||
panic('Arm64.call_addr_at() not implemented')
|
||||
}
|
||||
|
||||
fn (mut c Arm64) cmp_to_stack_top(reg Register) {
|
||||
@ -530,3 +526,11 @@ fn (mut c Arm64) cmp_to_stack_top(reg Register) {
|
||||
fn (mut c Arm64) push(r Register) {
|
||||
panic('Arm64.push() not implemented')
|
||||
}
|
||||
|
||||
pub fn (mut c Arm64) add(r Register, val int) {
|
||||
panic('Arm64.add() not implemented')
|
||||
}
|
||||
|
||||
fn (mut c Arm64) mov_deref(reg Register, regptr Register, typ ast.Type) {
|
||||
panic('Arm64.mov_deref() not implemented')
|
||||
}
|
||||
|
@ -98,7 +98,7 @@ fn (mut g Gen) expr(node ast.Expr) {
|
||||
g.code_gen.gen_match_expr(node)
|
||||
}
|
||||
ast.SelectorExpr {
|
||||
g.code_gen.gen_selector_expr(node)
|
||||
g.gen_selector_expr(node)
|
||||
}
|
||||
ast.CastExpr {
|
||||
g.code_gen.gen_cast_expr(node)
|
||||
@ -111,7 +111,7 @@ fn (mut g Gen) expr(node ast.Expr) {
|
||||
g.expr(node.expr)
|
||||
}
|
||||
ast.ConcatExpr {
|
||||
g.code_gen.gen_concat_expr(node)
|
||||
g.gen_concat_expr(node)
|
||||
}
|
||||
ast.TypeOf {
|
||||
g.gen_typeof_expr(node, false)
|
||||
@ -420,3 +420,40 @@ fn (mut g Gen) gen_print_from_expr(expr ast.Expr, typ ast.Type, name string) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn (mut g Gen) gen_selector_expr(expr ast.SelectorExpr) {
|
||||
main_reg := g.code_gen.main_reg()
|
||||
g.expr(expr.expr)
|
||||
offset := g.get_field_offset(expr.expr_type, expr.field_name)
|
||||
g.code_gen.add(main_reg, offset)
|
||||
g.code_gen.mov_deref(main_reg, main_reg, expr.typ)
|
||||
}
|
||||
|
||||
fn (mut g Gen) gen_left_value(node ast.Expr) {
|
||||
match node {
|
||||
ast.Ident {
|
||||
offset := g.get_var_offset(node.name)
|
||||
g.code_gen.lea_var_to_reg(Amd64Register.rax, offset)
|
||||
}
|
||||
ast.SelectorExpr {
|
||||
g.expr(node.expr)
|
||||
offset := g.get_field_offset(node.expr_type, node.field_name)
|
||||
if offset != 0 {
|
||||
g.code_gen.add(Amd64Register.rax, offset)
|
||||
}
|
||||
}
|
||||
ast.StructInit, ast.ArrayInit {
|
||||
g.expr(node)
|
||||
}
|
||||
ast.IndexExpr {} // TODO
|
||||
ast.PrefixExpr {
|
||||
if node.op != .mul {
|
||||
g.n_error('Unsupported left value')
|
||||
}
|
||||
g.expr(node.right)
|
||||
}
|
||||
else {
|
||||
g.n_error('Unsupported left value')
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -67,6 +67,7 @@ mut:
|
||||
interface CodeGen {
|
||||
mut:
|
||||
g &Gen
|
||||
add(r Register, val int)
|
||||
address_size() int
|
||||
adr(r Arm64Register, delta int) // Note: Temporary!
|
||||
allocate_var(name string, size int, initial_val int) int
|
||||
@ -88,14 +89,11 @@ mut:
|
||||
dec_var(var Var, config VarConfig)
|
||||
fn_decl(node ast.FnDecl)
|
||||
gen_asm_stmt(asm_node ast.AsmStmt)
|
||||
gen_assert(assert_node ast.AssertStmt)
|
||||
gen_cast_expr(expr ast.CastExpr)
|
||||
gen_concat_expr(expr ast.ConcatExpr)
|
||||
gen_exit(expr ast.Expr)
|
||||
gen_match_expr(expr ast.MatchExpr)
|
||||
gen_print_reg(r Register, n int, fd int)
|
||||
gen_print(s string, fd int)
|
||||
gen_selector_expr(expr ast.SelectorExpr)
|
||||
gen_syscall(node ast.CallExpr)
|
||||
inc_var(var Var, config VarConfig)
|
||||
infix_expr(node ast.InfixExpr) // TODO: make platform-independant
|
||||
@ -110,6 +108,7 @@ mut:
|
||||
load_fp_var(var Var, config VarConfig)
|
||||
load_fp(val f64)
|
||||
main_reg() Register
|
||||
mov_deref(reg Register, regptr Register, typ ast.Type)
|
||||
mov_int_to_var(var Var, integer int, config VarConfig)
|
||||
mov_reg_to_var(var Var, reg Register, config VarConfig)
|
||||
mov_reg(r1 Register, r2 Register)
|
||||
@ -125,6 +124,7 @@ mut:
|
||||
svc()
|
||||
syscall() // unix syscalls
|
||||
trap()
|
||||
zero_fill(size int, var LocalVar)
|
||||
}
|
||||
|
||||
type Register = Amd64Register | Arm64Register
|
||||
@ -1083,3 +1083,29 @@ pub fn (mut g Gen) v_error(s string, pos token.Pos) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn (mut g Gen) gen_concat_expr(node ast.ConcatExpr) {
|
||||
typ := node.return_type
|
||||
ts := g.table.sym(typ)
|
||||
size := g.get_type_size(typ)
|
||||
// construct a struct variable contains the return value
|
||||
var := LocalVar{
|
||||
offset: g.allocate_by_type('', typ)
|
||||
typ: typ
|
||||
}
|
||||
|
||||
g.code_gen.zero_fill(size, var)
|
||||
main_reg := g.code_gen.main_reg()
|
||||
// store exprs to the variable
|
||||
for i, expr in node.vals {
|
||||
offset := g.structs[typ.idx()].offsets[i]
|
||||
g.expr(expr)
|
||||
// TODO expr not on rax
|
||||
g.code_gen.mov_reg_to_var(var, main_reg,
|
||||
offset: offset
|
||||
typ: ts.mr_info().types[i]
|
||||
)
|
||||
}
|
||||
// store the multi return struct value
|
||||
g.code_gen.lea_var_to_reg(main_reg, var.offset)
|
||||
}
|
||||
|
@ -95,7 +95,7 @@ fn (mut g Gen) stmt(node ast.Stmt) {
|
||||
g.code_gen.gen_asm_stmt(node)
|
||||
}
|
||||
ast.AssertStmt {
|
||||
g.code_gen.gen_assert(node)
|
||||
g.gen_assert(node)
|
||||
}
|
||||
ast.GlobalDecl {
|
||||
g.warning('globals are not supported yet', node.pos)
|
||||
@ -323,3 +323,19 @@ fn (mut g Gen) for_in_stmt(node ast.ForInStmt) { // Work on that
|
||||
g.v_error('for-in statement is not yet implemented', node.pos)
|
||||
}
|
||||
}
|
||||
|
||||
fn (mut g Gen) gen_assert(assert_node ast.AssertStmt) {
|
||||
mut cjmp_addr := 0
|
||||
ane := assert_node.expr
|
||||
label := g.labels.new_label()
|
||||
cjmp_addr = g.condition(ane, true)
|
||||
g.labels.patches << LabelPatch{
|
||||
id: label
|
||||
pos: cjmp_addr
|
||||
}
|
||||
g.println('; jump to label ${label}')
|
||||
g.expr(assert_node.expr)
|
||||
g.code_gen.trap()
|
||||
g.labels.addrs[label] = g.pos()
|
||||
g.println('; label ${label}')
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user