Skip to content

Commit

Permalink
v: adjust some checks, based on branch prediction analysis (vlang#22848)
Browse files Browse the repository at this point in the history
  • Loading branch information
felipensp authored Nov 15, 2024
1 parent 561efd1 commit c4fd61c
Show file tree
Hide file tree
Showing 8 changed files with 117 additions and 124 deletions.
5 changes: 2 additions & 3 deletions vlib/v/ast/scope.v
Original file line number Diff line number Diff line change
Expand Up @@ -158,10 +158,9 @@ pub fn (mut s Scope) register_struct_field(name string, field ScopeStructField)
}

pub fn (mut s Scope) register(obj ScopeObject) {
if obj.name == '_' || obj.name in s.objects {
return
if !(obj.name == '_' || obj.name in s.objects) {
s.objects[obj.name] = obj
}
s.objects[obj.name] = obj
}

// returns the innermost scope containing pos
Expand Down
27 changes: 14 additions & 13 deletions vlib/v/checker/assign.v
Original file line number Diff line number Diff line change
Expand Up @@ -307,6 +307,7 @@ fn (mut c Checker) assign_stmt(mut node ast.AssignStmt) {
for left is ast.ParExpr {
left = (left as ast.ParExpr).expr
}
is_assign := node.op in [.assign, .decl_assign]
match mut left {
ast.Ident {
if (is_decl || left.kind == .blank_ident) && left_type.is_ptr()
Expand All @@ -326,7 +327,7 @@ fn (mut c Checker) assign_stmt(mut node ast.AssignStmt) {
}
left_type = right_type
node.left_types[i] = right_type
if node.op !in [.assign, .decl_assign] {
if !is_assign {
c.error('cannot modify blank `_` identifier', left.pos)
}
} else if left.info !is ast.IdentVar {
Expand Down Expand Up @@ -601,18 +602,8 @@ or use an explicit `unsafe{ a[..] }`, if you do not want a copy of the slice.',
}
}
}
if left_sym.kind == .array_fixed && !c.inside_unsafe && node.op in [.assign, .decl_assign]
&& right_sym.kind == .array_fixed && left is ast.Ident && !left.is_blank_ident()
&& right is ast.Ident {
if right_sym.info is ast.ArrayFixed {
if right_sym.info.elem_type.is_ptr() {
c.error('assignment from one fixed array to another with a pointer element type is prohibited outside of `unsafe`',
node.pos)
}
}
}
if left_sym.kind == .map && node.op in [.assign, .decl_assign] && right_sym.kind == .map
&& !left.is_blank_ident() && right.is_lvalue() && right !is ast.ComptimeSelector
if left_sym.kind == .map && is_assign && right_sym.kind == .map && !left.is_blank_ident()
&& right.is_lvalue() && right !is ast.ComptimeSelector
&& (!right_type.is_ptr() || (right is ast.Ident && right.is_auto_deref_var())) {
// Do not allow `a = b`
c.error('cannot copy map: call `move` or `clone` method (or use a reference)',
Expand All @@ -628,6 +619,16 @@ or use an explicit `unsafe{ a[..] }`, if you do not want a copy of the slice.',
c.error('cannot assign `${right}` as a generic function variable', right.pos())
}
}
if left_sym.kind == .array_fixed && !c.inside_unsafe && is_assign
&& right_sym.kind == .array_fixed && left is ast.Ident && !left.is_blank_ident()
&& right is ast.Ident {
if right_sym.info is ast.ArrayFixed {
if right_sym.info.elem_type.is_ptr() {
c.error('assignment from one fixed array to another with a pointer element type is prohibited outside of `unsafe`',
node.pos)
}
}
}
if left_type.is_any_kind_of_pointer() && !left.is_auto_deref_var() {
if !c.inside_unsafe && node.op !in [.assign, .decl_assign] {
// ptr op=
Expand Down
6 changes: 2 additions & 4 deletions vlib/v/checker/checker.v
Original file line number Diff line number Diff line change
Expand Up @@ -2748,10 +2748,8 @@ fn (mut c Checker) stmts_ending_with_expression(mut stmts []ast.Stmt, expected_o
c.stmt_level++
for i, mut stmt in stmts {
c.is_last_stmt = i == stmts.len - 1
if c.scope_returns {
if unreachable.line_nr == -1 {
unreachable = stmt.pos
}
if c.scope_returns && unreachable.line_nr == -1 {
unreachable = stmt.pos
}
prev_expected_or_type := c.expected_or_type
c.expected_or_type = expected_or_type
Expand Down
120 changes: 62 additions & 58 deletions vlib/v/gen/c/cgen.v
Original file line number Diff line number Diff line change
Expand Up @@ -2169,31 +2169,26 @@ fn (mut g Gen) stmt(node ast.Stmt) {
g.set_current_pos_as_last_stmt_pos()
}
match node {
ast.AsmStmt {
g.write_v_source_line_info_stmt(node)
g.asm_stmt(node)
}
ast.AssertStmt {
g.write_v_source_line_info_stmt(node)
g.assert_stmt(node)
}
ast.AssignStmt {
g.write_v_source_line_info_stmt(node)
g.assign_stmt(node)
ast.FnDecl {
g.fn_decl(node)
}
ast.Block {
g.write_v_source_line_info_stmt(node)
if node.is_unsafe {
g.writeln('{ // Unsafe block')
} else {
if !node.is_unsafe {
g.writeln('{')
} else {
g.writeln('{ // Unsafe block')
}
g.stmts(node.stmts)
g.writeln('}')
}
ast.BranchStmt {
ast.AssignStmt {
g.write_v_source_line_info_stmt(node)
g.branch_stmt(node)
g.assign_stmt(node)
}
ast.AssertStmt {
g.write_v_source_line_info_stmt(node)
g.assert_stmt(node)
}
ast.ConstDecl {
g.write_v_source_line_info_stmt(node)
Expand All @@ -2202,18 +2197,9 @@ fn (mut g Gen) stmt(node ast.Stmt) {
ast.ComptimeFor {
g.comptime_for(node)
}
ast.DebuggerStmt {
g.debugger_stmt(node)
}
ast.DeferStmt {
mut defer_stmt := node
defer_stmt.ifdef = g.defer_ifdef
g.writeln('${g.defer_flag_var(defer_stmt)} = true;')
g.defer_stmts << defer_stmt
}
ast.EmptyStmt {}
ast.EnumDecl {
g.enum_decl(node)
ast.BranchStmt {
g.write_v_source_line_info_stmt(node)
g.branch_stmt(node)
}
ast.ExprStmt {
g.write_v_source_line_info_stmt(node)
Expand Down Expand Up @@ -2246,9 +2232,6 @@ fn (mut g Gen) stmt(node ast.Stmt) {
}
}
}
ast.FnDecl {
g.fn_decl(node)
}
ast.ForCStmt {
prev_branch_parent_pos := g.branch_parent_pos
g.branch_parent_pos = node.pos.pos
Expand Down Expand Up @@ -2297,18 +2280,20 @@ fn (mut g Gen) stmt(node ast.Stmt) {
g.labeled_loops.delete(node.label)
g.inner_loop = save_inner_loop
}
ast.GlobalDecl {
g.global_decl(node)
ast.Return {
g.return_stmt(node)
}
ast.GotoLabel {
g.writeln('${c_name(node.name)}: {}')
ast.DeferStmt {
mut defer_stmt := node
defer_stmt.ifdef = g.defer_ifdef
g.writeln('${g.defer_flag_var(defer_stmt)} = true;')
g.defer_stmts << defer_stmt
}
ast.GotoStmt {
g.write_v_source_line_info_stmt(node)
g.writeln('goto ${c_name(node.name)};')
ast.EnumDecl {
g.enum_decl(node)
}
ast.HashStmt {
g.hash_stmt(node)
ast.GlobalDecl {
g.global_decl(node)
}
ast.Import {}
ast.InterfaceDecl {
Expand All @@ -2327,20 +2312,6 @@ fn (mut g Gen) stmt(node ast.Stmt) {
}
}
}
ast.Module {
g.is_builtin_mod = util.module_is_builtin(node.name)
g.cur_mod = node
}
ast.NodeError {}
ast.Return {
g.return_stmt(node)
}
ast.SemicolonStmt {
g.writeln(';')
}
ast.SqlStmt {
g.sql_stmt(node)
}
ast.StructDecl {
name := if node.language == .c {
util.no_dots(node.name)
Expand Down Expand Up @@ -2369,11 +2340,40 @@ fn (mut g Gen) stmt(node ast.Stmt) {
g.typedefs.writeln('typedef struct ${name} ${name};')
}
}
ast.GotoLabel {
g.writeln('${c_name(node.name)}: {}')
}
ast.GotoStmt {
g.write_v_source_line_info_stmt(node)
g.writeln('goto ${c_name(node.name)};')
}
ast.AsmStmt {
g.write_v_source_line_info_stmt(node)
g.asm_stmt(node)
}
ast.HashStmt {
g.hash_stmt(node)
}
ast.TypeDecl {
if !g.pref.skip_unused {
g.writeln('// TypeDecl')
}
}
ast.SemicolonStmt {
g.writeln(';')
}
ast.SqlStmt {
g.sql_stmt(node)
}
ast.Module {
g.is_builtin_mod = util.module_is_builtin(node.name)
g.cur_mod = node
}
ast.EmptyStmt {}
ast.DebuggerStmt {
g.debugger_stmt(node)
}
ast.NodeError {}
}
if !g.skip_stmt_pos { // && g.stmt_path_pos.len > 0 {
g.stmt_path_pos.delete_last()
Expand Down Expand Up @@ -3555,7 +3555,11 @@ fn (mut g Gen) expr(node_ ast.Expr) {
g.ident(node)
}
ast.IfExpr {
g.if_expr(node)
if !node.is_comptime {
g.if_expr(node)
} else {
g.comptime_if(node)
}
}
ast.IfGuardExpr {
g.write('/* guard */')
Expand All @@ -3564,12 +3568,12 @@ fn (mut g Gen) expr(node_ ast.Expr) {
g.index_expr(node)
}
ast.InfixExpr {
if node.op in [.left_shift, .plus_assign, .minus_assign] {
g.inside_map_infix = true
if node.op !in [.left_shift, .plus_assign, .minus_assign] {
g.infix_expr(node)
g.inside_map_infix = false
} else {
g.inside_map_infix = true
g.infix_expr(node)
g.inside_map_infix = false
}
}
ast.IntegerLiteral {
Expand Down
4 changes: 0 additions & 4 deletions vlib/v/gen/c/if.v
Original file line number Diff line number Diff line change
Expand Up @@ -176,10 +176,6 @@ fn (mut g Gen) needs_conds_order(node ast.IfExpr) bool {
}

fn (mut g Gen) if_expr(node ast.IfExpr) {
if node.is_comptime {
g.comptime_if(node)
return
}
// For simple if expressions we can use C's `?:`
// `if x > 0 { 1 } else { 2 }` => `(x > 0)? (1) : (2)`
// For if expressions with multiple statements or another if expression inside, it's much
Expand Down
Loading

0 comments on commit c4fd61c

Please sign in to comment.