mirror of
https://github.com/vlang/v.git
synced 2025-09-13 22:42:26 +03:00
Merge 90a1acb244
into c221b3226b
This commit is contained in:
commit
374c6ab467
11 changed files with 213 additions and 60 deletions
|
@ -486,7 +486,9 @@ pub fn malloc_noscan(n isize) &u8 {
|
|||
_memory_panic(@FN, n)
|
||||
}
|
||||
mut res := &u8(unsafe { nil })
|
||||
$if prealloc {
|
||||
$if native {
|
||||
res = unsafe { C.malloc(n) }
|
||||
} $else $if prealloc {
|
||||
return unsafe { prealloc_malloc(n) }
|
||||
} $else $if gcboehm ? {
|
||||
$if gcboehm_opt ? {
|
||||
|
|
|
@ -1798,6 +1798,10 @@ fn (mut c Amd64) mov(r Register, val i32) {
|
|||
}
|
||||
}
|
||||
|
||||
fn (mut c Amd64) mul_reg_main(b Register) {
|
||||
c.mul_reg_rax(b as Amd64Register)
|
||||
}
|
||||
|
||||
// rax times b
|
||||
fn (mut c Amd64) mul_reg_rax(b Amd64Register) {
|
||||
match b {
|
||||
|
@ -2510,8 +2514,42 @@ fn (mut c Amd64) assign_ident_right_expr(node ast.AssignStmt, i i32, right ast.E
|
|||
ast.ArrayInit {
|
||||
match node.op {
|
||||
.decl_assign {
|
||||
c.g.allocate_by_type(name, right.typ)
|
||||
c.init_array(ident, right)
|
||||
c.g.allocate_by_type(ident.name, ast.array_type)
|
||||
len := ast.CallArg{
|
||||
expr: if right.has_len {
|
||||
right.len_expr
|
||||
} else {
|
||||
ast.IntegerLiteral{'0', right.pos}
|
||||
}
|
||||
typ: ast.int_type
|
||||
pos: right.pos
|
||||
}
|
||||
cap := ast.CallArg{
|
||||
expr: if right.has_cap {
|
||||
right.cap_expr
|
||||
} else {
|
||||
ast.IntegerLiteral{'0', right.pos}
|
||||
}
|
||||
typ: ast.int_type
|
||||
pos: right.pos
|
||||
}
|
||||
size := ast.CallArg{
|
||||
expr: ast.IntegerLiteral{c.g.get_type_size(right.elem_type).str(), right.pos}
|
||||
typ: ast.int_type
|
||||
pos: right.pos
|
||||
}
|
||||
c.call_fn(ast.CallExpr{
|
||||
pos: right.pos
|
||||
name: '__new_array'
|
||||
args: [len, cap, size]
|
||||
expected_arg_types: [ast.int_type, ast.int_type, ast.int_type]
|
||||
language: .v
|
||||
return_type: ast.array_type
|
||||
nr_ret_values: 1
|
||||
is_return_used: true
|
||||
})
|
||||
c.lea_var_to_reg(Amd64Register.rdx, c.g.get_var_offset(ident.name))
|
||||
c.move_struct(.rax, .rdx, c.g.get_type_size(ast.array_type))
|
||||
}
|
||||
else {
|
||||
c.g.n_error('${@LOCATION} Unexpected operator `${node.op}`')
|
||||
|
@ -2673,6 +2711,42 @@ fn (mut c Amd64) assign_ident_right_expr(node ast.AssignStmt, i i32, right ast.E
|
|||
}*/
|
||||
}
|
||||
|
||||
fn (mut c Amd64) gen_index_expr(node ast.IndexExpr) {
|
||||
if node.left_type.is_string() {
|
||||
c.g.expr(node.index)
|
||||
c.push(Amd64Register.rax)
|
||||
|
||||
c.g.expr(node.left) // load address of string struct
|
||||
c.mov_deref(Amd64Register.rax, Amd64Register.rax, ast.u64_type_idx) // load value of the str pointer
|
||||
|
||||
c.pop2(Amd64Register.rdx) // index
|
||||
c.add_reg2(Amd64Register.rax, Amd64Register.rdx) // add the offset to the address
|
||||
} else if node.left_type.is_any_kind_of_pointer() {
|
||||
// load the pointer
|
||||
c.g.expr(node.left)
|
||||
c.mov_reg(Amd64Register.rcx, Amd64Register.rax)
|
||||
// add the index times the size (bytes) of the type
|
||||
c.g.expr(node.index)
|
||||
c.mov(Amd64Register.rbx, i32(c.g.get_type_size(node.typ)))
|
||||
c.mul_reg_main(Amd64Register.rbx)
|
||||
c.add_reg2(Amd64Register.rax, Amd64Register.rcx)
|
||||
} else if node.is_array {
|
||||
c.g.expr(node.left)
|
||||
offset := c.g.get_field_offset(ast.array_type, 'data')
|
||||
if offset != 0 {
|
||||
c.add(Amd64Register.rax, offset)
|
||||
}
|
||||
c.mov_reg(Amd64Register.rcx, Amd64Register.rax)
|
||||
// add the index times the size (bytes) of the type
|
||||
c.g.expr(node.index)
|
||||
c.mov(Amd64Register.rbx, i32(c.g.get_type_size(node.typ)))
|
||||
c.mul_reg_main(Amd64Register.rbx)
|
||||
c.add_reg2(Amd64Register.rax, Amd64Register.rcx)
|
||||
} else {
|
||||
c.g.n_error('${@LOCATION} index expr: unhandled node type {node}')
|
||||
}
|
||||
}
|
||||
|
||||
// /!\ for div, mul, mod the left value should always be .rax
|
||||
fn (mut c Amd64) apply_op_int(left_value Amd64Register, right_value Amd64Register, op token.Kind) {
|
||||
match op {
|
||||
|
@ -3109,7 +3183,6 @@ fn (mut c Amd64) assign_stmt(node ast.AssignStmt) {
|
|||
c.push(c.main_reg())
|
||||
c.g.gen_left_value(left)
|
||||
c.mov_reg(Amd64Register.rbx, Amd64Register.rax) // effective address of the left expr
|
||||
c.mov_deref(Amd64Register.rax, Amd64Register.rbx, var_type) // value of left expr
|
||||
c.pop(.rcx) // value of right expr
|
||||
c.gen_type_promotion(node.right_types[0], var_type)
|
||||
|
||||
|
@ -3124,14 +3197,17 @@ fn (mut c Amd64) assign_stmt(node ast.AssignStmt) {
|
|||
c.mov_store(.rbx, .rcx, size)
|
||||
}
|
||||
.boolean_and_assign {
|
||||
c.mov_deref(Amd64Register.rax, Amd64Register.rbx, var_type) // value of left expr
|
||||
c.bitand_reg(.rax, .rcx)
|
||||
c.mov_store(.rbx, .rax, size)
|
||||
}
|
||||
.boolean_or_assign {
|
||||
c.mov_deref(Amd64Register.rax, Amd64Register.rbx, var_type) // value of left expr
|
||||
c.bitor_reg(.rax, .rcx)
|
||||
c.mov_store(.rbx, .rax, size)
|
||||
}
|
||||
else {
|
||||
c.mov_deref(Amd64Register.rax, Amd64Register.rbx, var_type) // value of left expr
|
||||
c.apply_op_int(.rax, .rcx, node.op)
|
||||
c.mov_store(.rbx, .rax, size)
|
||||
}
|
||||
|
|
|
@ -554,3 +554,11 @@ fn (mut c Arm64) mov_deref(reg Register, regptr Register, typ ast.Type) {
|
|||
fn (mut c Arm64) patch_relative_jmp(pos i32, addr i64) {
|
||||
panic('Arm64.patch_relative_jmp() not implemented')
|
||||
}
|
||||
|
||||
fn (mut c Arm64) mul_reg_main(b Register) {
|
||||
panic('Arm64.mul_reg_main() not implemented')
|
||||
}
|
||||
|
||||
fn (mut c Arm64) gen_index_expr(node ast.IndexExpr) {
|
||||
panic('Arm64.gen_index_expr{) not implemented')
|
||||
}
|
||||
|
|
|
@ -29,45 +29,53 @@ already compiling functions:
|
|||
// false: whitelist function
|
||||
// true: blacklist function
|
||||
const blacklist = {
|
||||
'main.main': false
|
||||
'c_error_number_str': false
|
||||
'exit': false
|
||||
'gc_is_enabled': false
|
||||
'int_max': false
|
||||
'int_min': false
|
||||
'flush_stdout': false
|
||||
'flush_stderr': false
|
||||
'print_character': false
|
||||
'u8.is_alnum': false
|
||||
'u8.is_bin_digit': false
|
||||
'u8.is_capital': false
|
||||
'u8.is_digit': false
|
||||
'u8.is_hex_digit': false
|
||||
'u8.is_letter': false
|
||||
'u8.is_oct_digit': false
|
||||
'u8.is_space': false
|
||||
'string.is_capital': false
|
||||
'string.is_ascii': false
|
||||
'string.is_identifier': false
|
||||
'string.is_blank': false
|
||||
'string.indent_width': false
|
||||
'string.index_u8': false
|
||||
'string.last_index': true
|
||||
'string.last_index_u8': false
|
||||
'string.contains_u8': false
|
||||
'malloc_noscan': false
|
||||
'malloc': false
|
||||
'is_nil': false
|
||||
'memdup': false
|
||||
'vcalloc': false
|
||||
'vmemcpy': false
|
||||
'eprint': false
|
||||
'eprintln': false
|
||||
'_write_buf_to_fd': false
|
||||
'_writeln_to_fd': false
|
||||
'_memory_panic': false
|
||||
'panic': false
|
||||
'vcurrent_hash': false
|
||||
'main.main': false
|
||||
'c_error_number_str': false
|
||||
'exit': false
|
||||
'gc_is_enabled': false
|
||||
'int_max': false
|
||||
'int_min': false
|
||||
'flush_stdout': false
|
||||
'flush_stderr': false
|
||||
'print_character': false
|
||||
'u8.is_alnum': false
|
||||
'u8.is_bin_digit': false
|
||||
'u8.is_capital': false
|
||||
'u8.is_digit': false
|
||||
'u8.is_hex_digit': false
|
||||
'u8.is_letter': false
|
||||
'u8.is_oct_digit': false
|
||||
'u8.is_space': false
|
||||
'string.is_capital': false
|
||||
'string.is_ascii': false
|
||||
'string.is_identifier': false
|
||||
'string.is_blank': false
|
||||
'string.indent_width': false
|
||||
'string.index_u8': false
|
||||
'string.last_index': true
|
||||
'string.last_index_u8': false
|
||||
'string.contains_u8': false
|
||||
'malloc_noscan': false
|
||||
'malloc': false
|
||||
'is_nil': false
|
||||
'memdup': false
|
||||
'vcalloc': false
|
||||
'vmemcpy': false
|
||||
'eprint': false
|
||||
'eprintln': false
|
||||
'_write_buf_to_fd': false
|
||||
'_writeln_to_fd': false
|
||||
'_memory_panic': false
|
||||
'panic': false
|
||||
'vcurrent_hash': false
|
||||
'__new_array': false
|
||||
'panic_on_negative_len': false
|
||||
'panic_on_negative_cap': false
|
||||
'panic_n': false
|
||||
'impl_i64_to_string': false
|
||||
'vmemmove': false
|
||||
'tos': false
|
||||
'strings.new_builder': true
|
||||
}
|
||||
|
||||
const windows_blacklist = {
|
||||
|
|
|
@ -150,21 +150,11 @@ fn (mut g Gen) expr(node ast.Expr) {
|
|||
g.gen_sizeof_expr(node)
|
||||
}
|
||||
ast.IndexExpr {
|
||||
g.code_gen.gen_index_expr(node)
|
||||
if node.left_type.is_string() {
|
||||
g.expr(node.index)
|
||||
g.code_gen.push(Amd64Register.rax)
|
||||
|
||||
g.expr(node.left) // load address of string struct
|
||||
g.code_gen.mov_deref(Amd64Register.rax, Amd64Register.rax, ast.u64_type_idx) // load value of the str pointer
|
||||
|
||||
g.code_gen.pop2(Amd64Register.rdx) // index
|
||||
g.code_gen.add_reg2(Amd64Register.rax, Amd64Register.rdx) // add the offset to the address
|
||||
g.code_gen.mov_deref(Amd64Register.rax, Amd64Register.rax, ast.u8_type_idx)
|
||||
} else if node.left_type.is_pointer() {
|
||||
dump(node)
|
||||
g.n_error('${@LOCATION} expr: unhandled node type: Index expr is not applied on string')
|
||||
} else {
|
||||
g.n_error('${@LOCATION} expr: unhandled node type: Index expr is not applied on string')
|
||||
g.code_gen.mov_deref(Amd64Register.rax, Amd64Register.rax, node.typ)
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
@ -192,8 +182,11 @@ fn (mut g Gen) local_var_ident(ident ast.Ident, var LocalVar) {
|
|||
ast.Enum {
|
||||
g.code_gen.mov_var_to_reg(g.code_gen.main_reg(), ident)
|
||||
}
|
||||
ast.Array {
|
||||
g.code_gen.lea_var_to_reg(g.code_gen.main_reg(), g.get_var_offset(ident.name))
|
||||
}
|
||||
else {
|
||||
g.n_error('${@LOCATION} Unsupported variable type')
|
||||
g.n_error('${@LOCATION} Unsupported variable type ${ts.info}')
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -210,8 +203,18 @@ fn (mut g Gen) global_var_ident(ident ast.Ident, var GlobalVar) {
|
|||
fn (mut g Gen) const_var_ident(ident ast.Ident, var ConstVar) {
|
||||
if g.is_register_type(var.typ) {
|
||||
g.code_gen.mov_var_to_reg(g.code_gen.main_reg(), ident)
|
||||
} else {
|
||||
} else if g.is_fp_type(var.typ) {
|
||||
g.n_error('${@LOCATION} Unsupported variable type ${ident} ${var}')
|
||||
} else {
|
||||
ts := g.table.sym(g.unwrap(var.typ))
|
||||
match ts.info {
|
||||
ast.Struct {
|
||||
g.code_gen.mov_var_to_reg(g.code_gen.main_reg(), ident)
|
||||
}
|
||||
else {
|
||||
g.n_error('${@LOCATION} Unsupported variable type ${ident} ${var} ${ts.info}')
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -556,8 +559,8 @@ fn (mut g Gen) gen_left_value(node ast.Expr) {
|
|||
ast.ArrayInit {
|
||||
g.expr(node) // TODO: add a test that uses this
|
||||
}
|
||||
ast.IndexExpr { // TODO
|
||||
g.n_error('${@LOCATION} Unsupported IndexExpr left value')
|
||||
ast.IndexExpr {
|
||||
g.code_gen.gen_index_expr(node)
|
||||
}
|
||||
ast.PrefixExpr {
|
||||
if node.op != .mul {
|
||||
|
|
|
@ -114,6 +114,7 @@ mut:
|
|||
gen_asm_stmt(asm_node ast.AsmStmt)
|
||||
gen_cast_expr(expr ast.CastExpr)
|
||||
gen_exit(expr ast.Expr)
|
||||
gen_index_expr(ast.IndexExpr)
|
||||
gen_match_expr(expr ast.MatchExpr)
|
||||
gen_print_reg(r Register, n i32, fd i32)
|
||||
gen_print(s string, fd i32)
|
||||
|
@ -139,6 +140,7 @@ mut:
|
|||
mov(r Register, val i32)
|
||||
mov64(r Register, val Number)
|
||||
movabs(reg Register, val i64)
|
||||
mul_reg_main(b Register)
|
||||
patch_relative_jmp(pos i32, addr i64)
|
||||
pop2(r Register)
|
||||
prefix_expr(node ast.PrefixExpr)
|
||||
|
@ -891,7 +893,7 @@ fn (mut g Gen) get_type_size(raw_type ast.Type) i32 {
|
|||
return 1
|
||||
}
|
||||
ts := g.table.sym(typ)
|
||||
if ts.size != -1 {
|
||||
if ts.size != -1 && ts.size != 0 {
|
||||
return i32(ts.size)
|
||||
}
|
||||
mut size := i32(0)
|
||||
|
@ -929,6 +931,22 @@ fn (mut g Gen) get_type_size(raw_type ast.Type) i32 {
|
|||
}
|
||||
g.structs[typ.idx()] = strc
|
||||
}
|
||||
ast.Array {
|
||||
// TODO: replace u32 by the enum ArrayFlags size
|
||||
for f_typ in [ast.voidptr_type, ast.int_type, ast.int_type, ast.int_type, ast.u32_type,
|
||||
ast.int_type] {
|
||||
f_size := g.get_type_size(f_typ)
|
||||
f_align := g.get_type_align(f_typ)
|
||||
padding := (f_align - size % f_align) % f_align
|
||||
strc.offsets << size + padding
|
||||
size += f_size + padding
|
||||
if f_align > align {
|
||||
align = f_align
|
||||
}
|
||||
}
|
||||
size = (size + align - 1) / align * align
|
||||
g.structs[typ.idx()] = strc
|
||||
}
|
||||
else {}
|
||||
}
|
||||
mut ts_ := g.table.sym(typ)
|
||||
|
|
|
@ -1,3 +1,13 @@
|
|||
fn main() {
|
||||
assert [1, 2, 3] != []
|
||||
mut my_array := []int{len:3}
|
||||
my_array[0] = 4
|
||||
my_array[1] = 5
|
||||
my_array[2] = 6
|
||||
println(my_array[0])
|
||||
println(my_array[1])
|
||||
println(my_array[2])
|
||||
assert my_array[0] == 4
|
||||
assert my_array[1] == 5
|
||||
assert my_array[2] == 6
|
||||
}
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
4
|
||||
5
|
||||
6
|
|
@ -3,9 +3,25 @@ fn main() {
|
|||
test_lt_gt()
|
||||
test_ref_deref()
|
||||
test_nil()
|
||||
index_expr_test()
|
||||
println("ok")
|
||||
}
|
||||
|
||||
fn index_expr_test() {
|
||||
mut buf := C.malloc(2)
|
||||
unsafe {
|
||||
buf[0] = 1
|
||||
buf[1] = 2
|
||||
assert buf[0] == 1
|
||||
assert buf[1] == 2
|
||||
buf = malloc_noscan(2)
|
||||
buf[0] = 3
|
||||
buf[1] = 4
|
||||
assert buf[0] == 3
|
||||
assert buf[1] == 4
|
||||
}
|
||||
}
|
||||
|
||||
fn test_eq_ne() {
|
||||
unsafe {
|
||||
mut a := voidptr(0)
|
||||
|
|
|
@ -85,6 +85,13 @@ fn test_runes() {
|
|||
println(`\xe2\x98\x85`)
|
||||
}
|
||||
|
||||
const a = 'my string'
|
||||
|
||||
fn const_test() {
|
||||
b := a
|
||||
println(b)
|
||||
}
|
||||
|
||||
fn main() {
|
||||
test_unicode_characters()
|
||||
test_string_len()
|
||||
|
@ -93,4 +100,5 @@ fn main() {
|
|||
test_escape_codes()
|
||||
test_raw_string()
|
||||
test_runes()
|
||||
const_test()
|
||||
}
|
||||
|
|
|
@ -23,3 +23,4 @@ V
|
|||
😀
|
||||
🚀
|
||||
★★★★
|
||||
my string
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue