From 4a156897764d3030a10ee5e3ce4b08e0e090365e Mon Sep 17 00:00:00 2001 From: gingerBill Date: Mon, 25 Mar 2019 21:00:45 +0000 Subject: Remove bounds checks for slice expressions with both indices empty --- src/ir.cpp | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) (limited to 'src/ir.cpp') diff --git a/src/ir.cpp b/src/ir.cpp index 6631711b5..bfc4fae82 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -7186,7 +7186,9 @@ irAddr ir_build_addr(irProcedure *proc, Ast *expr) { irValue *len = ir_slice_len(proc, base); if (high == nullptr) high = len; - ir_emit_slice_bounds_check(proc, se->open, low, high, len, false); + if (se->low != nullptr || se->high != nullptr) { + ir_emit_slice_bounds_check(proc, se->open, low, high, len, false); + } irValue *elem = ir_emit_ptr_offset(proc, ir_slice_elem(proc, base), low); irValue *new_len = ir_emit_arith(proc, Token_Sub, high, low, t_int); @@ -7203,7 +7205,9 @@ irAddr ir_build_addr(irProcedure *proc, Ast *expr) { irValue *len = ir_dynamic_array_len(proc, base); if (high == nullptr) high = len; - ir_emit_slice_bounds_check(proc, se->open, low, high, len, false); + if (se->low != nullptr || se->high != nullptr) { + ir_emit_slice_bounds_check(proc, se->open, low, high, len, false); + } irValue *elem = ir_emit_ptr_offset(proc, ir_dynamic_array_elem(proc, base), low); irValue *new_len = ir_emit_arith(proc, Token_Sub, high, low, t_int); @@ -7224,7 +7228,9 @@ irAddr ir_build_addr(irProcedure *proc, Ast *expr) { bool high_const = type_and_value_of_expr(se->high).mode == Addressing_Constant; if (!low_const || !high_const) { - ir_emit_slice_bounds_check(proc, se->open, low, high, len, false); + if (se->low != nullptr || se->high != nullptr) { + ir_emit_slice_bounds_check(proc, se->open, low, high, len, false); + } } irValue *elem = ir_emit_ptr_offset(proc, ir_array_elem(proc, addr), low); irValue *new_len = ir_emit_arith(proc, Token_Sub, high, low, t_int); @@ -7240,7 +7246,9 @@ irAddr ir_build_addr(irProcedure *proc, Ast *expr) { if (high == nullptr) high = len; // if (max == nullptr) max = ir_string_len(proc, base); - ir_emit_slice_bounds_check(proc, se->open, low, high, len, true); + if (se->low != nullptr || se->high != nullptr) { + ir_emit_slice_bounds_check(proc, se->open, low, high, len, true); + } irValue *elem = ir_emit_ptr_offset(proc, ir_string_elem(proc, base), low); irValue *new_len = ir_emit_arith(proc, Token_Sub, high, low, t_int); -- cgit v1.2.3 From 9e6d488063a7f3070ee68794364258de610c968e Mon Sep 17 00:00:00 2001 From: gingerBill Date: Mon, 25 Mar 2019 21:20:12 +0000 Subject: Modify slice_expr_error_* logic to change depending on which parameters are passed --- core/runtime/internal.odin | 31 ++++++++++++++++++++++----- src/checker.cpp | 3 ++- src/ir.cpp | 52 +++++++++++++++++++++++++++++----------------- 3 files changed, 61 insertions(+), 25 deletions(-) (limited to 'src/ir.cpp') diff --git a/core/runtime/internal.odin b/core/runtime/internal.odin index 410cf7ec4..202f739b6 100644 --- a/core/runtime/internal.odin +++ b/core/runtime/internal.odin @@ -285,8 +285,25 @@ bounds_check_error :: proc "contextless" (file: string, line, column: int, index handle_error(file, line, column, index, count); } -slice_expr_error :: proc "contextless" (file: string, line, column: int, lo, hi: int, len: int) { - if 0 <= lo && lo <= hi && lo < len && hi <= len do return; +slice_expr_error_hi :: proc "contextless" (file: string, line, column: int, hi: int, len: int) { + if 0 <= hi && hi <= len do return; + handle_error :: proc "contextless" (file: string, line, column: int, lo, hi: int, len: int) { + fd := os.stderr; + print_caller_location(fd, Source_Code_Location{file, line, column, "", 0}); + os.write_string(fd, " Invalid slice indices: "); + print_i64(fd, i64(lo)); + os.write_string(fd, ":"); + print_i64(fd, i64(hi)); + os.write_string(fd, ":"); + print_i64(fd, i64(len)); + os.write_byte(fd, '\n'); + debug_trap(); + } + handle_error(file, line, column, 0, hi, len); +} + +slice_expr_error_lo_hi :: proc "contextless" (file: string, line, column: int, lo, hi: int, len: int) { + if 0 <= lo && lo < len && len <= hi && hi <= len do return; handle_error :: proc "contextless" (file: string, line, column: int, lo, hi: int, len: int) { fd := os.stderr; print_caller_location(fd, Source_Code_Location{file, line, column, "", 0}); @@ -303,7 +320,7 @@ slice_expr_error :: proc "contextless" (file: string, line, column: int, lo, hi: } dynamic_array_expr_error :: proc "contextless" (file: string, line, column: int, low, high, max: int) { - if 0 <= low && low <= high && low < max && high <= max do return; + if 0 <= low && low <= high && high <= max do return; handle_error :: proc "contextless" (file: string, line, column: int, low, high, max: int) { fd := os.stderr; print_caller_location(fd, Source_Code_Location{file, line, column, "", 0}); @@ -343,8 +360,12 @@ bounds_check_error_loc :: inline proc "contextless" (using loc := #caller_locati bounds_check_error(file_path, int(line), int(column), index, count); } -slice_expr_error_loc :: inline proc "contextless" (using loc := #caller_location, lo, hi: int, len: int) { - slice_expr_error(file_path, int(line), int(column), lo, hi, len); +slice_expr_error_hi_loc :: inline proc "contextless" (using loc := #caller_location, hi: int, len: int) { + slice_expr_error_hi(file_path, int(line), int(column), hi, len); +} + +slice_expr_error_lo_hi_loc :: inline proc "contextless" (using loc := #caller_location, lo, hi: int, len: int) { + slice_expr_error_lo_hi(file_path, int(line), int(column), lo, hi, len); } dynamic_array_expr_error_loc :: inline proc "contextless" (using loc := #caller_location, low, high, max: int) { diff --git a/src/checker.cpp b/src/checker.cpp index 971c714b2..f1e2bb45d 100644 --- a/src/checker.cpp +++ b/src/checker.cpp @@ -1606,7 +1606,8 @@ void generate_minimum_dependency_set(Checker *c, Entity *start) { if (!build_context.no_bounds_check) { String bounds_check_entities[] = { str_lit("bounds_check_error"), - str_lit("slice_expr_error"), + str_lit("slice_expr_error_hi"), + str_lit("slice_expr_error_lo_hi"), str_lit("dynamic_array_expr_error"), }; for (isize i = 0; i < gb_count_of(bounds_check_entities); i++) { diff --git a/src/ir.cpp b/src/ir.cpp index bfc4fae82..b5ff56b93 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -5352,7 +5352,7 @@ void ir_emit_bounds_check(irProcedure *proc, Token token, irValue *index, irValu ir_emit_runtime_call(proc, "bounds_check_error", args); } -void ir_emit_slice_bounds_check(irProcedure *proc, Token token, irValue *low, irValue *high, irValue *len, bool is_substring) { +void ir_emit_slice_bounds_check(irProcedure *proc, Token token, irValue *low, irValue *high, irValue *len, bool lower_value_used) { if (build_context.no_bounds_check) { return; } @@ -5364,18 +5364,31 @@ void ir_emit_slice_bounds_check(irProcedure *proc, Token token, irValue *low, ir irValue *file = ir_find_or_add_entity_string(proc->module, token.pos.file); irValue *line = ir_const_int(token.pos.line); irValue *column = ir_const_int(token.pos.column); - low = ir_emit_conv(proc, low, t_int); high = ir_emit_conv(proc, high, t_int); - auto args = array_make(ir_allocator(), 6); - args[0] = file; - args[1] = line; - args[2] = column; - args[3] = low; - args[4] = high; - args[5] = len; + if (!lower_value_used) { + auto args = array_make(ir_allocator(), 5); + args[0] = file; + args[1] = line; + args[2] = column; + args[3] = high; + args[4] = len; - ir_emit_runtime_call(proc, "slice_expr_error", args); + ir_emit_runtime_call(proc, "slice_expr_error_hi", args); + } else { + // No need to convert unless used + low = ir_emit_conv(proc, low, t_int); + + auto args = array_make(ir_allocator(), 6); + args[0] = file; + args[1] = line; + args[2] = column; + args[3] = low; + args[4] = high; + args[5] = len; + + ir_emit_runtime_call(proc, "slice_expr_error_lo_hi", args); + } } void ir_emit_dynamic_array_bounds_check(irProcedure *proc, Token token, irValue *low, irValue *high, irValue *max) { @@ -7169,6 +7182,8 @@ irAddr ir_build_addr(irProcedure *proc, Ast *expr) { if (se->low != nullptr) low = ir_build_expr(proc, se->low); if (se->high != nullptr) high = ir_build_expr(proc, se->high); + bool no_indices = se->low == nullptr && se->high == nullptr; + irValue *addr = ir_build_addr_ptr(proc, se->expr); irValue *base = ir_emit_load(proc, addr); Type *type = base_type(ir_type(base)); @@ -7186,8 +7201,8 @@ irAddr ir_build_addr(irProcedure *proc, Ast *expr) { irValue *len = ir_slice_len(proc, base); if (high == nullptr) high = len; - if (se->low != nullptr || se->high != nullptr) { - ir_emit_slice_bounds_check(proc, se->open, low, high, len, false); + if (!no_indices) { + ir_emit_slice_bounds_check(proc, se->open, low, high, len, se->low != nullptr); } irValue *elem = ir_emit_ptr_offset(proc, ir_slice_elem(proc, base), low); @@ -7205,8 +7220,8 @@ irAddr ir_build_addr(irProcedure *proc, Ast *expr) { irValue *len = ir_dynamic_array_len(proc, base); if (high == nullptr) high = len; - if (se->low != nullptr || se->high != nullptr) { - ir_emit_slice_bounds_check(proc, se->open, low, high, len, false); + if (!no_indices) { + ir_emit_slice_bounds_check(proc, se->open, low, high, len, se->low != nullptr); } irValue *elem = ir_emit_ptr_offset(proc, ir_dynamic_array_elem(proc, base), low); @@ -7228,8 +7243,8 @@ irAddr ir_build_addr(irProcedure *proc, Ast *expr) { bool high_const = type_and_value_of_expr(se->high).mode == Addressing_Constant; if (!low_const || !high_const) { - if (se->low != nullptr || se->high != nullptr) { - ir_emit_slice_bounds_check(proc, se->open, low, high, len, false); + if (!no_indices) { + ir_emit_slice_bounds_check(proc, se->open, low, high, len, se->low != nullptr); } } irValue *elem = ir_emit_ptr_offset(proc, ir_array_elem(proc, addr), low); @@ -7244,10 +7259,9 @@ irAddr ir_build_addr(irProcedure *proc, Ast *expr) { GB_ASSERT(type == t_string); irValue *len = ir_string_len(proc, base); if (high == nullptr) high = len; - // if (max == nullptr) max = ir_string_len(proc, base); - if (se->low != nullptr || se->high != nullptr) { - ir_emit_slice_bounds_check(proc, se->open, low, high, len, true); + if (!no_indices) { + ir_emit_slice_bounds_check(proc, se->open, low, high, len, se->low != nullptr); } irValue *elem = ir_emit_ptr_offset(proc, ir_string_elem(proc, base), low); -- cgit v1.2.3