aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKevin Watters <kevinwatters@gmail.com>2019-03-26 11:17:58 -0400
committerKevin Watters <kevinwatters@gmail.com>2019-03-26 11:17:58 -0400
commit14ff561f6cceef2ef50d6d23d66d5403101a7cc0 (patch)
tree2f5729694019a9b7a66d019d85c1c0756dc05216
parente6f9b4fb11285c5ceea3b3cc7cee26aa9f5ae3d2 (diff)
parent1fd677b42e33cf0407e204830df656fc1a931df5 (diff)
Merge branch 'master' of github.com:odin-lang/Odin
-rw-r--r--core/runtime/core.odin4
-rw-r--r--core/runtime/internal.odin29
-rw-r--r--core/strconv/strconv.odin35
-rw-r--r--examples/demo/demo.odin14
-rw-r--r--src/checker.cpp3
-rw-r--r--src/ir.cpp52
6 files changed, 93 insertions, 44 deletions
diff --git a/core/runtime/core.odin b/core/runtime/core.odin
index 1ce7cfac5..187573557 100644
--- a/core/runtime/core.odin
+++ b/core/runtime/core.odin
@@ -403,7 +403,9 @@ unordered_remove :: proc(array: ^$D/[dynamic]$T, index: int, loc := #caller_loca
@builtin
ordered_remove :: proc(array: ^$D/[dynamic]$T, index: int, loc := #caller_location) {
bounds_check_error_loc(loc, index, len(array));
- copy(array[index:], array[index+1:]);
+ if index+1 < len(array) {
+ copy(array[index:], array[index+1:]);
+ }
pop(array);
}
diff --git a/core/runtime/internal.odin b/core/runtime/internal.odin
index 4fdb01cdf..82cd4cb72 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 && 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 && lo <= 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});
@@ -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/core/strconv/strconv.odin b/core/strconv/strconv.odin
index 0a48ce68b..65ba1147c 100644
--- a/core/strconv/strconv.odin
+++ b/core/strconv/strconv.odin
@@ -211,10 +211,15 @@ append_float :: proc(buf: []byte, f: f64, fmt: byte, prec, bit_size: int) -> str
quote :: proc(buf: []byte, s: string) -> string {
write_byte :: inline proc(buf: []byte, i: ^int, bytes: ..byte) {
+ if i^ >= len(buf) do return;
n := copy(buf[i^:], bytes[:]);
i^ += n;
}
+ if buf == nil {
+ return "";
+ }
+
c :: '"';
i := 0;
@@ -230,8 +235,10 @@ quote :: proc(buf: []byte, s: string) -> string {
write_byte(buf, &i, digits[s[0]>>4]);
write_byte(buf, &i, digits[s[0]&0xf]);
}
- s2 := quote_rune(buf[i:], r);
- i += len(s2);
+ if i < len(buf) {
+ s2 := quote_rune(buf[i:], r);
+ i += len(s2);
+ }
}
write_byte(buf, &i, c);
return string(buf[:i]);
@@ -239,17 +246,27 @@ quote :: proc(buf: []byte, s: string) -> string {
quote_rune :: proc(buf: []byte, r: rune) -> string {
write_byte :: inline proc(buf: []byte, i: ^int, bytes: ..byte) {
- n := copy(buf[i^:], bytes[:]);
- i^ += n;
+ if i^ < len(buf) {
+ n := copy(buf[i^:], bytes[:]);
+ i^ += n;
+ }
}
write_string :: inline proc(buf: []byte, i: ^int, s: string) {
- n := copy(buf[i^:], cast([]byte)s);
- i^ += n;
+ if i^ < len(buf) {
+ n := copy(buf[i^:], cast([]byte)s);
+ i^ += n;
+ }
}
write_rune :: inline proc(buf: []byte, i: ^int, r: rune) {
- b, w := utf8.encode_rune(r);
- n := copy(buf[i^:], b[:w]);
- i^ += n;
+ if i^ < len(buf) {
+ b, w := utf8.encode_rune(r);
+ n := copy(buf[i^:], b[:w]);
+ i^ += n;
+ }
+ }
+
+ if buf == nil {
+ return "";
}
i := 0;
diff --git a/examples/demo/demo.odin b/examples/demo/demo.odin
index e5c5830e1..efce9299a 100644
--- a/examples/demo/demo.odin
+++ b/examples/demo/demo.odin
@@ -561,20 +561,6 @@ threading_example :: proc() {
when os.OS == "windows" {
fmt.println("# threading_example");
- unordered_remove :: proc(array: ^$D/[dynamic]$T, index: int, loc := #caller_location) {
- runtime.bounds_check_error_loc(loc, index, len(array));
- n := len(array)-1;
- if index != n {
- array[index] = array[n];
- }
- pop(array);
- }
- ordered_remove :: proc(array: ^$D/[dynamic]$T, index: int, loc := #caller_location) {
- runtime.bounds_check_error_loc(loc, index, len(array));
- copy(array[index:], array[index+1:]);
- pop(array);
- }
-
worker_proc :: proc(t: ^thread.Thread) -> int {
for iteration in 1..5 {
fmt.printf("Thread %d is on iteration %d\n", t.user_index, iteration);
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 6631711b5..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<irValue *>(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<irValue *>(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_hi", args);
+ } else {
+ // No need to convert unless used
+ low = ir_emit_conv(proc, low, t_int);
- ir_emit_runtime_call(proc, "slice_expr_error", args);
+ auto args = array_make<irValue *>(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,7 +7201,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 (!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);
irValue *new_len = ir_emit_arith(proc, Token_Sub, high, low, t_int);
@@ -7203,7 +7220,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 (!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);
irValue *new_len = ir_emit_arith(proc, Token_Sub, high, low, t_int);
@@ -7224,7 +7243,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 (!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);
irValue *new_len = ir_emit_arith(proc, Token_Sub, high, low, t_int);
@@ -7238,9 +7259,10 @@ 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);
- 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);
irValue *new_len = ir_emit_arith(proc, Token_Sub, high, low, t_int);