cgen: optimize array op assign (#7178)

pull/7187/head
Uwe Krüger 2020-12-07 17:13:19 +01:00 committed by GitHub
parent 91e18b039c
commit fd689f5fdd
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 77 additions and 50 deletions

View File

@ -796,6 +796,57 @@ fn test_in_struct() {
assert baz.bar[0] == 3
}
[direct_array_access]
fn test_direct_modification() {
mut foo := [2, 0, 5]
foo[1] = 3
foo[0] *= 7
foo[1]--
foo[2] -= 2
assert foo[0] == 14
assert foo[1] == 2
assert foo[2] == 3
}
fn test_shared_modification() {
shared foo := &[2, 0, 5]
lock foo {
unsafe {
foo[1] = 3
foo[0] *= 7
foo[1]--
foo[2] -= 2
}
}
rlock foo {
unsafe {
assert foo[0] == 14
assert foo[1] == 2
assert foo[2] == 3
}
}
}
[direct_array_access]
fn test_shared_direct_modification() {
shared foo := &[2, 0, 5]
lock foo {
unsafe {
foo[1] = 3
foo[0] *= 7
foo[1]--
foo[2] -= 2
}
}
rlock foo {
unsafe {
assert foo[0] == 14
assert foo[1] == 2
assert foo[2] == 3
}
}
}
fn test_bools() {
println('test b')
mut a := [true, false]

View File

@ -3666,12 +3666,18 @@ fn (mut g Gen) index_expr(node ast.IndexExpr) {
is_selector := node.left is ast.SelectorExpr
if g.is_assign_lhs && !is_selector && node.is_setter {
is_direct_array_access := g.fn_decl != 0 && g.fn_decl.is_direct_arr
is_op_assign := g.assign_op != .assign && info.elem_type != table.string_type
array_ptr_type_str := match elem_typ.kind {
.function { 'voidptr*' }
else { '$elem_type_str*' }
}
if is_direct_array_access {
g.write('(($array_ptr_type_str)')
} else if is_op_assign {
g.write('(*($array_ptr_type_str)array_get(')
if left_is_ptr && !node.left_type.has_flag(.shared_f) {
g.write('*')
}
} else {
g.is_array_set = true // special handling of assign_op and closing with '})'
g.write('array_set(')
@ -3680,7 +3686,6 @@ fn (mut g Gen) index_expr(node ast.IndexExpr) {
}
}
g.expr(node.left)
// TODO: test direct_array_access when 'shared' is implemented
if node.left_type.has_flag(.shared_f) {
if left_is_ptr {
g.write('->val')
@ -3700,59 +3705,30 @@ fn (mut g Gen) index_expr(node ast.IndexExpr) {
} else {
g.write(', ')
g.expr(node.index)
mut need_wrapper := true
/*
match node.right {
ast.EnumVal, ast.Ident {
// `&x` is enough for variables and enums
// `&(Foo[]){ ... }` is only needed for function calls and literals
need_wrapper = false
if !is_op_assign {
mut need_wrapper := true
/*
match node.right {
ast.EnumVal, ast.Ident {
// `&x` is enough for variables and enums
// `&(Foo[]){ ... }` is only needed for function calls and literals
need_wrapper = false
}
else {}
}
else {}
}
*/
if need_wrapper {
if elem_typ.kind == .function {
g.write(', &(voidptr[]) { ')
*/
if need_wrapper {
if elem_typ.kind == .function {
g.write(', &(voidptr[]) { ')
} else {
g.write(', &($elem_type_str[]) { ')
}
} else {
g.write(', &($elem_type_str[]) { ')
g.write(', &')
}
} else {
g.write(', &')
}
// `x[0] *= y`
if g.assign_op != .assign &&
g.assign_op in token.assign_tokens && info.elem_type != table.string_type {
// TODO move this
g.write('*($elem_type_str*)array_get(')
if left_is_ptr && !node.left_type.has_flag(.shared_f) {
g.write('*')
}
g.expr(node.left)
if node.left_type.has_flag(.shared_f) {
if left_is_ptr {
g.write('->val')
} else {
g.write('.val')
}
}
g.write(', ')
g.expr(node.index)
g.write(') ')
op := match g.assign_op {
.mult_assign { '*' }
.plus_assign { '+' }
.minus_assign { '-' }
.div_assign { '/' }
.xor_assign { '^' }
.mod_assign { '%' }
.or_assign { '|' }
.and_assign { '&' }
.left_shift_assign { '<<' }
.right_shift_assign { '>>' }
else { '' }
}
g.write(op)
// `x[0] *= y`
g.write('))')
}
}
} else {