len, cap, make; remove .count, .capacity, new_slice

This commit is contained in:
Ginger Bill
2017-04-02 18:16:45 +01:00
parent 2c8b99337b
commit 8ce58573df
16 changed files with 538 additions and 185 deletions
+212 -9
View File
@@ -1470,6 +1470,7 @@ irValue *ir_gen_map_header(irProcedure *proc, irValue *map_val, Type *map_type)
GB_ASSERT_MSG(is_type_pointer(ir_type(map_val)), "%s", type_to_string(ir_type(map_val)));
gbAllocator a = proc->module->allocator;
irValue *h = ir_add_local_generated(proc, t_map_header);
map_type = base_type(map_type);
Type *key_type = map_type->Map.key;
Type *val_type = map_type->Map.value;
@@ -1962,12 +1963,74 @@ irValue *ir_emit_arith(irProcedure *proc, TokenKind op, irValue *left, irValue *
return ir_emit(proc, ir_instr_binary_op(proc, op, left, right, type));
}
irValue *ir_emit_comp_against_nil(irProcedure *proc, TokenKind op_kind, irValue *x) {
Type *t = ir_type(x);
if (is_type_any(t)) {
irValue *ti = ir_emit_struct_ev(proc, x, 0);
irValue *data = ir_emit_struct_ev(proc, x, 1);
if (op_kind == Token_CmpEq) {
irValue *a = ir_emit_comp(proc, Token_CmpEq, ti, v_raw_nil);
irValue *b = ir_emit_comp(proc, Token_CmpEq, data, v_raw_nil);
return ir_emit_arith(proc, Token_Or, a, b, t_bool);
} else if (op_kind == Token_NotEq) {
irValue *a = ir_emit_comp(proc, Token_NotEq, ti, v_raw_nil);
irValue *b = ir_emit_comp(proc, Token_NotEq, data, v_raw_nil);
return ir_emit_arith(proc, Token_And, a, b, t_bool);
}
} else if (is_type_slice(t)) {
irValue *data = ir_emit_struct_ev(proc, x, 0);
irValue *cap = ir_emit_struct_ev(proc, x, 2);
if (op_kind == Token_CmpEq) {
irValue *a = ir_emit_comp(proc, Token_CmpEq, data, v_raw_nil);
irValue *b = ir_emit_comp(proc, Token_CmpEq, cap, v_zero);
return ir_emit_arith(proc, Token_Or, a, b, t_bool);
} else if (op_kind == Token_NotEq) {
irValue *a = ir_emit_comp(proc, Token_NotEq, data, v_raw_nil);
irValue *b = ir_emit_comp(proc, Token_NotEq, cap, v_zero);
return ir_emit_arith(proc, Token_And, a, b, t_bool);
}
} else if (is_type_dynamic_array(t)) {
irValue *data = ir_emit_struct_ev(proc, x, 0);
irValue *cap = ir_emit_struct_ev(proc, x, 2);
if (op_kind == Token_CmpEq) {
irValue *a = ir_emit_comp(proc, Token_CmpEq, data, v_raw_nil);
irValue *b = ir_emit_comp(proc, Token_CmpEq, cap, v_zero);
return ir_emit_arith(proc, Token_Or, a, b, t_bool);
} else if (op_kind == Token_NotEq) {
irValue *a = ir_emit_comp(proc, Token_NotEq, data, v_raw_nil);
irValue *b = ir_emit_comp(proc, Token_NotEq, cap, v_zero);
return ir_emit_arith(proc, Token_And, a, b, t_bool);
}
} else if (is_type_map(t)) {
irValue *hashes = ir_emit_struct_ev(proc, x, 0);
irValue *entries = ir_emit_struct_ev(proc, x, 1);
irValue *a = ir_emit_comp_against_nil(proc, op_kind, hashes);
irValue *b = ir_emit_comp_against_nil(proc, op_kind, entries);
if (op_kind == Token_CmpEq) {
return ir_emit_arith(proc, Token_Or, a, b, t_bool);
} else if (op_kind == Token_NotEq) {
return ir_emit_arith(proc, Token_And, a, b, t_bool);
}
}
return NULL;
}
irValue *ir_emit_comp(irProcedure *proc, TokenKind op_kind, irValue *left, irValue *right) {
Type *a = base_type(ir_type(left));
Type *b = base_type(ir_type(right));
GB_ASSERT(gb_is_between(op_kind, Token__ComparisonBegin+1, Token__ComparisonEnd-1));
irValue *nil_check = NULL;
if (left->kind == irValue_Nil) {
nil_check = ir_emit_comp_against_nil(proc, op_kind, right);
} else if (right->kind == irValue_Nil) {
nil_check = ir_emit_comp_against_nil(proc, op_kind, left);
}
if (nil_check != NULL) {
return nil_check;
}
if (are_types_identical(a, b)) {
// NOTE(bill): No need for a conversion
} else if (left->kind == irValue_Constant || left->kind == irValue_Nil) {
@@ -3222,6 +3285,20 @@ void ir_build_defer_stmt(irProcedure *proc, irDefer d) {
}
irValue *ir_emit_clamp(irProcedure *proc, Type *t, irValue *x, irValue *min, irValue *max) {
irValue *cond = NULL;
ir_emit_comment(proc, str_lit("clamp"));
x = ir_emit_conv(proc, x, t);
min = ir_emit_conv(proc, min, t);
max = ir_emit_conv(proc, max, t);
cond = ir_emit_comp(proc, Token_Gt, min, x);
x = ir_emit_select(proc, cond, min, x);
cond = ir_emit_comp(proc, Token_Lt, max, x);
x = ir_emit_select(proc, cond, max, x);
return x;
}
irValue *ir_find_global_variable(irProcedure *proc, String name) {
irValue **value = map_ir_value_get(&proc->module->members, hash_string(name));
@@ -3505,6 +3582,59 @@ irValue *ir_build_expr(irProcedure *proc, AstNode *expr) {
return ir_type_info(proc, t);
} break;
case BuiltinProc_len: {
irValue *v = ir_build_expr(proc, ce->args.e[0]);
Type *t = base_type(ir_type(v));
if (is_type_pointer(t)) {
// IMPORTANT TODO(bill): Should there be a nil pointer check?
v = ir_emit_load(proc, v);
t = type_deref(t);
}
if (is_type_string(t)) {
return ir_string_len(proc, v);
} else if (is_type_array(t)) {
GB_PANIC("Array lengths are constant");
} else if (is_type_vector(t)) {
GB_PANIC("Vector lengths are constant");
} else if (is_type_slice(t)) {
return ir_slice_count(proc, v);
} else if (is_type_dynamic_array(t)) {
return ir_dynamic_array_count(proc, v);
} else if (is_type_map(t)) {
irValue *entries = ir_emit_struct_ev(proc, v, 1);
return ir_dynamic_array_count(proc, entries);
}
GB_PANIC("Unreachable");
} break;
case BuiltinProc_cap: {
irValue *v = ir_build_expr(proc, ce->args.e[0]);
Type *t = base_type(ir_type(v));
if (is_type_pointer(t)) {
// IMPORTANT TODO(bill): Should there be a nil pointer check?
v = ir_emit_load(proc, v);
t = type_deref(t);
}
if (is_type_string(t)) {
GB_PANIC("Unreachable");
} else if (is_type_array(t)) {
GB_PANIC("Array lengths are constant");
} else if (is_type_vector(t)) {
GB_PANIC("Unreachable");
} else if (is_type_slice(t)) {
return ir_slice_capacity(proc, v);
} else if (is_type_dynamic_array(t)) {
return ir_dynamic_array_capacity(proc, v);
} else if (is_type_map(t)) {
irValue *entries = ir_emit_struct_ev(proc, v, 1);
return ir_dynamic_array_capacity(proc, entries);
}
GB_PANIC("Unreachable");
} break;
case BuiltinProc_new: {
ir_emit_comment(proc, str_lit("new"));
// new :: proc(Type) -> ^Type
@@ -3524,6 +3654,7 @@ irValue *ir_build_expr(irProcedure *proc, AstNode *expr) {
return v;
} break;
#if 0
case BuiltinProc_new_slice: {
ir_emit_comment(proc, str_lit("new_slice"));
// new_slice :: proc(Type, len: int) -> []Type
@@ -3562,6 +3693,83 @@ irValue *ir_build_expr(irProcedure *proc, AstNode *expr) {
ir_fill_slice(proc, slice, ptr, count, capacity);
return ir_emit_load(proc, slice);
} break;
#endif
case BuiltinProc_make: {
ir_emit_comment(proc, str_lit("make"));
gbAllocator a = proc->module->allocator;
Type *type = type_of_expr(proc->module->info, ce->args.e[0]);
if (is_type_slice(type)) {
Type *elem_type = core_type(type)->Slice.elem;
Type *elem_ptr_type = make_type_pointer(a, elem_type);
irValue *elem_size = ir_const_int(a, type_size_of(a, elem_type));
irValue *elem_align = ir_const_int(a, type_align_of(a, elem_type));
irValue *count = ir_emit_conv(proc, ir_build_expr(proc, ce->args.e[1]), t_int);
irValue *capacity = count;
if (ce->args.count == 3) {
capacity = ir_emit_conv(proc, ir_build_expr(proc, ce->args.e[2]), t_int);
}
ir_emit_slice_bounds_check(proc, ast_node_token(ce->args.e[1]), v_zero, count, capacity, false);
irValue *slice_size = ir_emit_arith(proc, Token_Mul, elem_size, capacity, t_int);
irValue **args = gb_alloc_array(a, irValue *, 2);
args[0] = slice_size;
args[1] = elem_align;
irValue *call = ir_emit_global_call(proc, "alloc_align", args, 2);
irValue *ptr = ir_emit_conv(proc, call, elem_ptr_type);
irValue *slice = ir_add_local_generated(proc, type);
ir_fill_slice(proc, slice, ptr, count, capacity);
return ir_emit_load(proc, slice);
} else if (is_type_dynamic_map(type)) {
irValue *int_16 = ir_const_int(a, 16);
irValue *cap = v_zero;
if (ce->args.count == 2) {
cap = ir_emit_conv(proc, ir_build_expr(proc, ce->args.e[1]), t_int);
}
irValue *cond = ir_emit_comp(proc, Token_Gt, cap, v_zero);
cap = ir_emit_select(proc, cond, cap, int_16);
irValue *map = ir_add_local_generated(proc, type);
irValue *header = ir_gen_map_header(proc, map, base_type(type));
irValue **args = gb_alloc_array(a, irValue *, 2);
args[0] = header;
args[1] = cap;
ir_emit_global_call(proc, "__dynamic_map_reserve", args, 2);
return ir_emit_load(proc, map);
} else if (is_type_dynamic_array(type)) {
Type *elem_type = base_type(type)->DynamicArray.elem;
irValue *len = v_zero;
irValue *cap = ir_const_int(a, 8);
if (ce->args.count > 1) {
len = ir_emit_conv(proc, ir_build_expr(proc, ce->args.e[1]), t_int);
}
if (ce->args.count > 2) {
cap = ir_emit_conv(proc, ir_build_expr(proc, ce->args.e[2]), t_int);
}
ir_emit_slice_bounds_check(proc, ast_node_token(ce->args.e[0]), v_zero, len, cap, false);
irValue *array = ir_add_local_generated(proc, type);
irValue **args = gb_alloc_array(a, irValue *, 5);
args[0] = array;
args[1] = ir_const_int(a, type_size_of(a, elem_type));
args[2] = ir_const_int(a, type_align_of(a, elem_type));;
args[3] = len;
args[4] = cap;
ir_emit_global_call(proc, "__dynamic_array_make", args, 5);
return ir_emit_load(proc, array);
}
} break;
case BuiltinProc_free: {
ir_emit_comment(proc, str_lit("free"));
@@ -4112,15 +4320,10 @@ irValue *ir_build_expr(irProcedure *proc, AstNode *expr) {
case BuiltinProc_clamp: {
ir_emit_comment(proc, str_lit("clamp"));
Type *t = type_of_expr(proc->module->info, expr);
irValue *x = ir_emit_conv(proc, ir_build_expr(proc, ce->args.e[0]), t);
irValue *min = ir_emit_conv(proc, ir_build_expr(proc, ce->args.e[1]), t);
irValue *max = ir_emit_conv(proc, ir_build_expr(proc, ce->args.e[2]), t);
irValue *cond;
cond = ir_emit_comp(proc, Token_Gt, min, x);
x = ir_emit_select(proc, cond, min, x);
cond = ir_emit_comp(proc, Token_Lt, max, x);
x = ir_emit_select(proc, cond, max, x);
return x;
return ir_emit_clamp(proc, t,
ir_build_expr(proc, ce->args.e[0]),
ir_build_expr(proc, ce->args.e[1]),
ir_build_expr(proc, ce->args.e[2]));
} break;
}
}