From 4d0afc55c353563607206a085432c258e3dc92e1 Mon Sep 17 00:00:00 2001 From: Ginger Bill Date: Fri, 21 Apr 2017 10:03:27 +0100 Subject: [PATCH] Making slicing a little more robust --- core/_preload.odin | 4 +--- src/ir.c | 50 +++++++++++++++++++++++++++++----------------- 2 files changed, 33 insertions(+), 21 deletions(-) diff --git a/core/_preload.odin b/core/_preload.odin index a86eee836..6939a8c17 100644 --- a/core/_preload.odin +++ b/core/_preload.odin @@ -28,9 +28,7 @@ Calling_Convention :: enum { Type_Info_Record :: struct #ordered { types: []^Type_Info, names: []string, - offsets: []int, // offsets may not be used in tuples - // size: int, - // align: int, + offsets: []int, // offsets may not be used in tuples packed: bool, ordered: bool, custom_align: bool, diff --git a/src/ir.c b/src/ir.c index 4e1e942b4..500e221f0 100644 --- a/src/ir.c +++ b/src/ir.c @@ -2522,6 +2522,21 @@ void ir_fill_slice(irProcedure *proc, irValue *slice_ptr, irValue *data, irValue ir_emit_store(proc, ir_emit_struct_ep(proc, slice_ptr, 1), len); ir_emit_store(proc, ir_emit_struct_ep(proc, slice_ptr, 2), cap); } +void ir_fill_string(irProcedure *proc, irValue *string_ptr, irValue *data, irValue *len) { + Type *t = ir_type(string_ptr); + GB_ASSERT(is_type_pointer(t)); + t = type_deref(t); + GB_ASSERT(is_type_string(t)); + ir_emit_store(proc, ir_emit_struct_ep(proc, string_ptr, 0), data); + ir_emit_store(proc, ir_emit_struct_ep(proc, string_ptr, 1), len); +} + +irValue *ir_emit_string(irProcedure *proc, irValue *elem, irValue *len) { + irValue *str = ir_add_local_generated(proc, t_string); + ir_fill_string(proc, str, elem, len); + return ir_emit_load(proc, str); +} + @@ -2566,16 +2581,6 @@ irValue *ir_add_local_slice(irProcedure *proc, Type *slice_type, irValue *base, return slice; } -irValue *ir_emit_string(irProcedure *proc, irValue *elem, irValue *len) { - irValue *str = ir_add_local_generated(proc, t_string); - irValue *str_elem = ir_emit_struct_ep(proc, str, 0); - irValue *str_len = ir_emit_struct_ep(proc, str, 1); - ir_emit_store(proc, str_elem, elem); - ir_emit_store(proc, str_len, len); - return ir_emit_load(proc, str); -} - - String lookup_polymorphic_field(CheckerInfo *info, Type *dst, Type *src) { @@ -4906,14 +4911,16 @@ irAddr ir_build_addr(irProcedure *proc, AstNode *expr) { if (se->high != NULL) high = ir_build_expr(proc, se->high); if (se->max != NULL) max = ir_build_expr(proc, se->max); + bool add_one_to_len = false; + bool add_one_to_cap = false; if (high != NULL && se->interval0.kind == Token_Ellipsis) { - high = ir_emit_arith(proc, Token_Add, high, v_one, t_int); + add_one_to_len = true; } if (max != NULL && se->interval1.kind == Token_Ellipsis) { GB_ASSERT(se->interval0.kind == se->interval1.kind); - max = ir_emit_arith(proc, Token_Add, max, v_one, t_int); + add_one_to_cap = true; } irValue *addr = ir_build_addr(proc, se->expr).addr; @@ -4925,7 +4932,6 @@ irAddr ir_build_addr(irProcedure *proc, AstNode *expr) { addr = base; base = ir_emit_load(proc, base); } - // TODO(bill): Cleanup like mad! switch (type->kind) { @@ -4940,6 +4946,9 @@ irAddr ir_build_addr(irProcedure *proc, AstNode *expr) { irValue *elem = ir_emit_ptr_offset(proc, ir_slice_elem(proc, base), low); irValue *len = ir_emit_arith(proc, Token_Sub, high, low, t_int); irValue *cap = ir_emit_arith(proc, Token_Sub, max, low, t_int); + if (add_one_to_len) len = ir_emit_arith(proc, Token_Add, len, v_one, t_int); + if (add_one_to_cap) cap = ir_emit_arith(proc, Token_Add, cap, v_one, t_int); + irValue *slice = ir_add_local_generated(proc, slice_type); ir_fill_slice(proc, slice, elem, len, cap); return ir_addr(slice); @@ -4957,6 +4966,9 @@ irAddr ir_build_addr(irProcedure *proc, AstNode *expr) { irValue *elem = ir_emit_ptr_offset(proc, ir_dynamic_array_elem(proc, base), low); irValue *len = ir_emit_arith(proc, Token_Sub, high, low, t_int); irValue *cap = ir_emit_arith(proc, Token_Sub, max, low, t_int); + if (add_one_to_len) len = ir_emit_arith(proc, Token_Add, len, v_one, t_int); + if (add_one_to_cap) cap = ir_emit_arith(proc, Token_Add, cap, v_one, t_int); + irValue *slice = ir_add_local_generated(proc, slice_type); ir_fill_slice(proc, slice, elem, len, cap); return ir_addr(slice); @@ -4974,6 +4986,9 @@ irAddr ir_build_addr(irProcedure *proc, AstNode *expr) { irValue *elem = ir_emit_ptr_offset(proc, ir_array_elem(proc, addr), low); irValue *len = ir_emit_arith(proc, Token_Sub, high, low, t_int); irValue *cap = ir_emit_arith(proc, Token_Sub, max, low, t_int); + if (add_one_to_len) len = ir_emit_arith(proc, Token_Add, len, v_one, t_int); + if (add_one_to_cap) cap = ir_emit_arith(proc, Token_Add, cap, v_one, t_int); + irValue *slice = ir_add_local_generated(proc, slice_type); ir_fill_slice(proc, slice, elem, len, cap); return ir_addr(slice); @@ -4982,17 +4997,16 @@ irAddr ir_build_addr(irProcedure *proc, AstNode *expr) { case Type_Basic: { GB_ASSERT(type == t_string); if (high == NULL) high = ir_string_len(proc, base); - if (max == NULL) max = ir_string_len(proc, base); + // if (max == NULL) max = ir_string_len(proc, base); - ir_emit_slice_bounds_check(proc, se->open, low, high, max, true); + ir_emit_slice_bounds_check(proc, se->open, low, high, NULL, true); irValue *elem = ir_emit_ptr_offset(proc, ir_string_elem(proc, base), low); irValue *len = ir_emit_arith(proc, Token_Sub, high, low, t_int); + if (add_one_to_len) len = ir_emit_arith(proc, Token_Add, len, v_one, t_int); irValue *str = ir_add_local_generated(proc, t_string); - ir_emit_store(proc, ir_emit_struct_ep(proc, str, 0), elem); - ir_emit_store(proc, ir_emit_struct_ep(proc, str, 1), len); - + ir_fill_string(proc, str, elem, len); return ir_addr(str); } break; }