|
@@ -4424,406 +4424,6 @@ irValue *ir_build_builtin_proc(irProcedure *proc, Ast *expr, TypeAndValue tv, Bu
|
|
|
break;
|
|
|
}
|
|
|
|
|
|
- #if 0
|
|
|
- case BuiltinProc_new: {
|
|
|
- ir_emit_comment(proc, str_lit("new"));
|
|
|
- // proc new(Type) -> ^Type
|
|
|
- gbAllocator a = ir_allocator();
|
|
|
-
|
|
|
- Type *type = type_of_expr(ce->args[0]);
|
|
|
- Type *allocation_type = type;
|
|
|
- i32 variant_index = 0;
|
|
|
- if (is_type_struct(type)) {
|
|
|
- Type *st = base_type(type);
|
|
|
- if (st->Struct.variant_parent != nullptr) {
|
|
|
- allocation_type = st->Struct.variant_parent;
|
|
|
- variant_index = st->Struct.variant_index;
|
|
|
- GB_ASSERT(allocation_type != nullptr);
|
|
|
- }
|
|
|
- }
|
|
|
- Type *ptr_type = alloc_type_pointer(type);
|
|
|
-
|
|
|
- i64 size = type_size_of(allocation_type);
|
|
|
- i64 align = type_align_of(allocation_type);
|
|
|
-
|
|
|
- irValue **args = gb_alloc_array(a, irValue *, 2);
|
|
|
- args[0] = ir_const_int(size);
|
|
|
- args[1] = ir_const_int(align);
|
|
|
- irValue *call = ir_emit_runtime_call(proc, "alloc", args, 2);
|
|
|
- irValue *v = ir_emit_conv(proc, call, ptr_type);
|
|
|
- if (type != allocation_type) {
|
|
|
- Type *u = base_type(allocation_type);
|
|
|
- Type *uptr_type = alloc_type_pointer(u);
|
|
|
- irValue *parent = ir_emit_conv(proc, call, uptr_type);
|
|
|
- irValue *tag_ptr = ir_emit_union_tag_ptr(proc, parent);
|
|
|
- ir_emit_store(proc, tag_ptr, ir_const_int(variant_index));
|
|
|
- }
|
|
|
- return v;
|
|
|
- break;
|
|
|
- }
|
|
|
- #endif
|
|
|
-
|
|
|
- case BuiltinProc_make: {
|
|
|
- ir_emit_comment(proc, str_lit("make"));
|
|
|
- gbAllocator a = ir_allocator();
|
|
|
- Type *type = type_of_expr(ce->args[0]);
|
|
|
-
|
|
|
- String proc_name = {};
|
|
|
- if (proc->entity != nullptr) {
|
|
|
- proc_name = proc->entity->token.string;
|
|
|
- }
|
|
|
-
|
|
|
- if (is_type_slice(type)) {
|
|
|
- Type *elem_type = core_type(type)->Slice.elem;
|
|
|
- Type *elem_ptr_type = alloc_type_pointer(elem_type);
|
|
|
-
|
|
|
- i64 esz = type_size_of(elem_type);
|
|
|
- i64 eal = type_align_of(elem_type);
|
|
|
-
|
|
|
- irValue *elem_size = ir_const_int(esz);
|
|
|
- irValue *elem_align = ir_const_int(eal);
|
|
|
-
|
|
|
- irValue *len = ir_emit_conv(proc, ir_build_expr(proc, ce->args[1]), t_int);
|
|
|
-
|
|
|
- ir_emit_slice_bounds_check(proc, ast_token(ce->args[1]), v_zero, len, len, false);
|
|
|
-
|
|
|
- irValue *slice_size = len;
|
|
|
- if (esz != 1) {
|
|
|
- slice_size = ir_emit_arith(proc, Token_Mul, elem_size, len, t_int);
|
|
|
- }
|
|
|
-
|
|
|
- TokenPos pos = ast_token(ce->args[0]).pos;
|
|
|
-
|
|
|
- auto args = array_make<irValue *>(ir_allocator(), 3);
|
|
|
- args[0] = slice_size;
|
|
|
- args[1] = elem_align;
|
|
|
- args[2] = ir_emit_source_code_location(proc, proc_name, pos);
|
|
|
- irValue *call = ir_emit_package_call(proc, "mem", "alloc", args);
|
|
|
-
|
|
|
- irValue *ptr = ir_emit_conv(proc, call, elem_ptr_type);
|
|
|
- irValue *slice = ir_add_local_generated(proc, type);
|
|
|
- ir_fill_slice(proc, slice, ptr, len);
|
|
|
- return ir_emit_load(proc, slice);
|
|
|
- } else if (is_type_map(type)) {
|
|
|
- irValue *int_16 = ir_const_int(16);
|
|
|
- irValue *cap = int_16;
|
|
|
- if (ce->args.count == 2) {
|
|
|
- cap = ir_emit_conv(proc, ir_build_expr(proc, ce->args[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));
|
|
|
-
|
|
|
- auto args = array_make<irValue *>(ir_allocator(), 3);
|
|
|
- args[0] = header;
|
|
|
- args[1] = cap;
|
|
|
- args[2] = ir_emit_source_code_location(proc, ce->args[0]);
|
|
|
- ir_emit_runtime_call(proc, "__dynamic_map_reserve", args);
|
|
|
-
|
|
|
- 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;
|
|
|
- if (ce->args.count > 1) {
|
|
|
- len = ir_emit_conv(proc, ir_build_expr(proc, ce->args[1]), t_int);
|
|
|
- }
|
|
|
- irValue *cap = len;
|
|
|
- if (ce->args.count > 2) {
|
|
|
- cap = ir_emit_conv(proc, ir_build_expr(proc, ce->args[2]), t_int);
|
|
|
- }
|
|
|
-
|
|
|
- ir_emit_dynamic_array_bounds_check(proc, ast_token(ce->args[0]), v_zero, len, cap);
|
|
|
-
|
|
|
- irValue *array = ir_add_local_generated(proc, type);
|
|
|
-
|
|
|
- auto args = array_make<irValue *>(ir_allocator(), 6);
|
|
|
- args[0] = ir_emit_conv(proc, array, t_rawptr);
|
|
|
- args[1] = ir_const_int(type_size_of(elem_type));
|
|
|
- args[2] = ir_const_int(type_align_of(elem_type));
|
|
|
- args[3] = len;
|
|
|
- args[4] = cap;
|
|
|
- args[5] = ir_emit_source_code_location(proc, ce->args[0]);
|
|
|
- ir_emit_runtime_call(proc, "__dynamic_array_make", args);
|
|
|
- return ir_emit_load(proc, array);
|
|
|
- }
|
|
|
- break;
|
|
|
- }
|
|
|
-
|
|
|
- #if 0
|
|
|
- case BuiltinProc_free: {
|
|
|
- ir_emit_comment(proc, str_lit("free"));
|
|
|
-
|
|
|
- gbAllocator a = ir_allocator();
|
|
|
-
|
|
|
- Ast *node = ce->args[0];
|
|
|
- TypeAndValue tav = type_and_value_of_expr(node);
|
|
|
- Type *type = base_type(tav.type);
|
|
|
-
|
|
|
- if (is_type_dynamic_array(type)) {
|
|
|
- irValue *val = ir_build_expr(proc, node);
|
|
|
- irValue *da_allocator = ir_emit_struct_ev(proc, val, 3);
|
|
|
-
|
|
|
- irValue *ptr = ir_emit_struct_ev(proc, val, 0);
|
|
|
- ptr = ir_emit_conv(proc, ptr, t_rawptr);
|
|
|
-
|
|
|
- irValue **args = gb_alloc_array(a, irValue *, 1);
|
|
|
- args[0] = da_allocator;
|
|
|
- args[1] = ptr;
|
|
|
- return ir_emit_runtime_call(proc, "free_ptr_with_allocator", args, 2);
|
|
|
- } else if (is_type_map(type)) {
|
|
|
- irValue *map = ir_build_expr(proc, node);
|
|
|
- irValue *map_ptr = ir_address_from_load_or_generate_local(proc, map);
|
|
|
-
|
|
|
- {
|
|
|
- irValue *array = ir_emit_struct_ep(proc, map_ptr, 0);
|
|
|
-
|
|
|
- irValue *da_allocator = ir_emit_load(proc, ir_emit_struct_ep(proc, array, 3));
|
|
|
- irValue *da_ptr = ir_emit_load(proc, ir_emit_struct_ep(proc, array, 0));
|
|
|
- da_ptr = ir_emit_conv(proc, da_ptr, t_rawptr);
|
|
|
-
|
|
|
- irValue **args = gb_alloc_array(a, irValue *, 1);
|
|
|
- args[0] = da_allocator;
|
|
|
- args[1] = da_ptr;
|
|
|
- ir_emit_runtime_call(proc, "free_ptr_with_allocator", args, 2);
|
|
|
- }
|
|
|
- {
|
|
|
- irValue *array = ir_emit_struct_ep(proc, map_ptr, 1);
|
|
|
-
|
|
|
- irValue *da_allocator = ir_emit_load(proc, ir_emit_struct_ep(proc, array, 3));
|
|
|
- irValue *da_ptr = ir_emit_load(proc, ir_emit_struct_ep(proc, array, 0));
|
|
|
- da_ptr = ir_emit_conv(proc, da_ptr, t_rawptr);
|
|
|
-
|
|
|
- irValue **args = gb_alloc_array(a, irValue *, 1);
|
|
|
- args[0] = da_allocator;
|
|
|
- args[1] = da_ptr;
|
|
|
- ir_emit_runtime_call(proc, "free_ptr_with_allocator", args, 2);
|
|
|
- }
|
|
|
- return nullptr;
|
|
|
- }
|
|
|
-
|
|
|
- irValue *val = ir_build_expr(proc, node);
|
|
|
- irValue *ptr = nullptr;
|
|
|
- if (is_type_pointer(type)) {
|
|
|
- ptr = val;
|
|
|
- } else if (is_type_slice(type)) {
|
|
|
- ptr = ir_slice_elem(proc, val);
|
|
|
- } else if (is_type_string(type)) {
|
|
|
- ptr = ir_string_elem(proc, val);
|
|
|
- } else {
|
|
|
- GB_PANIC("Invalid type to 'free'");
|
|
|
- }
|
|
|
-
|
|
|
- if (ptr == nullptr) {
|
|
|
- return nullptr;
|
|
|
- }
|
|
|
-
|
|
|
- ptr = ir_emit_conv(proc, ptr, t_rawptr);
|
|
|
-
|
|
|
- irValue **args = gb_alloc_array(a, irValue *, 1);
|
|
|
- args[0] = ptr;
|
|
|
- return ir_emit_runtime_call(proc, "free_ptr", args, 1);
|
|
|
- break;
|
|
|
- }
|
|
|
- #endif
|
|
|
- #if 0
|
|
|
- case BuiltinProc_reserve: {
|
|
|
- ir_emit_comment(proc, str_lit("reserve"));
|
|
|
- gbAllocator a = ir_allocator();
|
|
|
-
|
|
|
- irValue *ptr = ir_build_addr_ptr(proc, ce->args[0]);
|
|
|
- Type *type = ir_type(ptr);
|
|
|
- GB_ASSERT(is_type_pointer(type));
|
|
|
- type = base_type(type_deref(type));
|
|
|
-
|
|
|
- irValue *capacity = ir_emit_conv(proc, ir_build_expr(proc, ce->args[1]), t_int);
|
|
|
-
|
|
|
- if (is_type_dynamic_array(type)) {
|
|
|
- Type *elem = type->DynamicArray.elem;
|
|
|
-
|
|
|
- irValue *elem_size = ir_const_int(type_size_of(elem));
|
|
|
- irValue *elem_align = ir_const_int(type_align_of(elem));
|
|
|
-
|
|
|
- ptr = ir_emit_conv(proc, ptr, t_rawptr);
|
|
|
-
|
|
|
- irValue **args = gb_alloc_array(a, irValue *, 4);
|
|
|
- args[0] = ptr;
|
|
|
- args[1] = elem_size;
|
|
|
- args[2] = elem_align;
|
|
|
- args[3] = capacity;
|
|
|
- return ir_emit_runtime_call(proc, "__dynamic_array_reserve", args, 4);
|
|
|
- } else if (is_type_map(type)) {
|
|
|
- irValue **args = gb_alloc_array(a, irValue *, 2);
|
|
|
- args[0] = ir_gen_map_header(proc, ptr, type);
|
|
|
- args[1] = capacity;
|
|
|
- return ir_emit_runtime_call(proc, "__dynamic_map_reserve", args, 2);
|
|
|
- } else {
|
|
|
- GB_PANIC("Unknown type for 'reserve'");
|
|
|
- }
|
|
|
- break;
|
|
|
- }
|
|
|
- #endif
|
|
|
- #if 0
|
|
|
- case BuiltinProc_clear: {
|
|
|
- ir_emit_comment(proc, str_lit("clear"));
|
|
|
- Type *original_type = type_of_expr(ce->args[0]);
|
|
|
- irAddr const &addr = ir_build_addr(proc, ce->args[0]);
|
|
|
- irValue *ptr = addr.addr;
|
|
|
- if (is_double_pointer(ir_type(ptr))) {
|
|
|
- ptr = ir_addr_load(proc, addr);
|
|
|
- }
|
|
|
- Type *t = base_type(type_deref(original_type));
|
|
|
- if (is_type_dynamic_array(t)) {
|
|
|
- irValue *count_ptr = ir_emit_struct_ep(proc, ptr, 1);
|
|
|
- ir_emit_store(proc, count_ptr, v_zero);
|
|
|
- } else if (is_type_map(t)) {
|
|
|
- irValue *ha = ir_emit_struct_ep(proc, ptr, 0);
|
|
|
- irValue *ea = ir_emit_struct_ep(proc, ptr, 1);
|
|
|
- ir_emit_store(proc, ir_emit_struct_ep(proc, ha, 1), v_zero);
|
|
|
- ir_emit_store(proc, ir_emit_struct_ep(proc, ea, 1), v_zero);
|
|
|
- } else if (is_type_slice(t)) {
|
|
|
- irValue *count_ptr = ir_emit_struct_ep(proc, ptr, 1);
|
|
|
- ir_emit_store(proc, count_ptr, v_zero);
|
|
|
- } else {
|
|
|
- GB_PANIC("TODO(bill): ir clear for '%s'", type_to_string(t));
|
|
|
- }
|
|
|
- return nullptr;
|
|
|
- break;
|
|
|
- }
|
|
|
- #endif
|
|
|
- #if 0
|
|
|
- case BuiltinProc_append: {
|
|
|
- ir_emit_comment(proc, str_lit("append"));
|
|
|
- gbAllocator a = ir_allocator();
|
|
|
-
|
|
|
- Type *value_type = type_of_expr(ce->args[0]);
|
|
|
- irAddr array_addr = ir_build_addr(proc, ce->args[0]);
|
|
|
- irValue *array_ptr = array_addr.addr;
|
|
|
- if (is_double_pointer(ir_type(array_ptr))) {
|
|
|
- array_ptr = ir_addr_load(proc, array_addr);
|
|
|
- }
|
|
|
- Type *type = ir_type(array_ptr);
|
|
|
- {
|
|
|
- TokenPos pos = ast_token(ce->args[0]).pos;
|
|
|
- GB_ASSERT_MSG(is_type_pointer(type), "%.*s(%td) %s",
|
|
|
- LIT(pos.file), pos.line,
|
|
|
- type_to_string(type));
|
|
|
- }
|
|
|
- type = base_type(type_deref(type));
|
|
|
- Type *elem_type = nullptr;
|
|
|
- bool is_slice = false;
|
|
|
- if (is_type_dynamic_array(type)) {
|
|
|
- elem_type = type->DynamicArray.elem;
|
|
|
- } else if (is_type_slice(type)) {
|
|
|
- is_slice = true;
|
|
|
- elem_type = type->Slice.elem;
|
|
|
- } else {
|
|
|
- GB_PANIC("Invalid type to append");
|
|
|
- }
|
|
|
-
|
|
|
- irValue *elem_size = ir_const_int(type_size_of(elem_type));
|
|
|
- irValue *elem_align = ir_const_int(type_align_of(elem_type));
|
|
|
-
|
|
|
- array_ptr = ir_emit_conv(proc, array_ptr, t_rawptr);
|
|
|
-
|
|
|
- isize arg_index = 0;
|
|
|
- isize arg_count = 0;
|
|
|
- for_array(i, ce->args) {
|
|
|
- Ast *a = ce->args[i];
|
|
|
- Type *at = base_type(type_of_expr(a));
|
|
|
- if (at->kind == Type_Tuple) {
|
|
|
- arg_count += at->Tuple.variable_count;
|
|
|
- } else {
|
|
|
- arg_count++;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- irValue **args = gb_alloc_array(ir_allocator(), irValue *, arg_count);
|
|
|
- bool vari_expand = ce->ellipsis.pos.line != 0;
|
|
|
-
|
|
|
- for_array(i, ce->args) {
|
|
|
- irValue *a = ir_build_expr(proc, ce->args[i]);
|
|
|
- Type *at = ir_type(a);
|
|
|
- if (at->kind == Type_Tuple) {
|
|
|
- for (isize i = 0; i < at->Tuple.variable_count; i++) {
|
|
|
- Entity *e = at->Tuple.variables[i];
|
|
|
- irValue *v = ir_emit_struct_ev(proc, a, i);
|
|
|
- args[arg_index++] = v;
|
|
|
- }
|
|
|
- } else {
|
|
|
- args[arg_index++] = a;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- if (!vari_expand) {
|
|
|
- for (isize i = 1; i < arg_count; i++) {
|
|
|
- args[i] = ir_emit_conv(proc, args[i], elem_type);
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- if (!vari_expand) {
|
|
|
- ir_emit_comment(proc, str_lit("variadic call argument generation"));
|
|
|
- Type *slice_type = alloc_type_slice(elem_type);
|
|
|
- irValue *slice = ir_add_local_generated(proc, slice_type);
|
|
|
- isize slice_len = arg_count-1;
|
|
|
-
|
|
|
- if (slice_len > 0) {
|
|
|
- irValue *base_array = ir_add_local_generated(proc, alloc_type_array(elem_type, slice_len));
|
|
|
-
|
|
|
- for (isize i = 1; i < arg_count; i++) {
|
|
|
- irValue *addr = ir_emit_array_epi(proc, base_array, i-1);
|
|
|
- ir_emit_store(proc, addr, args[i]);
|
|
|
- }
|
|
|
-
|
|
|
- irValue *base_elem = ir_emit_array_epi(proc, base_array, 0);
|
|
|
- irValue *len = ir_const_int(slice_len);
|
|
|
- ir_fill_slice(proc, slice, base_elem, len, len);
|
|
|
- }
|
|
|
-
|
|
|
- arg_count = 2;
|
|
|
- args[arg_count-1] = ir_emit_load(proc, slice);
|
|
|
- }
|
|
|
-
|
|
|
- irValue *item_slice = args[1];
|
|
|
- irValue *items = ir_slice_elem(proc, item_slice);
|
|
|
- irValue *item_count = ir_slice_len(proc, item_slice);
|
|
|
-
|
|
|
- irValue **daa_args = gb_alloc_array(a, irValue *, 5);
|
|
|
- daa_args[0] = array_ptr;
|
|
|
- daa_args[1] = elem_size;
|
|
|
- daa_args[2] = elem_align;
|
|
|
- daa_args[3] = ir_emit_conv(proc, items, t_rawptr);
|
|
|
- daa_args[4] = ir_emit_conv(proc, item_count, t_int);
|
|
|
-
|
|
|
- if (is_slice) {
|
|
|
- return ir_emit_runtime_call(proc, "__slice_append", daa_args, 5);
|
|
|
- }
|
|
|
- return ir_emit_runtime_call(proc, "__dynamic_array_append", daa_args, 5);
|
|
|
- break;
|
|
|
- }
|
|
|
- #endif
|
|
|
- #if 0
|
|
|
- case BuiltinProc_delete: {
|
|
|
- ir_emit_comment(proc, str_lit("delete"));
|
|
|
- irValue *map = ir_build_expr(proc, ce->args[0]);
|
|
|
- irValue *key = ir_build_expr(proc, ce->args[1]);
|
|
|
- Type *map_type = ir_type(map);
|
|
|
- GB_ASSERT(is_type_map(map_type));
|
|
|
- Type *key_type = base_type(map_type)->Map.key;
|
|
|
-
|
|
|
- irValue *addr = ir_address_from_load_or_generate_local(proc, map);
|
|
|
-
|
|
|
- gbAllocator a = ir_allocator();
|
|
|
- irValue **args = gb_alloc_array(a, irValue *, 2);
|
|
|
- args[0] = ir_gen_map_header(proc, addr, map_type);
|
|
|
- args[1] = ir_gen_map_key(proc, key, key_type);
|
|
|
- return ir_emit_runtime_call(proc, "__dynamic_map_delete", args, 2);
|
|
|
- break;
|
|
|
- }
|
|
|
- #endif
|
|
|
-
|
|
|
case BuiltinProc_swizzle: {
|
|
|
ir_emit_comment(proc, str_lit("swizzle.begin"));
|
|
|
irAddr const &addr = ir_build_addr(proc, ce->args[0]);
|