From c9b82a21e9a52122a226ecc05c46a29dc8f57dac Mon Sep 17 00:00:00 2001 From: gingerBill Date: Fri, 23 Apr 2021 10:01:52 +0100 Subject: Move `check_builtin_procedure` to check_builtin.cpp --- src/check_expr.cpp | 2806 +--------------------------------------------------- 1 file changed, 1 insertion(+), 2805 deletions(-) (limited to 'src/check_expr.cpp') diff --git a/src/check_expr.cpp b/src/check_expr.cpp index 9818b5015..885a2eaa3 100644 --- a/src/check_expr.cpp +++ b/src/check_expr.cpp @@ -113,7 +113,7 @@ void add_map_key_type_dependencies(CheckerContext *ctx, Type *key); Type *make_soa_struct_slice(CheckerContext *ctx, Ast *array_typ_expr, Ast *elem_expr, Type *elem); Type *make_soa_struct_dynamic_array(CheckerContext *ctx, Ast *array_typ_expr, Ast *elem_expr, Type *elem); - +bool check_builtin_procedure(CheckerContext *c, Operand *operand, Ast *call, i32 id, Type *type_hint); Entity *entity_from_expr(Ast *expr) { expr = unparen_expr(expr); @@ -3830,2810 +3830,6 @@ bool check_identifier_exists(Scope *s, Ast *node, bool nested = false, Scope **o return false; } -typedef bool (BuiltinTypeIsProc)(Type *t); - -BuiltinTypeIsProc *builtin_type_is_procs[BuiltinProc__type_simple_boolean_end - BuiltinProc__type_simple_boolean_begin] = { - nullptr, // BuiltinProc__type_simple_boolean_begin - - is_type_boolean, - is_type_integer, - is_type_rune, - is_type_float, - is_type_complex, - is_type_quaternion, - is_type_string, - is_type_typeid, - is_type_any, - is_type_endian_little, - is_type_endian_big, - is_type_unsigned, - is_type_numeric, - is_type_ordered, - is_type_ordered_numeric, - is_type_indexable, - is_type_sliceable, - is_type_comparable, - is_type_simple_compare, - is_type_dereferenceable, - is_type_valid_for_keys, - - is_type_named, - is_type_pointer, - is_type_array, - is_type_enumerated_array, - is_type_slice, - is_type_dynamic_array, - - is_type_map, - is_type_struct, - is_type_union, - is_type_enum, - is_type_proc, - is_type_bit_set, - is_type_simd_vector, - - is_type_polymorphic_record_specialized, - is_type_polymorphic_record_unspecialized, - - type_has_nil, -}; - - - -bool check_builtin_procedure(CheckerContext *c, Operand *operand, Ast *call, i32 id, Type *type_hint) { - ast_node(ce, CallExpr, call); - if (ce->inlining != ProcInlining_none) { - error(call, "Inlining operators are not allowed on built-in procedures"); - } - - BuiltinProc *bp = &builtin_procs[id]; - { - char const *err = nullptr; - if (ce->args.count < bp->arg_count) { - err = "Too few"; - } else if (ce->args.count > bp->arg_count && !bp->variadic) { - err = "Too many"; - } - - if (err != nullptr) { - gbString expr = expr_to_string(ce->proc); - error(ce->close, "%s arguments for '%s', expected %td, got %td", - err, expr, - bp->arg_count, ce->args.count); - gb_string_free(expr); - return false; - } - } - - switch (id) { - case BuiltinProc_size_of: - case BuiltinProc_align_of: - case BuiltinProc_offset_of: - case BuiltinProc_type_info_of: - case BuiltinProc_typeid_of: - case BuiltinProc_len: - case BuiltinProc_min: - case BuiltinProc_max: - // NOTE(bill): The first arg may be a Type, this will be checked case by case - break; - - case BuiltinProc_DIRECTIVE: { - ast_node(bd, BasicDirective, ce->proc); - String name = bd->name; - if (name == "defined") { - break; - } - if (name == "config") { - break; - } - /*fallthrough*/ - } - default: - if (BuiltinProc__type_begin < id && id < BuiltinProc__type_end) { - check_expr_or_type(c, operand, ce->args[0]); - } else if (ce->args.count > 0) { - check_multi_expr(c, operand, ce->args[0]); - } - break; - } - - String builtin_name = builtin_procs[id].name; - - - if (ce->args.count > 0) { - if (ce->args[0]->kind == Ast_FieldValue) { - if (id != BuiltinProc_soa_zip) { - error(call, "'field = value' calling is not allowed on built-in procedures"); - return false; - } - } - } - - switch (id) { - default: - GB_PANIC("Implement built-in procedure: %.*s", LIT(builtin_name)); - break; - - case BuiltinProc_DIRECTIVE: { - ast_node(bd, BasicDirective, ce->proc); - String name = bd->name; - if (name == "location") { - if (ce->args.count > 1) { - error(ce->args[0], "'#location' expects either 0 or 1 arguments, got %td", ce->args.count); - } - if (ce->args.count > 0) { - Ast *arg = ce->args[0]; - Entity *e = nullptr; - Operand o = {}; - if (arg->kind == Ast_Ident) { - e = check_ident(c, &o, arg, nullptr, nullptr, true); - } else if (arg->kind == Ast_SelectorExpr) { - e = check_selector(c, &o, arg, nullptr); - } - if (e == nullptr) { - error(ce->args[0], "'#location' expected a valid entity name"); - } - } - - operand->type = t_source_code_location; - operand->mode = Addressing_Value; - } else if (name == "load") { - if (ce->args.count != 1) { - error(ce->args[0], "'#load' expects 1 argument, got %td", ce->args.count); - return false; - } - - Ast *arg = ce->args[0]; - Operand o = {}; - check_expr(c, &o, arg); - if (o.mode != Addressing_Constant) { - error(arg, "'#load' expected a constant string argument"); - return false; - } - - if (!is_type_string(o.type)) { - gbString str = type_to_string(o.type); - error(arg, "'#load' expected a constant string, got %s", str); - gb_string_free(str); - return false; - } - - gbAllocator a = heap_allocator(); - - GB_ASSERT(o.value.kind == ExactValue_String); - String base_dir = dir_from_path(get_file_path_string(bd->token.pos.file_id)); - String original_string = o.value.value_string; - - - gbMutex *ignore_mutex = nullptr; - String path = {}; - bool ok = determine_path_from_string(ignore_mutex, call, base_dir, original_string, &path); - - char *c_str = alloc_cstring(a, path); - defer (gb_free(a, c_str)); - - - gbFile f = {}; - gbFileError file_err = gb_file_open(&f, c_str); - defer (gb_file_close(&f)); - - switch (file_err) { - default: - case gbFileError_Invalid: - error(ce->proc, "Failed to `#load` file: %s; invalid file or cannot be found", c_str); - return false; - case gbFileError_NotExists: - error(ce->proc, "Failed to `#load` file: %s; file cannot be found", c_str); - return false; - case gbFileError_Permission: - error(ce->proc, "Failed to `#load` file: %s; file permissions problem", c_str); - return false; - case gbFileError_None: - // Okay - break; - } - - String result = {}; - isize file_size = cast(isize)gb_file_size(&f); - if (file_size > 0) { - u8 *data = cast(u8 *)gb_alloc(a, file_size+1); - gb_file_read_at(&f, data, file_size, 0); - data[file_size] = '\0'; - result.text = data; - result.len = file_size; - } - - operand->type = t_u8_slice; - operand->mode = Addressing_Constant; - operand->value = exact_value_string(result); - - } else if (name == "assert") { - if (ce->args.count != 1) { - error(call, "'#assert' expects 1 argument, got %td", ce->args.count); - return false; - } - if (!is_type_boolean(operand->type) || operand->mode != Addressing_Constant) { - gbString str = expr_to_string(ce->args[0]); - error(call, "'%s' is not a constant boolean", str); - gb_string_free(str); - return false; - } - if (!operand->value.value_bool) { - gbString arg = expr_to_string(ce->args[0]); - error(call, "Compile time assertion: %s", arg); - if (c->proc_name != "") { - gbString str = type_to_string(c->curr_proc_sig); - error_line("\tCalled within '%.*s' :: %s\n", LIT(c->proc_name), str); - gb_string_free(str); - } - gb_string_free(arg); - } - - operand->type = t_untyped_bool; - operand->mode = Addressing_Constant; - } else if (name == "panic") { - if (ce->args.count != 1) { - error(call, "'#panic' expects 1 argument, got %td", ce->args.count); - return false; - } - if (!is_type_string(operand->type) && operand->mode != Addressing_Constant) { - gbString str = expr_to_string(ce->args[0]); - error(call, "'%s' is not a constant string", str); - gb_string_free(str); - return false; - } - error(call, "Compile time panic: %.*s", LIT(operand->value.value_string)); - if (c->proc_name != "") { - gbString str = type_to_string(c->curr_proc_sig); - error_line("\tCalled within '%.*s' :: %s\n", LIT(c->proc_name), str); - gb_string_free(str); - } - operand->type = t_invalid; - operand->mode = Addressing_NoValue; - } else if (name == "defined") { - if (ce->args.count != 1) { - error(call, "'#defined' expects 1 argument, got %td", ce->args.count); - return false; - } - Ast *arg = unparen_expr(ce->args[0]); - if (arg == nullptr || (arg->kind != Ast_Ident && arg->kind != Ast_SelectorExpr)) { - error(call, "'#defined' expects an identifier or selector expression, got %.*s", LIT(ast_strings[arg->kind])); - return false; - } - - if (c->curr_proc_decl == nullptr) { - error(call, "'#defined' is only allowed within a procedure, prefer the replacement '#config(NAME, default_value)'"); - return false; - } - - bool is_defined = check_identifier_exists(c->scope, arg); - operand->type = t_untyped_bool; - operand->mode = Addressing_Constant; - operand->value = exact_value_bool(false); - - } else if (name == "config") { - if (ce->args.count != 2) { - error(call, "'#config' expects 2 argument, got %td", ce->args.count); - return false; - } - Ast *arg = unparen_expr(ce->args[0]); - if (arg == nullptr || arg->kind != Ast_Ident) { - error(call, "'#config' expects an identifier, got %.*s", LIT(ast_strings[arg->kind])); - return false; - } - - Ast *def_arg = unparen_expr(ce->args[1]); - - Operand def = {}; - check_expr(c, &def, def_arg); - if (def.mode != Addressing_Constant) { - error(def_arg, "'#config' default value must be a constant"); - return false; - } - - String name = arg->Ident.token.string; - - - operand->type = def.type; - operand->mode = def.mode; - operand->value = def.value; - - Entity *found = scope_lookup_current(config_pkg->scope, name); - if (found != nullptr) { - if (found->kind != Entity_Constant) { - error(arg, "'#config' entity '%.*s' found but expected a constant", LIT(name)); - } else { - operand->type = found->type; - operand->mode = Addressing_Constant; - operand->value = found->Constant.value; - } - } - } else { - GB_PANIC("Unhandled #%.*s", LIT(name)); - } - - break; - } - - case BuiltinProc_len: - check_expr_or_type(c, operand, ce->args[0]); - if (operand->mode == Addressing_Invalid) { - return false; - } - /* fallthrough */ - - case BuiltinProc_cap: - { - // len :: proc(Type) -> int - // cap :: proc(Type) -> int - - Type *op_type = type_deref(operand->type); - Type *type = t_int; - AddressingMode mode = Addressing_Invalid; - ExactValue value = {}; - if (is_type_string(op_type) && id == BuiltinProc_len) { - if (operand->mode == Addressing_Constant) { - mode = Addressing_Constant; - String str = operand->value.value_string; - value = exact_value_i64(str.len); - type = t_untyped_integer; - } else { - mode = Addressing_Value; - if (is_type_cstring(op_type)) { - add_package_dependency(c, "runtime", "cstring_len"); - } - } - } else if (is_type_array(op_type)) { - Type *at = core_type(op_type); - mode = Addressing_Constant; - value = exact_value_i64(at->Array.count); - type = t_untyped_integer; - } else if (is_type_enumerated_array(op_type) && id == BuiltinProc_len) { - Type *at = core_type(op_type); - mode = Addressing_Constant; - value = exact_value_i64(at->EnumeratedArray.count); - type = t_untyped_integer; - } else if (is_type_slice(op_type) && id == BuiltinProc_len) { - mode = Addressing_Value; - } else if (is_type_dynamic_array(op_type)) { - mode = Addressing_Value; - } else if (is_type_map(op_type)) { - mode = Addressing_Value; - } else if (operand->mode == Addressing_Type && is_type_enum(op_type) && id == BuiltinProc_len) { - Type *bt = base_type(op_type); - mode = Addressing_Constant; - value = exact_value_i64(bt->Enum.fields.count); - type = t_untyped_integer; - } else if (is_type_struct(op_type)) { - Type *bt = base_type(op_type); - if (bt->Struct.soa_kind == StructSoa_Fixed) { - mode = Addressing_Constant; - value = exact_value_i64(bt->Struct.soa_count); - type = t_untyped_integer; - } else if ((bt->Struct.soa_kind == StructSoa_Slice && id == BuiltinProc_len) || - bt->Struct.soa_kind == StructSoa_Dynamic) { - mode = Addressing_Value; - } - } - if (operand->mode == Addressing_Type && mode != Addressing_Constant) { - mode = Addressing_Invalid; - } - - if (mode == Addressing_Invalid) { - gbString t = type_to_string(operand->type); - error(call, "'%.*s' is not supported for '%s'", LIT(builtin_name), t); - return false; - } - - operand->mode = mode; - operand->value = value; - operand->type = type; - - break; - } - - case BuiltinProc_size_of: { - // size_of :: proc(Type or expr) -> untyped int - Operand o = {}; - check_expr_or_type(c, &o, ce->args[0]); - if (o.mode == Addressing_Invalid) { - return false; - } - Type *t = o.type; - if (t == nullptr || t == t_invalid) { - error(ce->args[0], "Invalid argument for 'size_of'"); - return false; - } - t = default_type(t); - - operand->mode = Addressing_Constant; - operand->value = exact_value_i64(type_size_of(t)); - operand->type = t_untyped_integer; - - break; - } - - case BuiltinProc_align_of: { - // align_of :: proc(Type or expr) -> untyped int - Operand o = {}; - check_expr_or_type(c, &o, ce->args[0]); - if (o.mode == Addressing_Invalid) { - return false; - } - Type *t = o.type; - if (t == nullptr || t == t_invalid) { - error(ce->args[0], "Invalid argument for 'align_of'"); - return false; - } - t = default_type(t); - - operand->mode = Addressing_Constant; - operand->value = exact_value_i64(type_align_of(t)); - operand->type = t_untyped_integer; - - break; - } - - - case BuiltinProc_offset_of: { - // offset_of :: proc(Type, field) -> uintptr - Operand op = {}; - Type *bt = check_type(c, ce->args[0]); - Type *type = base_type(bt); - if (type == nullptr || type == t_invalid) { - error(ce->args[0], "Expected a type for 'offset_of'"); - return false; - } - - Ast *field_arg = unparen_expr(ce->args[1]); - if (field_arg == nullptr || - field_arg->kind != Ast_Ident) { - error(field_arg, "Expected an identifier for field argument"); - return false; - } - if (is_type_array(type)) { - error(field_arg, "Invalid type for 'offset_of'"); - return false; - } - - - ast_node(arg, Ident, field_arg); - Selection sel = lookup_field(type, arg->token.string, operand->mode == Addressing_Type); - if (sel.entity == nullptr) { - gbString type_str = type_to_string(bt); - error(ce->args[0], - "'%s' has no field named '%.*s'", type_str, LIT(arg->token.string)); - gb_string_free(type_str); - return false; - } - if (sel.indirect) { - gbString type_str = type_to_string(bt); - error(ce->args[0], - "Field '%.*s' is embedded via a pointer in '%s'", LIT(arg->token.string), type_str); - gb_string_free(type_str); - return false; - } - - operand->mode = Addressing_Constant; - operand->value = exact_value_i64(type_offset_of_from_selection(type, sel)); - operand->type = t_uintptr; - - break; - } - - - case BuiltinProc_type_of: { - // type_of :: proc(val: Type) -> type(Type) - Ast *expr = ce->args[0]; - Operand o = {}; - check_expr_or_type(c, &o, expr); - - // check_assignment(c, operand, nullptr, str_lit("argument of 'type_of'")); - if (o.mode == Addressing_Invalid || o.mode == Addressing_Builtin) { - return false; - } - if (o.type == nullptr || o.type == t_invalid || is_type_asm_proc(o.type)) { - error(o.expr, "Invalid argument to 'type_of'"); - return false; - } - // NOTE(bill): Prevent type cycles for procedure declarations - if (c->curr_proc_sig == o.type) { - gbString s = expr_to_string(o.expr); - error(o.expr, "Invalid cyclic type usage from 'type_of', got '%s'", s); - gb_string_free(s); - return false; - } - - if (is_type_polymorphic(o.type)) { - error(o.expr, "'type_of' of polymorphic type cannot be determined"); - return false; - } - operand->mode = Addressing_Type; - operand->type = o.type; - break; - } - - case BuiltinProc_type_info_of: { - // type_info_of :: proc(Type) -> ^Type_Info - if (c->scope->flags&ScopeFlag_Global) { - compiler_error("'type_info_of' Cannot be declared within the runtime package due to how the internals of the compiler works"); - } - - // NOTE(bill): The type information may not be setup yet - init_core_type_info(c->checker); - Ast *expr = ce->args[0]; - Operand o = {}; - check_expr_or_type(c, &o, expr); - if (o.mode == Addressing_Invalid) { - return false; - } - Type *t = o.type; - if (t == nullptr || t == t_invalid || is_type_asm_proc(o.type) || is_type_polymorphic(t)) { - if (is_type_polymorphic(t)) { - error(ce->args[0], "Invalid argument for 'type_info_of', unspecialized polymorphic type"); - } else { - error(ce->args[0], "Invalid argument for 'type_info_of'"); - } - return false; - } - t = default_type(t); - - add_type_info_type(c, t); - - if (is_operand_value(o) && is_type_typeid(t)) { - add_package_dependency(c, "runtime", "__type_info_of"); - } else if (o.mode != Addressing_Type) { - error(expr, "Expected a type or typeid for 'type_info_of'"); - return false; - } - - operand->mode = Addressing_Value; - operand->type = t_type_info_ptr; - break; - } - - case BuiltinProc_typeid_of: { - // typeid_of :: proc(Type) -> typeid - if (c->scope->flags&ScopeFlag_Global) { - compiler_error("'typeid_of' Cannot be declared within the runtime package due to how the internals of the compiler works"); - } - - // NOTE(bill): The type information may not be setup yet - init_core_type_info(c->checker); - Ast *expr = ce->args[0]; - Operand o = {}; - check_expr_or_type(c, &o, expr); - if (o.mode == Addressing_Invalid) { - return false; - } - Type *t = o.type; - if (t == nullptr || t == t_invalid || is_type_asm_proc(o.type) || is_type_polymorphic(operand->type)) { - error(ce->args[0], "Invalid argument for 'typeid_of'"); - return false; - } - t = default_type(t); - - add_type_info_type(c, t); - - if (o.mode != Addressing_Type) { - error(expr, "Expected a type for 'typeid_of'"); - return false; - } - - operand->mode = Addressing_Value; - operand->type = t_typeid; - operand->value = exact_value_typeid(t); - break; - } - - case BuiltinProc_swizzle: { - // swizzle :: proc(v: [N]T, ..int) -> [M]T - Type *type = base_type(operand->type); - i64 max_count = 0; - Type *elem_type = nullptr; - - if (!is_type_array(type) && !is_type_simd_vector(type)) { - gbString type_str = type_to_string(operand->type); - error(call, - "'swizzle' is only allowed on an array or #simd vector, got '%s'", - type_str); - gb_string_free(type_str); - return false; - } - if (type->kind == Type_Array) { - max_count = type->Array.count; - elem_type = type->Array.elem; - } else if (type->kind == Type_SimdVector) { - max_count = type->SimdVector.count; - elem_type = type->SimdVector.elem; - if (!build_context.use_llvm_api) { - error(call, "'swizzle' with #simd vector is not supported on this backend"); - } - } - - i64 arg_count = 0; - for_array(i, ce->args) { - if (i == 0) { - continue; - } - Ast *arg = ce->args[i]; - Operand op = {}; - check_expr(c, &op, arg); - if (op.mode == Addressing_Invalid) { - return false; - } - Type *arg_type = base_type(op.type); - if (!is_type_integer(arg_type) || op.mode != Addressing_Constant) { - error(op.expr, "Indices to 'swizzle' must be constant integers"); - return false; - } - - if (op.value.value_integer.neg) { - error(op.expr, "Negative 'swizzle' index"); - return false; - } - - BigInt mc = {}; - big_int_from_i64(&mc, max_count); - if (big_int_cmp(&mc, &op.value.value_integer) <= 0) { - error(op.expr, "'swizzle' index exceeds length"); - return false; - } - - arg_count++; - } - - if (arg_count > max_count) { - error(call, "Too many 'swizzle' indices, %td > %td", arg_count, max_count); - return false; - } - - if (arg_count < max_count) { - operand->type = alloc_type_array(elem_type, arg_count); - } - operand->mode = Addressing_Value; - - if (type_hint != nullptr && check_is_castable_to(c, operand, type_hint)) { - operand->type = type_hint; - } - - break; - } - - case BuiltinProc_complex: { - // complex :: proc(real, imag: float_type) -> complex_type - Operand x = *operand; - Operand y = {}; - - // NOTE(bill): Invalid will be the default till fixed - operand->type = t_invalid; - operand->mode = Addressing_Invalid; - - check_expr(c, &y, ce->args[1]); - if (y.mode == Addressing_Invalid) { - return false; - } - - convert_to_typed(c, &x, y.type); if (x.mode == Addressing_Invalid) return false; - convert_to_typed(c, &y, x.type); if (y.mode == Addressing_Invalid) return false; - if (x.mode == Addressing_Constant && - y.mode == Addressing_Constant) { - if (is_type_numeric(x.type) && exact_value_imag(x.value).value_float == 0) { - x.type = t_untyped_float; - } - if (is_type_numeric(y.type) && exact_value_imag(y.value).value_float == 0) { - y.type = t_untyped_float; - } - } - - if (!are_types_identical(x.type, y.type)) { - gbString tx = type_to_string(x.type); - gbString ty = type_to_string(y.type); - error(call, "Mismatched types to 'complex', '%s' vs '%s'", tx, ty); - gb_string_free(ty); - gb_string_free(tx); - return false; - } - - if (!is_type_float(x.type)) { - gbString s = type_to_string(x.type); - error(call, "Arguments have type '%s', expected a floating point", s); - gb_string_free(s); - return false; - } - if (is_type_endian_specific(x.type)) { - gbString s = type_to_string(x.type); - error(call, "Arguments with a specified endian are not allow, expected a normal floating point, got '%s'", s); - gb_string_free(s); - return false; - } - - if (x.mode == Addressing_Constant && y.mode == Addressing_Constant) { - f64 r = exact_value_to_float(x.value).value_float; - f64 i = exact_value_to_float(y.value).value_float; - operand->value = exact_value_complex(r, i); - operand->mode = Addressing_Constant; - } else { - operand->mode = Addressing_Value; - } - - BasicKind kind = core_type(x.type)->Basic.kind; - switch (kind) { - case Basic_f16: operand->type = t_complex32; break; - case Basic_f32: operand->type = t_complex64; break; - case Basic_f64: operand->type = t_complex128; break; - case Basic_UntypedFloat: operand->type = t_untyped_complex; break; - default: GB_PANIC("Invalid type"); break; - } - - if (type_hint != nullptr && check_is_castable_to(c, operand, type_hint)) { - operand->type = type_hint; - } - - break; - } - - case BuiltinProc_quaternion: { - // quaternion :: proc(real, imag, jmag, kmag: float_type) -> complex_type - Operand x = *operand; - Operand y = {}; - Operand z = {}; - Operand w = {}; - - // NOTE(bill): Invalid will be the default till fixed - operand->type = t_invalid; - operand->mode = Addressing_Invalid; - - check_expr(c, &y, ce->args[1]); - if (y.mode == Addressing_Invalid) { - return false; - } - check_expr(c, &z, ce->args[2]); - if (y.mode == Addressing_Invalid) { - return false; - } - check_expr(c, &w, ce->args[3]); - if (y.mode == Addressing_Invalid) { - return false; - } - - convert_to_typed(c, &x, y.type); if (x.mode == Addressing_Invalid) return false; - convert_to_typed(c, &y, x.type); if (y.mode == Addressing_Invalid) return false; - convert_to_typed(c, &z, x.type); if (z.mode == Addressing_Invalid) return false; - convert_to_typed(c, &w, x.type); if (w.mode == Addressing_Invalid) return false; - if (x.mode == Addressing_Constant && - y.mode == Addressing_Constant && - z.mode == Addressing_Constant && - w.mode == Addressing_Constant) { - if (is_type_numeric(x.type) && exact_value_imag(x.value).value_float == 0) { - x.type = t_untyped_float; - } - if (is_type_numeric(y.type) && exact_value_imag(y.value).value_float == 0) { - y.type = t_untyped_float; - } - if (is_type_numeric(z.type) && exact_value_imag(z.value).value_float == 0) { - z.type = t_untyped_float; - } - if (is_type_numeric(w.type) && exact_value_imag(w.value).value_float == 0) { - w.type = t_untyped_float; - } - } - - if (!(are_types_identical(x.type, y.type) && are_types_identical(x.type, z.type) && are_types_identical(x.type, w.type))) { - gbString tx = type_to_string(x.type); - gbString ty = type_to_string(y.type); - gbString tz = type_to_string(z.type); - gbString tw = type_to_string(w.type); - error(call, "Mismatched types to 'quaternion', '%s' vs '%s' vs '%s' vs '%s'", tx, ty, tz, tw); - gb_string_free(tw); - gb_string_free(tz); - gb_string_free(ty); - gb_string_free(tx); - return false; - } - - if (!is_type_float(x.type)) { - gbString s = type_to_string(x.type); - error(call, "Arguments have type '%s', expected a floating point", s); - gb_string_free(s); - return false; - } - if (is_type_endian_specific(x.type)) { - gbString s = type_to_string(x.type); - error(call, "Arguments with a specified endian are not allow, expected a normal floating point, got '%s'", s); - gb_string_free(s); - return false; - } - - if (x.mode == Addressing_Constant && y.mode == Addressing_Constant && z.mode == Addressing_Constant && w.mode == Addressing_Constant) { - f64 r = exact_value_to_float(x.value).value_float; - f64 i = exact_value_to_float(y.value).value_float; - f64 j = exact_value_to_float(z.value).value_float; - f64 k = exact_value_to_float(w.value).value_float; - operand->value = exact_value_quaternion(r, i, j, k); - operand->mode = Addressing_Constant; - } else { - operand->mode = Addressing_Value; - } - - BasicKind kind = core_type(x.type)->Basic.kind; - switch (kind) { - case Basic_f16: operand->type = t_quaternion64; break; - case Basic_f32: operand->type = t_quaternion128; break; - case Basic_f64: operand->type = t_quaternion256; break; - case Basic_UntypedFloat: operand->type = t_untyped_quaternion; break; - default: GB_PANIC("Invalid type"); break; - } - - if (type_hint != nullptr && check_is_castable_to(c, operand, type_hint)) { - operand->type = type_hint; - } - - break; - } - - case BuiltinProc_real: - case BuiltinProc_imag: { - // real :: proc(x: type) -> float_type - // imag :: proc(x: type) -> float_type - - Operand *x = operand; - if (is_type_untyped(x->type)) { - if (x->mode == Addressing_Constant) { - if (is_type_numeric(x->type)) { - x->type = t_untyped_complex; - } - } else if (is_type_quaternion(x->type)) { - convert_to_typed(c, x, t_quaternion256); - if (x->mode == Addressing_Invalid) { - return false; - } - } else{ - convert_to_typed(c, x, t_complex128); - if (x->mode == Addressing_Invalid) { - return false; - } - } - } - - if (!is_type_complex(x->type) && !is_type_quaternion(x->type)) { - gbString s = type_to_string(x->type); - error(call, "Argument has type '%s', expected a complex or quaternion type", s); - gb_string_free(s); - return false; - } - - if (x->mode == Addressing_Constant) { - switch (id) { - case BuiltinProc_real: x->value = exact_value_real(x->value); break; - case BuiltinProc_imag: x->value = exact_value_imag(x->value); break; - } - } else { - x->mode = Addressing_Value; - } - - BasicKind kind = core_type(x->type)->Basic.kind; - switch (kind) { - case Basic_complex32: x->type = t_f16; break; - case Basic_complex64: x->type = t_f32; break; - case Basic_complex128: x->type = t_f64; break; - case Basic_quaternion64: x->type = t_f16; break; - case Basic_quaternion128: x->type = t_f32; break; - case Basic_quaternion256: x->type = t_f64; break; - case Basic_UntypedComplex: x->type = t_untyped_float; break; - case Basic_UntypedQuaternion: x->type = t_untyped_float; break; - default: GB_PANIC("Invalid type"); break; - } - - if (type_hint != nullptr && check_is_castable_to(c, operand, type_hint)) { - operand->type = type_hint; - } - - break; - } - - case BuiltinProc_jmag: - case BuiltinProc_kmag: { - // jmag :: proc(x: type) -> float_type - // kmag :: proc(x: type) -> float_type - - Operand *x = operand; - if (is_type_untyped(x->type)) { - if (x->mode == Addressing_Constant) { - if (is_type_numeric(x->type)) { - x->type = t_untyped_complex; - } - } else{ - convert_to_typed(c, x, t_quaternion256); - if (x->mode == Addressing_Invalid) { - return false; - } - } - } - - if (!is_type_quaternion(x->type)) { - gbString s = type_to_string(x->type); - error(call, "Argument has type '%s', expected a quaternion type", s); - gb_string_free(s); - return false; - } - - if (x->mode == Addressing_Constant) { - switch (id) { - case BuiltinProc_jmag: x->value = exact_value_jmag(x->value); break; - case BuiltinProc_kmag: x->value = exact_value_kmag(x->value); break; - } - } else { - x->mode = Addressing_Value; - } - - BasicKind kind = core_type(x->type)->Basic.kind; - switch (kind) { - case Basic_quaternion64: x->type = t_f16; break; - case Basic_quaternion128: x->type = t_f32; break; - case Basic_quaternion256: x->type = t_f64; break; - case Basic_UntypedComplex: x->type = t_untyped_float; break; - case Basic_UntypedQuaternion: x->type = t_untyped_float; break; - default: GB_PANIC("Invalid type"); break; - } - - if (type_hint != nullptr && check_is_castable_to(c, operand, type_hint)) { - operand->type = type_hint; - } - - break; - } - - case BuiltinProc_conj: { - // conj :: proc(x: type) -> type - Operand *x = operand; - if (is_type_complex(x->type)) { - if (x->mode == Addressing_Constant) { - ExactValue v = exact_value_to_complex(x->value); - f64 r = v.value_complex->real; - f64 i = -v.value_complex->imag; - x->value = exact_value_complex(r, i); - x->mode = Addressing_Constant; - } else { - x->mode = Addressing_Value; - } - } else if (is_type_quaternion(x->type)) { - if (x->mode == Addressing_Constant) { - ExactValue v = exact_value_to_quaternion(x->value); - f64 r = +v.value_quaternion->real; - f64 i = -v.value_quaternion->imag; - f64 j = -v.value_quaternion->jmag; - f64 k = -v.value_quaternion->kmag; - x->value = exact_value_quaternion(r, i, j, k); - x->mode = Addressing_Constant; - } else { - x->mode = Addressing_Value; - } - } else { - gbString s = type_to_string(x->type); - error(call, "Expected a complex or quaternion, got '%s'", s); - gb_string_free(s); - return false; - } - - break; - } - - case BuiltinProc_expand_to_tuple: { - Type *type = base_type(operand->type); - if (!is_type_struct(type) && !is_type_array(type)) { - gbString type_str = type_to_string(operand->type); - error(call, "Expected a struct or array type, got '%s'", type_str); - gb_string_free(type_str); - return false; - } - gbAllocator a = permanent_allocator(); - - Type *tuple = alloc_type_tuple(); - - if (is_type_struct(type)) { - isize variable_count = type->Struct.fields.count; - array_init(&tuple->Tuple.variables, a, variable_count); - // TODO(bill): Should I copy each of the entities or is this good enough? - gb_memmove_array(tuple->Tuple.variables.data, type->Struct.fields.data, variable_count); - } else if (is_type_array(type)) { - isize variable_count = type->Array.count; - array_init(&tuple->Tuple.variables, a, variable_count); - for (isize i = 0; i < variable_count; i++) { - tuple->Tuple.variables[i] = alloc_entity_array_elem(nullptr, blank_token, type->Array.elem, cast(i32)i); - } - } - operand->type = tuple; - operand->mode = Addressing_Value; - - if (tuple->Tuple.variables.count == 1) { - operand->type = tuple->Tuple.variables[0]->type; - } - - break; - } - - case BuiltinProc_min: { - // min :: proc($T: typeid) -> ordered - // min :: proc(a: ..ordered) -> ordered - - check_multi_expr_or_type(c, operand, ce->args[0]); - - Type *original_type = operand->type; - Type *type = base_type(operand->type); - if (operand->mode == Addressing_Type && is_type_enumerated_array(type)) { - // Okay - } else if (!is_type_ordered(type) || !(is_type_numeric(type) || is_type_string(type))) { - gbString type_str = type_to_string(original_type); - error(call, "Expected a ordered numeric type to 'min', got '%s'", type_str); - gb_string_free(type_str); - return false; - } - - if (operand->mode == Addressing_Type) { - if (ce->args.count != 1) { - error(call, "If 'min' gets a type, only 1 arguments is allowed, got %td", ce->args.count); - return false; - } - - if (is_type_boolean(type)) { - operand->mode = Addressing_Constant; - operand->type = original_type; - operand->value = exact_value_bool(false); - return true; - } else if (is_type_integer(type)) { - operand->mode = Addressing_Constant; - operand->type = original_type; - if (is_type_unsigned(type)) { - operand->value = exact_value_u64(0); - return true; - } else { - i64 sz = 8*type_size_of(type); - ExactValue a = exact_value_i64(1); - ExactValue b = exact_value_i64(sz-1); - ExactValue v = exact_binary_operator_value(Token_Shl, a, b); - v = exact_unary_operator_value(Token_Sub, v, cast(i32)sz, false); - operand->value = v; - return true; - } - } else if (is_type_float(type)) { - operand->mode = Addressing_Constant; - operand->type = original_type; - switch (type_size_of(type)) { - case 2: - operand->value = exact_value_float(-65504.0f); - break; - case 4: - operand->value = exact_value_float(-3.402823466e+38f); - break; - case 8: - operand->value = exact_value_float(-1.7976931348623158e+308); - break; - default: - GB_PANIC("Unhandled float type"); - break; - } - return true; - } else if (is_type_enum(type)) { - operand->mode = Addressing_Constant; - operand->type = original_type; - operand->value = type->Enum.min_value; - return true; - } else if (is_type_enumerated_array(type)) { - Type *bt = base_type(type); - GB_ASSERT(bt->kind == Type_EnumeratedArray); - operand->mode = Addressing_Constant; - operand->type = bt->EnumeratedArray.index; - operand->value = bt->EnumeratedArray.min_value; - return true; - } - gbString type_str = type_to_string(original_type); - error(call, "Invalid type for 'min', got %s", type_str); - gb_string_free(type_str); - return false; - } - - - bool all_constant = operand->mode == Addressing_Constant; - - auto operands = array_make(heap_allocator(), 0, ce->args.count); - defer (array_free(&operands)); - - array_add(&operands, *operand); - - for (isize i = 1; i < ce->args.count; i++) { - Ast *other_arg = ce->args[i]; - Operand b = {}; - check_expr(c, &b, other_arg); - if (b.mode == Addressing_Invalid) { - return false; - } - if (!is_type_ordered(b.type) || !(is_type_numeric(b.type) || is_type_string(b.type))) { - gbString type_str = type_to_string(b.type); - error(call, - "Expected a ordered numeric type to 'min', got '%s'", - type_str); - gb_string_free(type_str); - return false; - } - array_add(&operands, b); - - if (all_constant) { - all_constant = b.mode == Addressing_Constant; - } - } - - if (all_constant) { - ExactValue value = operands[0].value; - Type *type = operands[0].type; - for (isize i = 1; i < operands.count; i++) { - Operand y = operands[i]; - if (compare_exact_values(Token_Lt, value, y.value)) { - // okay - } else { - value = y.value; - type = y.type; - } - } - operand->value = value; - operand->type = type; - } else { - operand->mode = Addressing_Value; - operand->type = original_type; - - for_array(i, operands) { - Operand *a = &operands[i]; - for_array(j, operands) { - if (i == j) { - continue; - } - Operand *b = &operands[j]; - - convert_to_typed(c, a, b->type); - if (a->mode == Addressing_Invalid) { - return false; - } - convert_to_typed(c, b, a->type); - if (b->mode == Addressing_Invalid) { - return false; - } - } - } - - for (isize i = 0; i < operands.count-1; i++) { - Operand *a = &operands[i]; - Operand *b = &operands[i+1]; - - if (!are_types_identical(a->type, b->type)) { - gbString type_a = type_to_string(a->type); - gbString type_b = type_to_string(b->type); - error(a->expr, - "Mismatched types to 'min', '%s' vs '%s'", - type_a, type_b); - gb_string_free(type_b); - gb_string_free(type_a); - return false; - } - } - - - { - Type *bt = base_type(operands[0].type); - if (are_types_identical(bt, t_f32)) add_package_dependency(c, "runtime", "min_f32"); - if (are_types_identical(bt, t_f64)) add_package_dependency(c, "runtime", "min_f64"); - - operand->type = operands[0].type; - } - } - break; - } - - case BuiltinProc_max: { - // max :: proc($T: typeid) -> ordered - // max :: proc(a: ..ordered) -> ordered - - check_multi_expr_or_type(c, operand, ce->args[0]); - - Type *original_type = operand->type; - Type *type = base_type(operand->type); - - if (operand->mode == Addressing_Type && is_type_enumerated_array(type)) { - // Okay - } else if (!is_type_ordered(type) || !(is_type_numeric(type) || is_type_string(type))) { - gbString type_str = type_to_string(original_type); - error(call, "Expected a ordered numeric type to 'max', got '%s'", type_str); - gb_string_free(type_str); - return false; - } - - if (operand->mode == Addressing_Type) { - if (ce->args.count != 1) { - error(call, "If 'max' gets a type, only 1 arguments is allowed, got %td", ce->args.count); - return false; - } - - if (is_type_boolean(type)) { - operand->mode = Addressing_Constant; - operand->type = original_type; - operand->value = exact_value_bool(true); - return true; - } else if (is_type_integer(type)) { - operand->mode = Addressing_Constant; - operand->type = original_type; - if (is_type_unsigned(type)) { - i64 sz = 8*type_size_of(type); - ExactValue a = exact_value_i64(1); - ExactValue b = exact_value_i64(sz); - ExactValue v = exact_binary_operator_value(Token_Shl, a, b); - v = exact_binary_operator_value(Token_Sub, v, a); - operand->value = v; - return true; - } else { - i64 sz = 8*type_size_of(type); - ExactValue a = exact_value_i64(1); - ExactValue b = exact_value_i64(sz-1); - ExactValue v = exact_binary_operator_value(Token_Shl, a, b); - v = exact_binary_operator_value(Token_Sub, v, a); - operand->value = v; - return true; - } - } else if (is_type_float(type)) { - operand->mode = Addressing_Constant; - operand->type = original_type; - switch (type_size_of(type)) { - case 2: - operand->value = exact_value_float(65504.0f); - break; - case 4: - operand->value = exact_value_float(3.402823466e+38f); - break; - case 8: - operand->value = exact_value_float(1.7976931348623158e+308); - break; - default: - GB_PANIC("Unhandled float type"); - break; - } - return true; - } else if (is_type_enum(type)) { - operand->mode = Addressing_Constant; - operand->type = original_type; - operand->value = type->Enum.max_value; - return true; - } else if (is_type_enumerated_array(type)) { - Type *bt = base_type(type); - GB_ASSERT(bt->kind == Type_EnumeratedArray); - operand->mode = Addressing_Constant; - operand->type = bt->EnumeratedArray.index; - operand->value = bt->EnumeratedArray.max_value; - return true; - } - gbString type_str = type_to_string(original_type); - error(call, "Invalid type for 'max', got %s", type_str); - gb_string_free(type_str); - return false; - } - - bool all_constant = operand->mode == Addressing_Constant; - - auto operands = array_make(heap_allocator(), 0, ce->args.count); - defer (array_free(&operands)); - - array_add(&operands, *operand); - - - for (isize i = 1; i < ce->args.count; i++) { - Ast *arg = ce->args[i]; - Operand b = {}; - check_expr(c, &b, arg); - if (b.mode == Addressing_Invalid) { - return false; - } - if (!is_type_ordered(b.type) || !(is_type_numeric(b.type) || is_type_string(b.type))) { - gbString type_str = type_to_string(b.type); - error(arg, - "Expected a ordered numeric type to 'max', got '%s'", - type_str); - gb_string_free(type_str); - return false; - } - array_add(&operands, b); - - if (all_constant) { - all_constant = b.mode == Addressing_Constant; - } - } - - if (all_constant) { - ExactValue value = operands[0].value; - Type *type = operands[0].type; - for (isize i = 1; i < operands.count; i++) { - Operand y = operands[i]; - if (compare_exact_values(Token_Gt, value, y.value)) { - // okay - } else { - type = y.type; - value = y.value; - } - } - operand->value = value; - operand->type = type; - } else { - operand->mode = Addressing_Value; - operand->type = original_type; - - for_array(i, operands) { - Operand *a = &operands[i]; - for_array(j, operands) { - if (i == j) { - continue; - } - Operand *b = &operands[j]; - - convert_to_typed(c, a, b->type); - if (a->mode == Addressing_Invalid) { - return false; - } - convert_to_typed(c, b, a->type); - if (b->mode == Addressing_Invalid) { - return false; - } - } - } - - for (isize i = 0; i < operands.count-1; i++) { - Operand *a = &operands[i]; - Operand *b = &operands[i+1]; - - if (!are_types_identical(a->type, b->type)) { - gbString type_a = type_to_string(a->type); - gbString type_b = type_to_string(b->type); - error(a->expr, - "Mismatched types to 'max', '%s' vs '%s'", - type_a, type_b); - gb_string_free(type_b); - gb_string_free(type_a); - return false; - } - } - - { - Type *bt = base_type(operands[0].type); - if (are_types_identical(bt, t_f32)) add_package_dependency(c, "runtime", "max_f32"); - if (are_types_identical(bt, t_f64)) add_package_dependency(c, "runtime", "max_f64"); - - operand->type = operands[0].type; - } - } - break; - } - - case BuiltinProc_abs: { - // abs :: proc(n: numeric) -> numeric - if (!(is_type_numeric(operand->type) && !is_type_array(operand->type))) { - gbString type_str = type_to_string(operand->type); - error(call, "Expected a numeric type to 'abs', got '%s'", type_str); - gb_string_free(type_str); - return false; - } - - if (operand->mode == Addressing_Constant) { - switch (operand->value.kind) { - case ExactValue_Integer: - operand->value.value_integer.neg = false; - break; - case ExactValue_Float: - operand->value.value_float = gb_abs(operand->value.value_float); - break; - case ExactValue_Complex: { - f64 r = operand->value.value_complex->real; - f64 i = operand->value.value_complex->imag; - operand->value = exact_value_float(gb_sqrt(r*r + i*i)); - - break; - } - default: - GB_PANIC("Invalid numeric constant"); - break; - } - } else { - operand->mode = Addressing_Value; - - { - Type *bt = base_type(operand->type); - if (are_types_identical(bt, t_f32)) add_package_dependency(c, "runtime", "abs_f32"); - if (are_types_identical(bt, t_f64)) add_package_dependency(c, "runtime", "abs_f64"); - if (are_types_identical(bt, t_complex64)) add_package_dependency(c, "runtime", "abs_complex64"); - if (are_types_identical(bt, t_complex128)) add_package_dependency(c, "runtime", "abs_complex128"); - if (are_types_identical(bt, t_quaternion128)) add_package_dependency(c, "runtime", "abs_quaternion128"); - if (are_types_identical(bt, t_quaternion256)) add_package_dependency(c, "runtime", "abs_quaternion256"); - } - } - - if (is_type_complex(operand->type)) { - operand->type = base_complex_elem_type(operand->type); - } - GB_ASSERT(!is_type_complex(operand->type)); - - break; - } - - case BuiltinProc_clamp: { - // clamp :: proc(a, min, max: ordered) -> ordered - Type *type = operand->type; - if (!is_type_ordered(type) || !(is_type_numeric(type) || is_type_string(type))) { - gbString type_str = type_to_string(operand->type); - error(call, "Expected a ordered numeric or string type to 'clamp', got '%s'", type_str); - gb_string_free(type_str); - return false; - } - - Ast *min_arg = ce->args[1]; - Ast *max_arg = ce->args[2]; - Operand x = *operand; - Operand y = {}; - Operand z = {}; - - check_expr(c, &y, min_arg); - if (y.mode == Addressing_Invalid) { - return false; - } - if (!is_type_ordered(y.type) || !(is_type_numeric(y.type) || is_type_string(y.type))) { - gbString type_str = type_to_string(y.type); - error(call, "Expected a ordered numeric or string type to 'clamp', got '%s'", type_str); - gb_string_free(type_str); - return false; - } - - check_expr(c, &z, max_arg); - if (z.mode == Addressing_Invalid) { - return false; - } - if (!is_type_ordered(z.type) || !(is_type_numeric(z.type) || is_type_string(z.type))) { - gbString type_str = type_to_string(z.type); - error(call, "Expected a ordered numeric or string type to 'clamp', got '%s'", type_str); - gb_string_free(type_str); - return false; - } - - if (x.mode == Addressing_Constant && - y.mode == Addressing_Constant && - z.mode == Addressing_Constant) { - ExactValue a = x.value; - ExactValue b = y.value; - ExactValue c = z.value; - - operand->mode = Addressing_Constant; - if (compare_exact_values(Token_Lt, a, b)) { - operand->value = b; - operand->type = y.type; - } else if (compare_exact_values(Token_Gt, a, c)) { - operand->value = c; - operand->type = z.type; - } else { - operand->value = a; - operand->type = x.type; - } - } else { - operand->mode = Addressing_Value; - operand->type = type; - - Operand *ops[3] = {&x, &y, &z}; - for (isize i = 0; i < 3; i++) { - Operand *a = ops[i]; - for (isize j = 0; j < 3; j++) { - if (i == j) continue; - Operand *b = ops[j]; - convert_to_typed(c, a, b->type); - if (a->mode == Addressing_Invalid) { return false; } - } - } - - if (!are_types_identical(x.type, y.type) || !are_types_identical(x.type, z.type)) { - gbString type_x = type_to_string(x.type); - gbString type_y = type_to_string(y.type); - gbString type_z = type_to_string(z.type); - error(call, - "Mismatched types to 'clamp', '%s', '%s', '%s'", - type_x, type_y, type_z); - gb_string_free(type_z); - gb_string_free(type_y); - gb_string_free(type_x); - return false; - } - - { - Type *bt = base_type(x.type); - if (are_types_identical(bt, t_f32)) { - add_package_dependency(c, "runtime", "min_f32"); - add_package_dependency(c, "runtime", "max_f32"); - } - if (are_types_identical(bt, t_f64)) { - add_package_dependency(c, "runtime", "min_f64"); - add_package_dependency(c, "runtime", "max_f64"); - } - - operand->type = ops[0]->type; - } - } - - break; - } - - case BuiltinProc_soa_zip: { - if (!build_context.use_llvm_api) { - error(call, "'soa_zip' is not supported with this backend"); - return false; - } - - auto types = array_make(temporary_allocator(), 0, ce->args.count); - auto names = array_make(temporary_allocator(), 0, ce->args.count); - - bool first_is_field_value = (ce->args[0]->kind == Ast_FieldValue); - - bool fail = false; - for_array(i, ce->args) { - Ast *arg = ce->args[i]; - bool mix = false; - if (first_is_field_value) { - mix = arg->kind != Ast_FieldValue; - } else { - mix = arg->kind == Ast_FieldValue; - } - if (mix) { - error(arg, "Mixture of 'field = value' and value elements in the procedure call 'soa_zip' is not allowed"); - fail = true; - break; - } - } - StringSet name_set = {}; - string_set_init(&name_set, temporary_allocator(), 2*ce->args.count); - - for_array(i, ce->args) { - String name = {}; - Ast *arg = ce->args[i]; - if (arg->kind == Ast_FieldValue) { - Ast *ename = arg->FieldValue.field; - if (!fail && ename->kind != Ast_Ident) { - error(ename, "Expected an identifier for field argument"); - } else if (ename->kind == Ast_Ident) { - name = ename->Ident.token.string; - } - arg = arg->FieldValue.value; - } - - Operand op = {}; - check_expr(c, &op, arg); - if (op.mode == Addressing_Invalid) { - return false; - } - Type *arg_type = base_type(op.type); - if (!is_type_slice(arg_type)) { - gbString s = type_to_string(op.type); - error(op.expr, "Indices to 'soa_zip' must be slices, got %s", s); - gb_string_free(s); - return false; - } - GB_ASSERT(arg_type->kind == Type_Slice); - if (name == "_") { - error(op.expr, "Field argument name '%.*s' is not allowed", LIT(name)); - name = {}; - } - if (name.len == 0) { - gbString field_name = gb_string_make(permanent_allocator(), "_"); - field_name = gb_string_append_fmt(field_name, "%td", types.count); - name = make_string_c(field_name); - } - - - if (string_set_exists(&name_set, name)) { - error(op.expr, "Field argument name '%.*s' already exists", LIT(name)); - } else { - array_add(&types, arg_type->Slice.elem); - array_add(&names, name); - - string_set_add(&name_set, name); - } - } - - - - - Ast *dummy_node_struct = alloc_ast_node(nullptr, Ast_Invalid); - Ast *dummy_node_soa = alloc_ast_node(nullptr, Ast_Invalid); - Scope *s = create_scope(builtin_pkg->scope); - - auto fields = array_make(permanent_allocator(), 0, types.count); - for_array(i, types) { - Type *type = types[i]; - String name = names[i]; - GB_ASSERT(name != ""); - Entity *e = alloc_entity_field(s, make_token_ident(name), type, false, cast(i32)i, EntityState_Resolved); - array_add(&fields, e); - scope_insert(s, e); - } - - Type *elem = nullptr; - if (type_hint != nullptr && is_type_struct(type_hint)) { - Type *soa_type = base_type(type_hint); - if (soa_type->Struct.soa_kind != StructSoa_Slice) { - goto soa_zip_end; - } - Type *soa_elem_type = soa_type->Struct.soa_elem; - Type *et = base_type(soa_elem_type); - if (et->kind != Type_Struct) { - goto soa_zip_end; - } - - if (et->Struct.fields.count != fields.count) { - goto soa_zip_end; - } - if (!fail && first_is_field_value) { - for_array(i, names) { - Selection sel = lookup_field(et, names[i], false); - if (sel.entity == nullptr) { - goto soa_zip_end; - } - if (sel.index.count != 1) { - goto soa_zip_end; - } - if (!are_types_identical(sel.entity->type, types[i])) { - goto soa_zip_end; - } - } - } else { - for_array(i, et->Struct.fields) { - if (!are_types_identical(et->Struct.fields[i]->type, types[i])) { - goto soa_zip_end; - } - } - } - - elem = soa_elem_type; - } - - soa_zip_end:; - - if (elem == nullptr) { - elem = alloc_type_struct(); - elem->Struct.scope = s; - elem->Struct.fields = fields; - elem->Struct.tags = array_make(permanent_allocator(), fields.count); - elem->Struct.node = dummy_node_struct; - type_set_offsets(elem); - } - - Type *soa_type = make_soa_struct_slice(c, dummy_node_soa, nullptr, elem); - type_set_offsets(soa_type); - - operand->type = soa_type; - operand->mode = Addressing_Value; - - break; - } - - case BuiltinProc_soa_unzip: { - if (!build_context.use_llvm_api) { - error(call, "'soa_unzip' is not supported with this backend"); - return false; - } - - Operand x = {}; - check_expr(c, &x, ce->args[0]); - if (x.mode == Addressing_Invalid) { - return false; - } - if (!is_operand_value(x)) { - error(call, "'soa_unzip' expects an #soa slice"); - return false; - } - Type *t = base_type(x.type); - if (!is_type_soa_struct(t) || t->Struct.soa_kind != StructSoa_Slice) { - gbString s = type_to_string(x.type); - error(call, "'soa_unzip' expects an #soa slice, got %s", s); - gb_string_free(s); - return false; - } - auto types = slice_make(permanent_allocator(), t->Struct.fields.count-1); - for_array(i, types) { - Entity *f = t->Struct.fields[i]; - GB_ASSERT(f->type->kind == Type_Pointer); - types[i] = alloc_type_slice(f->type->Pointer.elem); - } - - operand->type = alloc_type_tuple_from_field_types(types.data, types.count, false, false); - operand->mode = Addressing_Value; - break; - } - - - case BuiltinProc_simd_vector: { - Operand x = {}; - Operand y = {}; - x = *operand; - if (!is_type_integer(x.type) || x.mode != Addressing_Constant) { - error(call, "Expected a constant integer for 'intrinsics.simd_vector'"); - operand->mode = Addressing_Type; - operand->type = t_invalid; - return false; - } - if (x.value.value_integer.neg) { - error(call, "Negative vector element length"); - operand->mode = Addressing_Type; - operand->type = t_invalid; - return false; - } - i64 count = big_int_to_i64(&x.value.value_integer); - - check_expr_or_type(c, &y, ce->args[1]); - if (y.mode != Addressing_Type) { - error(call, "Expected a type 'intrinsics.simd_vector'"); - operand->mode = Addressing_Type; - operand->type = t_invalid; - return false; - } - Type *elem = y.type; - if (!is_type_valid_vector_elem(elem)) { - gbString str = type_to_string(elem); - error(call, "Invalid element type for 'intrinsics.simd_vector', expected an integer or float with no specific endianness, got '%s'", str); - gb_string_free(str); - operand->mode = Addressing_Type; - operand->type = t_invalid; - return false; - } - - operand->mode = Addressing_Type; - operand->type = alloc_type_simd_vector(count, elem); - break; - } - - case BuiltinProc_soa_struct: { - Operand x = {}; - Operand y = {}; - x = *operand; - if (!is_type_integer(x.type) || x.mode != Addressing_Constant) { - error(call, "Expected a constant integer for 'intrinsics.soa_struct'"); - operand->mode = Addressing_Type; - operand->type = t_invalid; - return false; - } - if (x.value.value_integer.neg) { - error(call, "Negative array element length"); - operand->mode = Addressing_Type; - operand->type = t_invalid; - return false; - } - i64 count = big_int_to_i64(&x.value.value_integer); - - check_expr_or_type(c, &y, ce->args[1]); - if (y.mode != Addressing_Type) { - error(call, "Expected a type 'intrinsics.soa_struct'"); - operand->mode = Addressing_Type; - operand->type = t_invalid; - return false; - } - Type *elem = y.type; - Type *bt_elem = base_type(elem); - if (!is_type_struct(elem) && !is_type_raw_union(elem) && !(is_type_array(elem) && bt_elem->Array.count <= 4)) { - gbString str = type_to_string(elem); - error(call, "Invalid type for 'intrinsics.soa_struct', expected a struct or array of length 4 or below, got '%s'", str); - gb_string_free(str); - operand->mode = Addressing_Type; - operand->type = t_invalid; - return false; - } - - operand->mode = Addressing_Type; - Type *soa_struct = nullptr; - Scope *scope = nullptr; - - if (is_type_array(elem)) { - Type *old_array = base_type(elem); - soa_struct = alloc_type_struct(); - soa_struct->Struct.fields = array_make(heap_allocator(), old_array->Array.count); - soa_struct->Struct.tags = array_make(heap_allocator(), old_array->Array.count); - soa_struct->Struct.node = operand->expr; - soa_struct->Struct.soa_kind = StructSoa_Fixed; - soa_struct->Struct.soa_elem = elem; - soa_struct->Struct.soa_count = count; - - scope = create_scope(c->scope); - soa_struct->Struct.scope = scope; - - String params_xyzw[4] = { - str_lit("x"), - str_lit("y"), - str_lit("z"), - str_lit("w") - }; - - for (i64 i = 0; i < old_array->Array.count; i++) { - Type *array_type = alloc_type_array(old_array->Array.elem, count); - Token token = {}; - token.string = params_xyzw[i]; - - Entity *new_field = alloc_entity_field(scope, token, array_type, false, cast(i32)i); - soa_struct->Struct.fields[i] = new_field; - add_entity(c->checker, scope, nullptr, new_field); - add_entity_use(c, nullptr, new_field); - } - - } else { - GB_ASSERT(is_type_struct(elem)); - - Type *old_struct = base_type(elem); - soa_struct = alloc_type_struct(); - soa_struct->Struct.fields = array_make(heap_allocator(), old_struct->Struct.fields.count); - soa_struct->Struct.tags = array_make(heap_allocator(), old_struct->Struct.tags.count); - soa_struct->Struct.node = operand->expr; - soa_struct->Struct.soa_kind = StructSoa_Fixed; - soa_struct->Struct.soa_elem = elem; - soa_struct->Struct.soa_count = count; - - scope = create_scope(old_struct->Struct.scope->parent); - soa_struct->Struct.scope = scope; - - for_array(i, old_struct->Struct.fields) { - Entity *old_field = old_struct->Struct.fields[i]; - if (old_field->kind == Entity_Variable) { - Type *array_type = alloc_type_array(old_field->type, count); - Entity *new_field = alloc_entity_field(scope, old_field->token, array_type, false, old_field->Variable.field_src_index); - soa_struct->Struct.fields[i] = new_field; - add_entity(c->checker, scope, nullptr, new_field); - } else { - soa_struct->Struct.fields[i] = old_field; - } - - soa_struct->Struct.tags[i] = old_struct->Struct.tags[i]; - } - } - - Token token = {}; - token.string = str_lit("Base_Type"); - Entity *base_type_entity = alloc_entity_type_name(scope, token, elem, EntityState_Resolved); - add_entity(c->checker, scope, nullptr, base_type_entity); - - add_type_info_type(c, soa_struct); - - operand->type = soa_struct; - break; - } - - case BuiltinProc_alloca: - { - Operand sz = {}; - Operand al = {}; - - check_expr(c, &sz, ce->args[0]); - if (sz.mode == Addressing_Invalid) { - return false; - } - check_expr(c, &al, ce->args[1]); - if (al.mode == Addressing_Invalid) { - return false; - } - convert_to_typed(c, &sz, t_int); if (sz.mode == Addressing_Invalid) return false; - convert_to_typed(c, &al, t_int); if (al.mode == Addressing_Invalid) return false; - - if (!is_type_integer(sz.type) || !is_type_integer(al.type)) { - error(operand->expr, "Both parameters to '%.*s' must integers", LIT(builtin_name)); - return false; - } - - if (sz.mode == Addressing_Constant) { - i64 i_sz = exact_value_to_i64(sz.value); - if (i_sz < 0) { - error(sz.expr, "Size parameter to '%.*s' must be non-negative, got %lld", LIT(builtin_name), cast(long long)i_sz); - return false; - } - } - if (al.mode == Addressing_Constant) { - i64 i_al = exact_value_to_i64(al.value); - if (i_al < 0) { - error(al.expr, "Alignment parameter to '%.*s' must be non-negative, got %lld", LIT(builtin_name), cast(long long)i_al); - return false; - } - - if (i_al > 1<<29) { - error(al.expr, "Alignment parameter to '%.*s' must not exceed '1<<29', got %lld", LIT(builtin_name), cast(long long)i_al); - return false; - } - - if (!gb_is_power_of_two(cast(isize)i_al) && i_al != 0) { - error(al.expr, "Alignment parameter to '%.*s' must be a power of 2 or 0, got %lld", LIT(builtin_name), cast(long long)i_al); - return false; - } - } else { - error(al.expr, "Alignment parameter to '%.*s' must be constant", LIT(builtin_name)); - } - - operand->type = t_u8_ptr; - operand->mode = Addressing_Value; - break; - } - - - case BuiltinProc_cpu_relax: - operand->mode = Addressing_NoValue; - break; - - case BuiltinProc_trap: - case BuiltinProc_debug_trap: - if (!build_context.use_llvm_api) { - error(ce->args[0], "'%.*s' is not supported on this backend", LIT(builtin_procs[id].name)); - } - operand->mode = Addressing_NoValue; - break; - - case BuiltinProc_read_cycle_counter: - if (!build_context.use_llvm_api) { - error(ce->args[0], "'%.*s' is not supported on this backend", LIT(builtin_procs[id].name)); - } - operand->mode = Addressing_Value; - operand->type = t_i64; - break; - - case BuiltinProc_count_ones: - case BuiltinProc_trailing_zeros: - case BuiltinProc_reverse_bits: - if (!build_context.use_llvm_api) { - error(ce->args[0], "'%.*s' is not supported on this backend", LIT(builtin_procs[id].name)); - // continue anyway - } - { - Operand x = {}; - check_expr(c, &x, ce->args[0]); - if (x.mode == Addressing_Invalid) { - return false; - } - - if (!is_type_integer_like(x.type)) { - gbString xts = type_to_string(x.type); - error(x.expr, "Values passed to '%.*s' must be an integer-like type (integer, boolean, enum, bit_set), got %s", LIT(builtin_procs[id].name), xts); - gb_string_free(xts); - } else if (x.type == t_llvm_bool) { - gbString xts = type_to_string(x.type); - error(x.expr, "Invalid type passed to '%.*s', got %s", LIT(builtin_procs[id].name), xts); - gb_string_free(xts); - } - - operand->mode = Addressing_Value; - operand->type = default_type(x.type); - } - break; - - case BuiltinProc_byte_swap: - if (!build_context.use_llvm_api) { - error(ce->args[0], "'%.*s' is not supported on this backend", LIT(builtin_procs[id].name)); - // continue anyway - } - { - Operand x = {}; - check_expr(c, &x, ce->args[0]); - if (x.mode == Addressing_Invalid) { - return false; - } - - if (!is_type_integer_like(x.type) && !is_type_float(x.type)) { - gbString xts = type_to_string(x.type); - error(x.expr, "Values passed to '%.*s' must be an integer-like type (integer, boolean, enum, bit_set) or float, got %s", LIT(builtin_procs[id].name), xts); - gb_string_free(xts); - } else if (x.type == t_llvm_bool) { - gbString xts = type_to_string(x.type); - error(x.expr, "Invalid type passed to '%.*s', got %s", LIT(builtin_procs[id].name), xts); - gb_string_free(xts); - } - i64 sz = type_size_of(x.type); - if (sz < 2) { - gbString xts = type_to_string(x.type); - error(x.expr, "Type passed to '%.*s' must be at least 2 bytes, got %s with size of %lld", LIT(builtin_procs[id].name), xts, sz); - gb_string_free(xts); - } - - operand->mode = Addressing_Value; - operand->type = default_type(x.type); - } - break; - - case BuiltinProc_overflow_add: - case BuiltinProc_overflow_sub: - case BuiltinProc_overflow_mul: - if (!build_context.use_llvm_api) { - error(ce->args[0], "'%.*s' is not supported on this backend", LIT(builtin_procs[id].name)); - // continue anyway - } - { - Operand x = {}; - Operand y = {}; - check_expr(c, &x, ce->args[0]); - check_expr(c, &y, ce->args[1]); - if (x.mode == Addressing_Invalid) { - return false; - } - if (y.mode == Addressing_Invalid) { - return false; - } - convert_to_typed(c, &y, x.type); - convert_to_typed(c, &x, y.type); - if (is_type_untyped(x.type)) { - gbString xts = type_to_string(x.type); - error(x.expr, "Expected a typed integer for '%.*s', got %s", LIT(builtin_procs[id].name), xts); - gb_string_free(xts); - return false; - } - if (!is_type_integer(x.type)) { - gbString xts = type_to_string(x.type); - error(x.expr, "Expected an integer for '%.*s', got %s", LIT(builtin_procs[id].name), xts); - gb_string_free(xts); - return false; - } - Type *ct = core_type(x.type); - if (is_type_different_to_arch_endianness(ct)) { - GB_ASSERT(ct->kind == Type_Basic); - if (ct->Basic.flags & (BasicFlag_EndianLittle|BasicFlag_EndianBig)) { - gbString xts = type_to_string(x.type); - error(x.expr, "Expected an integer which does not specify the explicit endianness for '%.*s', got %s", LIT(builtin_procs[id].name), xts); - gb_string_free(xts); - return false; - } - } - - operand->mode = Addressing_Value; - operand->type = make_optional_ok_type(default_type(x.type), false); // Just reusing this procedure, it's not optional - } - break; - - case BuiltinProc_atomic_fence: - case BuiltinProc_atomic_fence_acq: - case BuiltinProc_atomic_fence_rel: - case BuiltinProc_atomic_fence_acqrel: - operand->mode = Addressing_NoValue; - break; - - case BuiltinProc_volatile_store: - /*fallthrough*/ - case BuiltinProc_atomic_store: - case BuiltinProc_atomic_store_rel: - case BuiltinProc_atomic_store_relaxed: - case BuiltinProc_atomic_store_unordered: - { - Type *elem = nullptr; - if (!is_type_normal_pointer(operand->type, &elem)) { - error(operand->expr, "Expected a pointer for '%.*s'", LIT(builtin_name)); - return false; - } - Operand x = {}; - check_expr_with_type_hint(c, &x, ce->args[1], elem); - check_assignment(c, &x, elem, builtin_name); - - operand->type = nullptr; - operand->mode = Addressing_NoValue; - break; - } - - case BuiltinProc_volatile_load: - /*fallthrough*/ - case BuiltinProc_atomic_load: - case BuiltinProc_atomic_load_acq: - case BuiltinProc_atomic_load_relaxed: - case BuiltinProc_atomic_load_unordered: - { - Type *elem = nullptr; - if (!is_type_normal_pointer(operand->type, &elem)) { - error(operand->expr, "Expected a pointer for '%.*s'", LIT(builtin_name)); - return false; - } - operand->type = elem; - operand->mode = Addressing_Value; - break; - } - - case BuiltinProc_atomic_add: - case BuiltinProc_atomic_add_acq: - case BuiltinProc_atomic_add_rel: - case BuiltinProc_atomic_add_acqrel: - case BuiltinProc_atomic_add_relaxed: - case BuiltinProc_atomic_sub: - case BuiltinProc_atomic_sub_acq: - case BuiltinProc_atomic_sub_rel: - case BuiltinProc_atomic_sub_acqrel: - case BuiltinProc_atomic_sub_relaxed: - case BuiltinProc_atomic_and: - case BuiltinProc_atomic_and_acq: - case BuiltinProc_atomic_and_rel: - case BuiltinProc_atomic_and_acqrel: - case BuiltinProc_atomic_and_relaxed: - case BuiltinProc_atomic_nand: - case BuiltinProc_atomic_nand_acq: - case BuiltinProc_atomic_nand_rel: - case BuiltinProc_atomic_nand_acqrel: - case BuiltinProc_atomic_nand_relaxed: - case BuiltinProc_atomic_or: - case BuiltinProc_atomic_or_acq: - case BuiltinProc_atomic_or_rel: - case BuiltinProc_atomic_or_acqrel: - case BuiltinProc_atomic_or_relaxed: - case BuiltinProc_atomic_xor: - case BuiltinProc_atomic_xor_acq: - case BuiltinProc_atomic_xor_rel: - case BuiltinProc_atomic_xor_acqrel: - case BuiltinProc_atomic_xor_relaxed: - case BuiltinProc_atomic_xchg: - case BuiltinProc_atomic_xchg_acq: - case BuiltinProc_atomic_xchg_rel: - case BuiltinProc_atomic_xchg_acqrel: - case BuiltinProc_atomic_xchg_relaxed: - { - Type *elem = nullptr; - if (!is_type_normal_pointer(operand->type, &elem)) { - error(operand->expr, "Expected a pointer for '%.*s'", LIT(builtin_name)); - return false; - } - Operand x = {}; - check_expr_with_type_hint(c, &x, ce->args[1], elem); - check_assignment(c, &x, elem, builtin_name); - - operand->type = elem; - operand->mode = Addressing_Value; - break; - } - - case BuiltinProc_atomic_cxchg: - case BuiltinProc_atomic_cxchg_acq: - case BuiltinProc_atomic_cxchg_rel: - case BuiltinProc_atomic_cxchg_acqrel: - case BuiltinProc_atomic_cxchg_relaxed: - case BuiltinProc_atomic_cxchg_failrelaxed: - case BuiltinProc_atomic_cxchg_failacq: - case BuiltinProc_atomic_cxchg_acq_failrelaxed: - case BuiltinProc_atomic_cxchg_acqrel_failrelaxed: - - case BuiltinProc_atomic_cxchgweak: - case BuiltinProc_atomic_cxchgweak_acq: - case BuiltinProc_atomic_cxchgweak_rel: - case BuiltinProc_atomic_cxchgweak_acqrel: - case BuiltinProc_atomic_cxchgweak_relaxed: - case BuiltinProc_atomic_cxchgweak_failrelaxed: - case BuiltinProc_atomic_cxchgweak_failacq: - case BuiltinProc_atomic_cxchgweak_acq_failrelaxed: - case BuiltinProc_atomic_cxchgweak_acqrel_failrelaxed: - { - Type *elem = nullptr; - if (!is_type_normal_pointer(operand->type, &elem)) { - error(operand->expr, "Expected a pointer for '%.*s'", LIT(builtin_name)); - return false; - } - Operand x = {}; - Operand y = {}; - check_expr_with_type_hint(c, &x, ce->args[1], elem); - check_expr_with_type_hint(c, &y, ce->args[2], elem); - check_assignment(c, &x, elem, builtin_name); - check_assignment(c, &y, elem, builtin_name); - - operand->mode = Addressing_Value; - operand->type = make_optional_ok_type(elem, /*typed*/false); - break; - } - break; - - case BuiltinProc_fixed_point_mul: - case BuiltinProc_fixed_point_div: - case BuiltinProc_fixed_point_mul_sat: - case BuiltinProc_fixed_point_div_sat: - { - if (!build_context.use_llvm_api) { - error(ce->args[0], "'%.*s' is not supported on this backend", LIT(builtin_procs[id].name)); - // continue anyway - } - - Operand x = {}; - Operand y = {}; - Operand z = {}; - check_expr(c, &x, ce->args[0]); - if (x.mode == Addressing_Invalid) { - return false; - } - check_expr(c, &y, ce->args[1]); - if (y.mode == Addressing_Invalid) { - return false; - } - convert_to_typed(c, &x, y.type); - if (x.mode == Addressing_Invalid) { - return false; - } - convert_to_typed(c, &y, x.type); - if (x.mode == Addressing_Invalid) { - return false; - } - if (!are_types_identical(x.type, y.type)) { - gbString xts = type_to_string(x.type); - gbString yts = type_to_string(y.type); - error(x.expr, "Mismatched types for '%.*s', %s vs %s", LIT(builtin_procs[id].name), xts, yts); - gb_string_free(yts); - gb_string_free(xts); - return false; - } - - if (!is_type_integer(x.type) || is_type_untyped(x.type)) { - gbString xts = type_to_string(x.type); - error(x.expr, "Expected an integer type for '%.*s', got %s", LIT(builtin_procs[id].name), xts); - gb_string_free(xts); - return false; - } - - check_expr(c, &z, ce->args[2]); - if (z.mode == Addressing_Invalid) { - return false; - } - if (z.mode != Addressing_Constant || !is_type_integer(z.type)) { - error(z.expr, "Expected a constant integer for the scale in '%.*s'", LIT(builtin_procs[id].name)); - return false; - } - i64 n = exact_value_to_i64(z.value); - if (n <= 0) { - error(z.expr, "Scale parameter in '%.*s' must be positive, got %lld", LIT(builtin_procs[id].name), n); - return false; - } - i64 sz = 8*type_size_of(x.type); - if (n > sz) { - error(z.expr, "Scale parameter in '%.*s' is larger than the base integer bit width, got %lld, expected a maximum of %lld", LIT(builtin_procs[id].name), n, sz); - return false; - } - - operand->type = x.type; - operand->mode = Addressing_Value; - } - break; - - - case BuiltinProc_expect: - if (!build_context.use_llvm_api) { - error(ce->args[0], "'%.*s' is not supported on this backend", LIT(builtin_procs[id].name)); - // continue anyway - } - { - Operand x = {}; - Operand y = {}; - check_expr(c, &x, ce->args[0]); - check_expr(c, &y, ce->args[1]); - if (x.mode == Addressing_Invalid) { - return false; - } - if (y.mode == Addressing_Invalid) { - return false; - } - convert_to_typed(c, &y, x.type); - convert_to_typed(c, &x, y.type); - if (!are_types_identical(x.type, y.type)) { - gbString xts = type_to_string(x.type); - gbString yts = type_to_string(y.type); - error(x.expr, "Mismatched types for '%.*s', %s vs %s", LIT(builtin_procs[id].name), xts, yts); - gb_string_free(yts); - gb_string_free(xts); - *operand = x; // minimize error propagation - return true; - } - - if (!is_type_integer_like(x.type)) { - gbString xts = type_to_string(x.type); - error(x.expr, "Values passed to '%.*s' must be an integer-like type (integer, boolean, enum, bit_set), got %s", LIT(builtin_procs[id].name), xts); - gb_string_free(xts); - *operand = x; - return true; - } - - if (y.mode != Addressing_Constant) { - error(y.expr, "Second argument to '%.*s' must be constant as it is the expected value", LIT(builtin_procs[id].name)); - } - - if (x.mode == Addressing_Constant) { - // NOTE(bill): just completely ignore this intrinsic entirely - *operand = x; - return true; - } - - operand->mode = Addressing_Value; - operand->type = x.type; - } - break; - - - - - case BuiltinProc_type_base_type: - if (operand->mode != Addressing_Type) { - error(operand->expr, "Expected a type for '%.*s'", LIT(builtin_name)); - } else { - operand->type = base_type(operand->type); - } - operand->mode = Addressing_Type; - break; - case BuiltinProc_type_core_type: - if (operand->mode != Addressing_Type) { - error(operand->expr, "Expected a type for '%.*s'", LIT(builtin_name)); - } else { - operand->type = core_type(operand->type); - } - operand->mode = Addressing_Type; - break; - case BuiltinProc_type_elem_type: - if (operand->mode != Addressing_Type) { - error(operand->expr, "Expected a type for '%.*s'", LIT(builtin_name)); - } else { - Type *bt = base_type(operand->type); - switch (bt->kind) { - case Type_Basic: - switch (bt->Basic.kind) { - case Basic_complex64: operand->type = t_f32; break; - case Basic_complex128: operand->type = t_f64; break; - case Basic_quaternion128: operand->type = t_f32; break; - case Basic_quaternion256: operand->type = t_f64; break; - } - break; - case Type_Pointer: operand->type = bt->Pointer.elem; break; - case Type_Array: operand->type = bt->Array.elem; break; - case Type_EnumeratedArray: operand->type = bt->EnumeratedArray.elem; break; - case Type_Slice: operand->type = bt->Slice.elem; break; - case Type_DynamicArray: operand->type = bt->DynamicArray.elem; break; - } - } - operand->mode = Addressing_Type; - break; - - - case BuiltinProc_type_is_boolean: - case BuiltinProc_type_is_integer: - case BuiltinProc_type_is_rune: - case BuiltinProc_type_is_float: - case BuiltinProc_type_is_complex: - case BuiltinProc_type_is_quaternion: - case BuiltinProc_type_is_string: - case BuiltinProc_type_is_typeid: - case BuiltinProc_type_is_any: - case BuiltinProc_type_is_endian_little: - case BuiltinProc_type_is_endian_big: - case BuiltinProc_type_is_unsigned: - case BuiltinProc_type_is_numeric: - case BuiltinProc_type_is_ordered: - case BuiltinProc_type_is_ordered_numeric: - case BuiltinProc_type_is_indexable: - case BuiltinProc_type_is_sliceable: - case BuiltinProc_type_is_comparable: - case BuiltinProc_type_is_simple_compare: - case BuiltinProc_type_is_dereferenceable: - case BuiltinProc_type_is_valid_map_key: - case BuiltinProc_type_is_named: - case BuiltinProc_type_is_pointer: - case BuiltinProc_type_is_array: - case BuiltinProc_type_is_slice: - case BuiltinProc_type_is_dynamic_array: - case BuiltinProc_type_is_map: - case BuiltinProc_type_is_struct: - case BuiltinProc_type_is_union: - case BuiltinProc_type_is_enum: - case BuiltinProc_type_is_proc: - case BuiltinProc_type_is_bit_field: - case BuiltinProc_type_is_bit_field_value: - case BuiltinProc_type_is_bit_set: - case BuiltinProc_type_is_simd_vector: - case BuiltinProc_type_is_specialized_polymorphic_record: - case BuiltinProc_type_is_unspecialized_polymorphic_record: - case BuiltinProc_type_has_nil: - GB_ASSERT(BuiltinProc__type_simple_boolean_begin < id && id < BuiltinProc__type_simple_boolean_end); - - operand->value = exact_value_bool(false); - if (operand->mode != Addressing_Type) { - gbString str = expr_to_string(ce->args[0]); - error(operand->expr, "Expected a type for '%.*s', got '%s'", LIT(builtin_name), str); - gb_string_free(str); - } else { - i32 i = id - cast(i32)BuiltinProc__type_simple_boolean_begin; - auto procedure = builtin_type_is_procs[i]; - GB_ASSERT_MSG(procedure != nullptr, "%.*s", LIT(builtin_name)); - bool ok = procedure(operand->type); - operand->value = exact_value_bool(ok); - } - operand->mode = Addressing_Constant; - operand->type = t_untyped_bool; - break; - - case BuiltinProc_type_has_field: - { - Operand op = {}; - Type *bt = check_type(c, ce->args[0]); - Type *type = base_type(bt); - if (type == nullptr || type == t_invalid) { - error(ce->args[0], "Expected a type for '%.*s'", LIT(builtin_name)); - return false; - } - Operand x = {}; - check_expr(c, &x, ce->args[1]); - - if (!is_type_string(x.type) || x.mode != Addressing_Constant || x.value.kind != ExactValue_String) { - error(ce->args[1], "Expected a const string for field argument"); - return false; - } - - String field_name = x.value.value_string; - - Selection sel = lookup_field(type, field_name, false); - operand->mode = Addressing_Constant; - operand->value = exact_value_bool(sel.index.count != 0); - operand->type = t_untyped_bool; - - break; - } - break; - - case BuiltinProc_type_is_specialization_of: - { - if (operand->mode != Addressing_Type) { - error(operand->expr, "Expected a type for '%.*s'", LIT(builtin_name)); - operand->mode = Addressing_Invalid; - operand->type = t_invalid; - return false; - } - Type *t = operand->type; - Type *s = nullptr; - - bool prev_ips = c->in_polymorphic_specialization; - c->in_polymorphic_specialization = true; - s = check_type(c, ce->args[1]); - c->in_polymorphic_specialization = prev_ips; - - if (s == t_invalid) { - error(ce->args[1], "Invalid specialization type for '%.*s'", LIT(builtin_name)); - operand->mode = Addressing_Invalid; - operand->type = t_invalid; - return false; - } - - operand->mode = Addressing_Constant; - operand->type = t_untyped_bool; - operand->value = exact_value_bool(check_type_specialization_to(c, s, t, false, false)); - - } - break; - - case BuiltinProc_type_struct_field_count: - operand->value = exact_value_i64(0); - if (operand->mode != Addressing_Type) { - error(operand->expr, "Expected a struct type for '%.*s'", LIT(builtin_name)); - } else if (!is_type_struct(operand->type)) { - error(operand->expr, "Expected a struct type for '%.*s'", LIT(builtin_name)); - } else { - Type *bt = base_type(operand->type); - operand->value = exact_value_i64(bt->Struct.fields.count); - } - operand->mode = Addressing_Constant; - operand->type = t_untyped_integer; - break; - - case BuiltinProc_type_proc_parameter_count: - operand->value = exact_value_i64(0); - if (operand->mode != Addressing_Type) { - error(operand->expr, "Expected a procedure type for '%.*s'", LIT(builtin_name)); - } else if (!is_type_proc(operand->type)) { - error(operand->expr, "Expected a procedure type for '%.*s'", LIT(builtin_name)); - } else { - Type *bt = base_type(operand->type); - operand->value = exact_value_i64(bt->Proc.param_count); - } - operand->mode = Addressing_Constant; - operand->type = t_untyped_integer; - break; - case BuiltinProc_type_proc_return_count: - operand->value = exact_value_i64(0); - if (operand->mode != Addressing_Type) { - error(operand->expr, "Expected a procedure type for '%.*s'", LIT(builtin_name)); - } else if (!is_type_proc(operand->type)) { - error(operand->expr, "Expected a procedure type for '%.*s'", LIT(builtin_name)); - } else { - Type *bt = base_type(operand->type); - operand->value = exact_value_i64(bt->Proc.result_count); - } - operand->mode = Addressing_Constant; - operand->type = t_untyped_integer; - break; - - case BuiltinProc_type_proc_parameter_type: - if (operand->mode != Addressing_Type || !is_type_proc(operand->type)) { - error(operand->expr, "Expected a procedure type for '%.*s'", LIT(builtin_name)); - return false; - } else { - if (is_type_polymorphic(operand->type)) { - error(operand->expr, "Expected a non-polymorphic procedure type for '%.*s'", LIT(builtin_name)); - return false; - } - - Operand op = {}; - check_expr(c, &op, ce->args[1]); - if (op.mode != Addressing_Constant && !is_type_integer(op.type)) { - error(op.expr, "Expected a constant integer for the index of procedure parameter value"); - return false; - } - - i64 index = exact_value_to_i64(op.value); - if (index < 0) { - error(op.expr, "Expected a non-negative integer for the index of procedure parameter value, got %lld", cast(long long)index); - return false; - } - - Entity *param = nullptr; - i64 count = 0; - - Type *bt = base_type(operand->type); - if (bt->kind == Type_Proc) { - count = bt->Proc.param_count; - if (index < count) { - param = bt->Proc.params->Tuple.variables[index]; - } - } - - if (index >= count) { - error(op.expr, "Index of procedure parameter value out of bounds, expected 0..<%lld, got %lld", cast(long long)count, cast(long long)index); - return false; - } - GB_ASSERT(param != nullptr); - switch (param->kind) { - case Entity_Constant: - operand->mode = Addressing_Constant; - operand->type = param->type; - operand->value = param->Constant.value; - break; - case Entity_TypeName: - case Entity_Variable: - operand->mode = Addressing_Type; - operand->type = param->type; - break; - default: - GB_PANIC("Unhandled procedure entity type %d", param->kind); - break; - } - - } - - break; - - case BuiltinProc_type_proc_return_type: - if (operand->mode != Addressing_Type || !is_type_proc(operand->type)) { - error(operand->expr, "Expected a procedure type for '%.*s'", LIT(builtin_name)); - return false; - } else { - if (is_type_polymorphic(operand->type)) { - error(operand->expr, "Expected a non-polymorphic procedure type for '%.*s'", LIT(builtin_name)); - return false; - } - - Operand op = {}; - check_expr(c, &op, ce->args[1]); - if (op.mode != Addressing_Constant && !is_type_integer(op.type)) { - error(op.expr, "Expected a constant integer for the index of procedure parameter value"); - return false; - } - - i64 index = exact_value_to_i64(op.value); - if (index < 0) { - error(op.expr, "Expected a non-negative integer for the index of procedure parameter value, got %lld", cast(long long)index); - return false; - } - - Entity *param = nullptr; - i64 count = 0; - - Type *bt = base_type(operand->type); - if (bt->kind == Type_Proc) { - count = bt->Proc.result_count; - if (index < count) { - param = bt->Proc.results->Tuple.variables[index]; - } - } - - if (index >= count) { - error(op.expr, "Index of procedure parameter value out of bounds, expected 0..<%lld, got %lld", cast(long long)count, cast(long long)index); - return false; - } - GB_ASSERT(param != nullptr); - switch (param->kind) { - case Entity_Constant: - operand->mode = Addressing_Constant; - operand->type = param->type; - operand->value = param->Constant.value; - break; - case Entity_TypeName: - case Entity_Variable: - operand->mode = Addressing_Type; - operand->type = param->type; - break; - default: - GB_PANIC("Unhandled procedure entity type %d", param->kind); - break; - } - - } - - break; - - case BuiltinProc_type_polymorphic_record_parameter_count: - operand->value = exact_value_i64(0); - if (operand->mode != Addressing_Type) { - error(operand->expr, "Expected a record type for '%.*s'", LIT(builtin_name)); - } else { - Type *bt = base_type(operand->type); - if (bt->kind == Type_Struct) { - if (bt->Struct.polymorphic_params != nullptr) { - operand->value = exact_value_i64(bt->Struct.polymorphic_params->Tuple.variables.count); - } - } else if (bt->kind == Type_Union) { - if (bt->Union.polymorphic_params != nullptr) { - operand->value = exact_value_i64(bt->Union.polymorphic_params->Tuple.variables.count); - } - } else { - error(operand->expr, "Expected a record type for '%.*s'", LIT(builtin_name)); - } - } - operand->mode = Addressing_Constant; - operand->type = t_untyped_integer; - break; - case BuiltinProc_type_polymorphic_record_parameter_value: - if (operand->mode != Addressing_Type) { - error(operand->expr, "Expected a record type for '%.*s'", LIT(builtin_name)); - return false; - } else if (!is_type_polymorphic_record_specialized(operand->type)) { - error(operand->expr, "Expected a specialized polymorphic record type for '%.*s'", LIT(builtin_name)); - return false; - } else { - Operand op = {}; - check_expr(c, &op, ce->args[1]); - if (op.mode != Addressing_Constant && !is_type_integer(op.type)) { - error(op.expr, "Expected a constant integer for the index of record parameter value"); - return false; - } - - i64 index = exact_value_to_i64(op.value); - if (index < 0) { - error(op.expr, "Expected a non-negative integer for the index of record parameter value, got %lld", cast(long long)index); - return false; - } - - Entity *param = nullptr; - i64 count = 0; - - Type *bt = base_type(operand->type); - if (bt->kind == Type_Struct) { - if (bt->Struct.polymorphic_params != nullptr) { - count = bt->Struct.polymorphic_params->Tuple.variables.count; - if (index < count) { - param = bt->Struct.polymorphic_params->Tuple.variables[cast(isize)index]; - } - } - } else if (bt->kind == Type_Union) { - if (bt->Union.polymorphic_params != nullptr) { - count = bt->Union.polymorphic_params->Tuple.variables.count; - if (index < count) { - param = bt->Union.polymorphic_params->Tuple.variables[cast(isize)index]; - } - } - } else { - error(operand->expr, "Expected a specialized polymorphic record type for '%.*s'", LIT(builtin_name)); - return false; - } - - if (index >= count) { - error(op.expr, "Index of record parameter value out of bounds, expected 0..<%lld, got %lld", cast(long long)count, cast(long long)index); - return false; - } - GB_ASSERT(param != nullptr); - switch (param->kind) { - case Entity_Constant: - operand->mode = Addressing_Constant; - operand->type = param->type; - operand->value = param->Constant.value; - break; - case Entity_TypeName: - operand->mode = Addressing_Type; - operand->type = param->type; - break; - default: - GB_PANIC("Unhandled polymorphic record type"); - break; - } - - } - - break; - - case BuiltinProc_type_field_index_of: - { - Operand op = {}; - Type *bt = check_type(c, ce->args[0]); - Type *type = base_type(bt); - if (type == nullptr || type == t_invalid) { - error(ce->args[0], "Expected a type for '%.*s'", LIT(builtin_name)); - return false; - } - Operand x = {}; - check_expr(c, &x, ce->args[1]); - - if (!is_type_string(x.type) || x.mode != Addressing_Constant || x.value.kind != ExactValue_String) { - error(ce->args[1], "Expected a const string for field argument"); - return false; - } - - String field_name = x.value.value_string; - - Selection sel = lookup_field(type, field_name, false); - if (sel.entity == nullptr) { - gbString type_str = type_to_string(bt); - error(ce->args[0], - "'%s' has no field named '%.*s'", type_str, LIT(field_name)); - gb_string_free(type_str); - return false; - } - if (sel.indirect) { - gbString type_str = type_to_string(bt); - error(ce->args[0], - "Field '%.*s' is embedded via a pointer in '%s'", LIT(field_name), type_str); - gb_string_free(type_str); - return false; - } - - operand->mode = Addressing_Constant; - operand->value = exact_value_u64(sel.index[0]); - operand->type = t_uintptr; - break; - } - break; - - case BuiltinProc_type_equal_proc: - { - Operand op = {}; - Type *bt = check_type(c, ce->args[0]); - Type *type = base_type(bt); - if (type == nullptr || type == t_invalid) { - error(ce->args[0], "Expected a type for '%.*s'", LIT(builtin_name)); - return false; - } - if (!is_type_comparable(type)) { - gbString t = type_to_string(type); - error(ce->args[0], "Expected a comparable type for '%.*s', got %s", LIT(builtin_name), t); - gb_string_free(t); - return false; - } - - operand->mode = Addressing_Value; - operand->type = t_equal_proc; - break; - } - - case BuiltinProc_type_hasher_proc: - { - Operand op = {}; - Type *bt = check_type(c, ce->args[0]); - Type *type = base_type(bt); - if (type == nullptr || type == t_invalid) { - error(ce->args[0], "Expected a type for '%.*s'", LIT(builtin_name)); - return false; - } - if (!is_type_valid_for_keys(type)) { - gbString t = type_to_string(type); - error(ce->args[0], "Expected a valid type for map keys for '%.*s', got %s", LIT(builtin_name), t); - gb_string_free(t); - return false; - } - - add_map_key_type_dependencies(c, type); - - operand->mode = Addressing_Value; - operand->type = t_hasher_proc; - break; - } - } - - return true; -} - - isize add_dependencies_from_unpacking(CheckerContext *c, Entity **lhs, isize lhs_count, isize tuple_index, isize tuple_count) { if (lhs != nullptr) { for (isize j = 0; (tuple_index + j) < lhs_count && j < tuple_count; j++) { -- cgit v1.2.3 From 6383714bffb05a34a5320a757e08dd73bf9a2b0c Mon Sep 17 00:00:00 2001 From: gingerBill Date: Sun, 25 Apr 2021 19:56:46 +0100 Subject: Remove old procedure ABI code --- src/check_expr.cpp | 8 - src/check_type.cpp | 618 --------------------------------------------------- src/checker.cpp | 4 - src/llvm_backend.cpp | 19 +- src/types.cpp | 4 - 5 files changed, 8 insertions(+), 645 deletions(-) (limited to 'src/check_expr.cpp') diff --git a/src/check_expr.cpp b/src/check_expr.cpp index 885a2eaa3..61cdf7822 100644 --- a/src/check_expr.cpp +++ b/src/check_expr.cpp @@ -103,10 +103,6 @@ CallArgumentData check_call_arguments (CheckerContext *c, Operand *operand, Ty Type * check_init_variable (CheckerContext *c, Entity *e, Operand *operand, String context_name); -Type *type_to_abi_compat_param_type(gbAllocator a, Type *original_type, ProcCallingConvention cc); -Type *type_to_abi_compat_result_type(gbAllocator a, Type *original_type, ProcCallingConvention cc); -bool abi_compat_return_by_pointer(gbAllocator a, ProcCallingConvention cc, Type *abi_return_type); -void set_procedure_abi_types(Type *type); void check_assignment_error_suggestion(CheckerContext *c, Operand *o, Type *type); void add_map_key_type_dependencies(CheckerContext *ctx, Type *key); @@ -1088,10 +1084,6 @@ bool is_polymorphic_type_assignable(CheckerContext *c, Type *poly, Type *source, if (!ok) return false; } - if (modify_type) { - set_procedure_abi_types(source); - } - return true; #endif } diff --git a/src/check_type.cpp b/src/check_type.cpp index e3aac161c..aef1ddc7a 100644 --- a/src/check_type.cpp +++ b/src/check_type.cpp @@ -1162,9 +1162,6 @@ Type *determine_type_from_polymorphic(CheckerContext *ctx, Type *poly_type, Oper } if (is_polymorphic_type_assignable(ctx, poly_type, operand.type, false, modify_type)) { - if (show_error) { - set_procedure_abi_types(poly_type); - } return poly_type; } if (show_error) { @@ -1767,623 +1764,8 @@ Type *check_get_results(CheckerContext *ctx, Scope *scope, Ast *_results) { return tuple; } -Array systemv_distribute_struct_fields(Type *t) { - Type *bt = core_type(t); - - - isize distributed_cap = 1; - if (bt->kind == Type_Struct) { - distributed_cap = bt->Struct.fields.count; - } - auto distributed = array_make(heap_allocator(), 0, distributed_cap); - - i64 sz = type_size_of(bt); - switch (bt->kind) { - case Type_Basic: - switch (bt->Basic.kind){ - case Basic_complex64: - array_add(&distributed, t_f32); - array_add(&distributed, t_f32); - break; - case Basic_complex128: - array_add(&distributed, t_f64); - array_add(&distributed, t_f64); - break; - case Basic_quaternion128: - array_add(&distributed, t_f32); - array_add(&distributed, t_f32); - array_add(&distributed, t_f32); - array_add(&distributed, t_f32); - break; - case Basic_quaternion256: - goto DEFAULT; - case Basic_string: - array_add(&distributed, t_u8_ptr); - array_add(&distributed, t_int); - break; - case Basic_any: - GB_ASSERT(type_size_of(t_uintptr) == type_size_of(t_typeid)); - array_add(&distributed, t_rawptr); - array_add(&distributed, t_uintptr); - break; - - case Basic_u128: - case Basic_i128: - if (build_context.ODIN_OS == "windows") { - array_add(&distributed, alloc_type_simd_vector(2, t_u64)); - } else { - array_add(&distributed, bt); - } - break; - - default: - goto DEFAULT; - } - break; - - case Type_Struct: - if (bt->Struct.is_raw_union) { - goto DEFAULT; - } else { - // IMPORTANT TOOD(bill): handle #packed structs correctly - // IMPORTANT TODO(bill): handle #align structs correctly - for_array(field_index, bt->Struct.fields) { - Entity *f = bt->Struct.fields[field_index]; - auto nested = systemv_distribute_struct_fields(f->type); - array_add_elems(&distributed, nested.data, nested.count); - array_free(&nested); - } - } - break; - - case Type_Array: - for (i64 i = 0; i < bt->Array.count; i++) { - array_add(&distributed, bt->Array.elem); - } - break; - - case Type_BitSet: - array_add(&distributed, bit_set_to_int(bt)); - break; - - case Type_Tuple: - GB_PANIC("Invalid struct field type"); - break; - - case Type_Slice: - array_add(&distributed, t_rawptr); - array_add(&distributed, t_int); - break; - - case Type_Union: - case Type_DynamicArray: - case Type_Map: - // NOTE(bill, 2019-10-10): Odin specific, don't worry about C calling convention yet - goto DEFAULT; - - case Type_Pointer: - case Type_Proc: - case Type_SimdVector: // TODO(bill): Is this correct logic? - default: - DEFAULT:; - if (sz > 0) { - array_add(&distributed, bt); - } - break; - } - - return distributed; -} - -Type *struct_type_from_systemv_distribute_struct_fields(Type *abi_type) { - GB_ASSERT(is_type_tuple(abi_type)); - Type *final_type = alloc_type_struct(); - final_type->Struct.fields = abi_type->Tuple.variables; - return final_type; -} - - -Type *handle_single_distributed_type_parameter(Array const &types, bool packed, isize *offset) { - GB_ASSERT(types.count > 0); - - if (types.count == 1) { - if (offset) *offset = 1; - - i64 sz = type_size_of(types[0]); - - if (is_type_float(types[0])) { - return types[0]; - } - switch (sz) { - case 0: - GB_PANIC("Zero sized type found!"); - case 1: return t_u8; - case 2: return t_u16; - case 4: return t_u32; - case 8: return t_u64; - default: - return types[0]; - } - } else if (types.count >= 2) { - if (types[0] == t_f32 && types[1] == t_f32) { - if (offset) *offset = 2; - return alloc_type_simd_vector(2, t_f32); - } else if (type_size_of(types[0]) == 8) { - if (offset) *offset = 1; - return types[0]; - } - - i64 total_size = 0; - isize i = 0; - if (packed) { - for (; i < types.count && total_size < 8; i += 1) { - Type *t = types[i]; - i64 s = type_size_of(t); - total_size += s; - } - } else { - for (; i < types.count && total_size < 8; i += 1) { - Type *t = types[i]; - i64 s = gb_max(type_size_of(t), 0); - i64 a = gb_max(type_align_of(t), 1); - isize ts = align_formula(total_size, a); - if (ts >= 8) { - break; - } - total_size = ts + s; - } - } - if (offset) *offset = i; - switch (total_size) { - case 1: return t_u8; - case 2: return t_u16; - case 4: return t_u32; - case 8: return t_u64; - } - return t_u64; - } - - return nullptr; -} - -Type *handle_struct_system_v_amd64_abi_type(Type *t) { - if (type_size_of(t) > 16) { - return alloc_type_pointer(t); - } - Type *original_type = t; - Type *bt = core_type(t); - t = base_type(t); - i64 size = type_size_of(bt); - - switch (t->kind) { - case Type_Slice: - case Type_Struct: - break; - - case Type_Basic: - switch (bt->Basic.kind) { - case Basic_string: - case Basic_any: - case Basic_complex64: - case Basic_complex128: - case Basic_quaternion128: - break; - default: - return original_type; - } - break; - - default: - return original_type; - } - - bool is_packed = false; - if (is_type_struct(bt)) { - is_packed = bt->Struct.is_packed; - } - - if (is_type_raw_union(bt)) { - // TODO(bill): Handle raw union correctly for - return t; - } else { - auto field_types = systemv_distribute_struct_fields(bt); - defer (array_free(&field_types)); - - GB_ASSERT(field_types.count <= 16); - - Type *final_type = nullptr; - - if (field_types.count == 0) { - final_type = t; - } else if (field_types.count == 1) { - final_type = field_types[0]; - } else { - if (size <= 8) { - isize offset = 0; - final_type = handle_single_distributed_type_parameter(field_types, is_packed, &offset); - } else { - isize offset = 0; - isize next_offset = 0; - Type *two_types[2] = {}; - - two_types[0] = handle_single_distributed_type_parameter(field_types, is_packed, &offset); - auto remaining = array_slice(field_types, offset, field_types.count); - two_types[1] = handle_single_distributed_type_parameter(remaining, is_packed, &next_offset); - GB_ASSERT(offset + next_offset == field_types.count); - - auto variables = array_make(heap_allocator(), 2); - variables[0] = alloc_entity_param(nullptr, empty_token, two_types[0], false, false); - variables[1] = alloc_entity_param(nullptr, empty_token, two_types[1], false, false); - final_type = alloc_type_tuple(); - final_type->Tuple.variables = variables; - if (t->kind == Type_Struct) { - // NOTE(bill): Make this packed - final_type->Tuple.is_packed = t->Struct.is_packed; - } - } - } - - - GB_ASSERT(final_type != nullptr); - i64 ftsz = type_size_of(final_type); - i64 otsz = type_size_of(original_type); - if (ftsz != otsz) { - // TODO(bill): Handle this case which will be caused by #packed most likely - switch (otsz) { - case 1: - case 2: - case 4: - case 8: - GB_PANIC("Incorrectly handled case for handle_struct_system_v_amd64_abi_type, %s %lld vs %s %lld", type_to_string(final_type), ftsz, type_to_string(original_type), otsz); - } - } - - return final_type; - } -} -Type *type_to_abi_compat_param_type(gbAllocator a, Type *original_type, ProcCallingConvention cc) { - Type *new_type = original_type; - if (is_type_boolean(original_type)) { - Type *t = core_type(base_type(new_type)); - if (t == t_bool) { - return t_llvm_bool; - } - return new_type; - } - - if (is_type_proc(original_type)) { - // NOTE(bill): Force a cast to prevent a possible type cycle - return t_rawptr; - } - - if (is_calling_convention_none(cc)) { - return new_type; - } - - if (build_context.ODIN_ARCH == "386") { - return new_type; - } - - if (is_type_simd_vector(original_type)) { - return new_type; - } - if (build_context.ODIN_ARCH == "amd64") { - bool is_128 = is_type_integer_128bit(original_type); - if (!is_128 && is_type_bit_set(original_type) && type_size_of(original_type) == 16) { - // is_128 = true; - } - if (is_128) { - if (build_context.ODIN_OS == "windows") { - return alloc_type_simd_vector(2, t_u64); - } else { - return original_type; - } - } - } - - if (build_context.ODIN_OS == "windows") { - // NOTE(bill): Changing the passing parameter value type is to match C's ABI - // IMPORTANT TODO(bill): This only matches the ABI on MSVC at the moment - // SEE: https://msdn.microsoft.com/en-us/library/zthk2dkh.aspx - - - Type *bt = core_type(original_type); - switch (bt->kind) { - // Okay to pass by value (usually) - // Especially the only Odin types - case Type_Basic: { - i64 sz = bt->Basic.size; - // if (sz > 8 && build_context.word_size < 8) { - if (sz > 8) { - new_type = alloc_type_pointer(original_type); - } - break; - } - case Type_Pointer: - if (is_type_struct(bt->Pointer.elem)) { - // Force to a raw pointer - new_type = t_rawptr; - } - break; - case Type_Proc: - new_type = t_rawptr; - break; // NOTE(bill): Just a pointer - - // Odin specific - case Type_Slice: - case Type_Array: - case Type_DynamicArray: - case Type_Map: - case Type_Union: - // Could be in C too - case Type_Struct: - { - i64 align = type_align_of(original_type); - i64 size = type_size_of(original_type); - - switch (8*size) { - case 8: new_type = t_u8; break; - case 16: new_type = t_u16; break; - case 32: new_type = t_u32; break; - case 64: new_type = t_u64; break; - default: - new_type = alloc_type_pointer(original_type); - break; - } - - break; - } - } - } else if (build_context.ODIN_OS == "linux" || - build_context.ODIN_OS == "darwin") { - Type *bt = core_type(original_type); - switch (bt->kind) { - // Okay to pass by value (usually) - // Especially the only Odin types - case Type_Basic: { - i64 sz = bt->Basic.size; - // if (sz > 8 && build_context.word_size < 8) { - if (sz > 8) { - new_type = alloc_type_pointer(original_type); - } - - break; - } - case Type_Pointer: break; - case Type_Proc: break; // NOTE(bill): Just a pointer - - default: { - i64 size = type_size_of(original_type); - if (size > 16) { - new_type = alloc_type_pointer(original_type); - } else if (build_context.ODIN_ARCH == "amd64") { - // NOTE(bill): System V AMD64 ABI - new_type = handle_struct_system_v_amd64_abi_type(bt); - if (are_types_identical(core_type(original_type), new_type)) { - new_type = original_type; - } - return new_type; - } - - break; - } - } - } else { - // IMPORTANT TODO(bill): figure out the ABI settings for Linux, OSX etc. for - // their architectures - } - - return new_type; -} - - -Type *type_to_abi_compat_result_type(gbAllocator a, Type *original_type, ProcCallingConvention cc) { - Type *new_type = original_type; - if (new_type == nullptr) { - return nullptr; - } - GB_ASSERT(is_type_tuple(original_type)); - - Type *single_type = reduce_tuple_to_single_type(original_type); - - if (cc == ProcCC_InlineAsm) { - return new_type; - } - - if (is_type_proc(single_type)) { - // NOTE(bill): Force a cast to prevent a possible type cycle - return t_rawptr; - } - - if (is_type_simd_vector(single_type)) { - return new_type; - } - - if (is_type_pointer(single_type)) { - // NOTE(bill): Force a cast to prevent a possible type cycle - return t_rawptr; - } - - if (build_context.ODIN_OS == "windows") { - if (build_context.ODIN_ARCH == "amd64") { - if (is_type_integer_128bit(single_type)) { - if (is_calling_convention_none(cc)) { - return original_type; - } else { - return alloc_type_simd_vector(2, t_u64); - } - } - } - - Type *bt = core_type(reduce_tuple_to_single_type(original_type)); - // NOTE(bill): This is just reversed engineered from LLVM IR output - switch (bt->kind) { - // Okay to pass by value - // Especially the only Odin types - case Type_Pointer: break; - case Type_Proc: break; // NOTE(bill): Just a pointer - case Type_Basic: break; - - - default: { - i64 align = type_align_of(original_type); - i64 size = type_size_of(original_type); - switch (8*size) { -#if 1 - case 8: new_type = t_u8; break; - case 16: new_type = t_u16; break; - case 32: new_type = t_u32; break; - case 64: new_type = t_u64; break; -#endif - } - - break; - } - } - } else if (build_context.ODIN_OS == "linux" || build_context.ODIN_OS == "darwin") { - if (build_context.ODIN_ARCH == "amd64") { - - } - } else { - // IMPORTANT TODO(bill): figure out the ABI settings for Linux, OSX etc. for - // their architectures - } - - if (is_type_integer_128bit(single_type)) { - if (build_context.word_size == 8) { - return original_type; - } - } - - - if (new_type != original_type) { - Type *tuple = alloc_type_tuple(); - auto variables = array_make(a, 0, 1); - array_add(&variables, alloc_entity_param(original_type->Tuple.variables[0]->scope, empty_token, new_type, false, false)); - tuple->Tuple.variables = variables; - new_type = tuple; - } - - if (cc == ProcCC_None) { - for_array(i, new_type->Tuple.variables) { - Type **tp = &new_type->Tuple.variables[i]->type; - Type *t = core_type(*tp); - if (t == t_bool) { - *tp = t_llvm_bool; - } - } - } - - new_type->cached_size = -1; - new_type->cached_align = -1; - return new_type; -} - -bool abi_compat_return_by_pointer(gbAllocator a, ProcCallingConvention cc, Type *abi_return_type) { - if (abi_return_type == nullptr) { - return false; - } - if (is_calling_convention_none(cc)) { - return false; - } - - Type *single_type = reduce_tuple_to_single_type(abi_return_type); - - if (is_type_simd_vector(single_type)) { - return false; - } - - if (build_context.word_size == 8) { - if (is_type_integer_128bit(single_type)) { - return false; - } - } - - if (build_context.ODIN_OS == "windows" || build_context.ODIN_OS == "linux" ) { - i64 size = 8*type_size_of(abi_return_type); - switch (size) { - case 0: - case 8: - case 16: - case 32: - case 64: - return false; - default: - return true; - } - } else { - if (is_type_integer_128bit(single_type)) { - return build_context.word_size < 8; - } - } - - - - return false; -} - -void set_procedure_abi_types(Type *type) { - type = base_type(type); - if (type->kind != Type_Proc) { - return; - } - - if (type->Proc.abi_types_set || type->flags & TypeFlag_InProcessOfCheckingABI) { - return; - } - - gbAllocator allocator = permanent_allocator(); - - u32 flags = type->flags; - type->flags |= TypeFlag_InProcessOfCheckingABI; - - type->Proc.abi_compat_params = array_make(allocator, cast(isize)type->Proc.param_count); - for (i32 i = 0; i < type->Proc.param_count; i++) { - Entity *e = type->Proc.params->Tuple.variables[i]; - if (e->kind == Entity_Variable) { - Type *original_type = e->type; - Type *new_type = type_to_abi_compat_param_type(allocator, original_type, type->Proc.calling_convention); - type->Proc.abi_compat_params[i] = new_type; - switch (type->Proc.calling_convention) { - case ProcCC_Odin: - case ProcCC_Contextless: - if (is_type_pointer(new_type) && !is_type_pointer(e->type) && !is_type_proc(e->type)) { - e->flags |= EntityFlag_ImplicitReference; - } - break; - } - - if (build_context.ODIN_OS == "linux" || - build_context.ODIN_OS == "darwin") { - if (is_type_pointer(new_type) & !is_type_pointer(e->type) && !is_type_proc(e->type)) { - e->flags |= EntityFlag_ByVal; - } - } - } - } - - for (i32 i = 0; i < type->Proc.param_count; i++) { - Entity *e = type->Proc.params->Tuple.variables[i]; - if (e->kind == Entity_Variable) { - set_procedure_abi_types(e->type); - } - } - for (i32 i = 0; i < type->Proc.result_count; i++) { - Entity *e = type->Proc.results->Tuple.variables[i]; - if (e->kind == Entity_Variable) { - set_procedure_abi_types(e->type); - } - } - - // NOTE(bill): The types are the same - type->Proc.abi_compat_result_type = type_to_abi_compat_result_type(allocator, type->Proc.results, type->Proc.calling_convention); - type->Proc.return_by_pointer = abi_compat_return_by_pointer(allocator, type->Proc.calling_convention, type->Proc.abi_compat_result_type); - - type->Proc.abi_types_set = true; - type->flags = flags; -} // NOTE(bill): 'operands' is for generating non generic procedure type bool check_procedure_type(CheckerContext *ctx, Type *type, Ast *proc_type_node, Array *operands) { diff --git a/src/checker.cpp b/src/checker.cpp index e74c6fc10..5a2203cfb 100644 --- a/src/checker.cpp +++ b/src/checker.cpp @@ -732,15 +732,11 @@ void init_universal(void) { add_global_type_entity(str_lit("byte"), &basic_types[Basic_u8]); { - void set_procedure_abi_types(Type *type); - Type *equal_args[2] = {t_rawptr, t_rawptr}; t_equal_proc = alloc_type_proc_from_types(equal_args, 2, t_bool, false, ProcCC_Contextless); - set_procedure_abi_types(t_equal_proc); Type *hasher_args[2] = {t_rawptr, t_uintptr}; t_hasher_proc = alloc_type_proc_from_types(hasher_args, 2, t_uintptr, false, ProcCC_Contextless); - set_procedure_abi_types(t_hasher_proc); } // Constants diff --git a/src/llvm_backend.cpp b/src/llvm_backend.cpp index 0d27b9c6f..3e7d858ed 100644 --- a/src/llvm_backend.cpp +++ b/src/llvm_backend.cpp @@ -2545,8 +2545,6 @@ lbProcedure *lb_create_procedure(lbModule *m, Entity *entity) { Type *pt = base_type(entity->type); GB_ASSERT(pt->kind == Type_Proc); - set_procedure_abi_types(entity->type); - p->type = entity->type; p->type_expr = decl->type_expr; p->body = pl->body; @@ -2845,6 +2843,14 @@ lbValue lb_value_param(lbProcedure *p, Entity *e, Type *abi_type, i32 index, lbP return res; } +Type *struct_type_from_systemv_distribute_struct_fields(Type *abi_type) { + GB_ASSERT(is_type_tuple(abi_type)); + Type *final_type = alloc_type_struct(); + final_type->Struct.fields = abi_type->Tuple.variables; + return final_type; +} + + lbValue lb_add_param(lbProcedure *p, Entity *e, Ast *expr, Type *abi_type, i32 index) { lbParamPasskind kind = lbParamPass_Value; lbValue v = lb_value_param(p, e, abi_type, index, &kind); @@ -3476,9 +3482,6 @@ void lb_build_nested_proc(lbProcedure *p, AstProcLit *pd, Entity *e) { name_len = gb_snprintf(name_text, name_len, "%.*s.%.*s-%d", LIT(p->name), LIT(pd_name), guid); String name = make_string(cast(u8 *)name_text, name_len-1); - set_procedure_abi_types(e->type); - - e->Procedure.link_name = name; lbProcedure *nested_proc = lb_create_procedure(p->module, e); @@ -3613,7 +3616,6 @@ void lb_build_constant_value_decl(lbProcedure *p, AstValueDecl *vd) { return; } - set_procedure_abi_types(e->type); e->Procedure.link_name = name; lbProcedure *nested_proc = lb_create_procedure(p->module, e); @@ -8201,8 +8203,6 @@ lbValue lb_emit_call(lbProcedure *p, lbValue value, Array const &args, LLVMBuildUnreachable(p->builder); }); - set_procedure_abi_types(pt); - bool is_c_vararg = pt->Proc.c_vararg; isize param_count = pt->Proc.param_count; if (is_c_vararg) { @@ -9584,7 +9584,6 @@ lbValue lb_build_call_expr(lbProcedure *p, Ast *expr) { Type *proc_type_ = base_type(value.type); GB_ASSERT(proc_type_->kind == Type_Proc); TypeProc *pt = &proc_type_->Proc; - set_procedure_abi_types(proc_type_); if (is_call_expr_field_value(ce)) { auto args = array_make(permanent_allocator(), pt->param_count); @@ -10765,8 +10764,6 @@ lbValue lb_generate_anonymous_proc_lit(lbModule *m, String const &prefix_name, A String name = make_string((u8 *)name_text, name_len-1); Type *type = type_of_expr(expr); - set_procedure_abi_types(type); - Token token = {}; token.pos = ast_token(expr).pos; diff --git a/src/types.cpp b/src/types.cpp index a5c5c2eb2..56081acc8 100644 --- a/src/types.cpp +++ b/src/types.cpp @@ -198,11 +198,8 @@ struct TypeProc { isize specialization_count; ProcCallingConvention calling_convention; i32 variadic_index; - Array abi_compat_params; - Type * abi_compat_result_type; // TODO(bill): Make this a flag set rather than bools bool variadic; - bool abi_types_set; bool require_results; bool c_vararg; bool is_polymorphic; @@ -317,7 +314,6 @@ enum TypeFlag : u32 { TypeFlag_Polymorphic = 1<<1, TypeFlag_PolySpecialized = 1<<2, TypeFlag_InProcessOfCheckingPolymorphic = 1<<3, - TypeFlag_InProcessOfCheckingABI = 1<<4, }; struct Type { -- cgit v1.2.3 From cb2e6ea31db90ca80314e5ff8ce8f43371fade7c Mon Sep 17 00:00:00 2001 From: gingerBill Date: Sun, 25 Apr 2021 20:03:05 +0100 Subject: Remove `use_llvm_api` related checks and other related things --- core/runtime/internal.odin | 40 ++++++++++------------------------------ core/sys/cpu/cpu.odin | 2 -- src/build_settings.cpp | 8 -------- src/check_builtin.cpp | 40 ---------------------------------------- src/check_expr.cpp | 4 ---- src/check_stmt.cpp | 3 --- src/checker.cpp | 24 +++--------------------- src/main.cpp | 1 - 8 files changed, 13 insertions(+), 109 deletions(-) (limited to 'src/check_expr.cpp') diff --git a/core/runtime/internal.odin b/core/runtime/internal.odin index 3c05fb6a7..e2f8c7287 100644 --- a/core/runtime/internal.odin +++ b/core/runtime/internal.odin @@ -107,22 +107,12 @@ mem_copy :: proc "contextless" (dst, src: rawptr, len: int) -> rawptr { } // NOTE(bill): This _must_ be implemented like C's memmove foreign _ { - when ODIN_USE_LLVM_API { - when size_of(rawptr) == 8 { - @(link_name="llvm.memmove.p0i8.p0i8.i64") - llvm_memmove :: proc "none" (dst, src: rawptr, len: int, is_volatile: bool = false) ---; - } else { - @(link_name="llvm.memmove.p0i8.p0i8.i32") - llvm_memmove :: proc "none" (dst, src: rawptr, len: int, is_volatile: bool = false) ---; - } + when size_of(rawptr) == 8 { + @(link_name="llvm.memmove.p0i8.p0i8.i64") + llvm_memmove :: proc "none" (dst, src: rawptr, len: int, is_volatile: bool = false) ---; } else { - when size_of(rawptr) == 8 { - @(link_name="llvm.memmove.p0i8.p0i8.i64") - llvm_memmove :: proc "none" (dst, src: rawptr, len: int, align: i32 = 1, is_volatile: bool = false) ---; - } else { - @(link_name="llvm.memmove.p0i8.p0i8.i32") - llvm_memmove :: proc "none" (dst, src: rawptr, len: int, align: i32 = 1, is_volatile: bool = false) ---; - } + @(link_name="llvm.memmove.p0i8.p0i8.i32") + llvm_memmove :: proc "none" (dst, src: rawptr, len: int, is_volatile: bool = false) ---; } } llvm_memmove(dst, src, len); @@ -135,22 +125,12 @@ mem_copy_non_overlapping :: proc "contextless" (dst, src: rawptr, len: int) -> r } // NOTE(bill): This _must_ be implemented like C's memcpy foreign _ { - when ODIN_USE_LLVM_API { - when size_of(rawptr) == 8 { - @(link_name="llvm.memcpy.p0i8.p0i8.i64") - llvm_memcpy :: proc "none" (dst, src: rawptr, len: int, is_volatile: bool = false) ---; - } else { - @(link_name="llvm.memcpy.p0i8.p0i8.i32") - llvm_memcpy :: proc "none" (dst, src: rawptr, len: int, is_volatile: bool = false) ---; - } + when size_of(rawptr) == 8 { + @(link_name="llvm.memcpy.p0i8.p0i8.i64") + llvm_memcpy :: proc "none" (dst, src: rawptr, len: int, is_volatile: bool = false) ---; } else { - when size_of(rawptr) == 8 { - @(link_name="llvm.memcpy.p0i8.p0i8.i64") - llvm_memcpy :: proc "none" (dst, src: rawptr, len: int, align: i32 = 1, is_volatile: bool = false) ---; - } else { - @(link_name="llvm.memcpy.p0i8.p0i8.i32") - llvm_memcpy :: proc "none" (dst, src: rawptr, len: int, align: i32 = 1, is_volatile: bool = false) ---; - } + @(link_name="llvm.memcpy.p0i8.p0i8.i32") + llvm_memcpy :: proc "none" (dst, src: rawptr, len: int, is_volatile: bool = false) ---; } } llvm_memcpy(dst, src, len); diff --git a/core/sys/cpu/cpu.odin b/core/sys/cpu/cpu.odin index b6f770aed..b99fe01d8 100644 --- a/core/sys/cpu/cpu.odin +++ b/core/sys/cpu/cpu.odin @@ -1,7 +1,5 @@ package sys_cpu -#assert(ODIN_USE_LLVM_API); - Cache_Line_Pad :: struct {_: [_cache_line_size]byte}; initialized: bool; diff --git a/src/build_settings.cpp b/src/build_settings.cpp index 0be18a0d4..461b1610c 100644 --- a/src/build_settings.cpp +++ b/src/build_settings.cpp @@ -204,8 +204,6 @@ struct BuildContext { bool ignore_warnings; bool warnings_as_errors; - bool use_llvm_api; - bool use_subsystem_windows; bool ignore_microsoft_magic; bool linker_map_file; @@ -782,8 +780,6 @@ void init_build_context(TargetMetrics *cross_target) { bc->link_flags = str_lit(" "); bc->opt_flags = str_lit(" "); - bc->use_llvm_api = true; - gbString llc_flags = gb_string_make_reserve(heap_allocator(), 64); if (bc->ODIN_DEBUG) { @@ -841,10 +837,6 @@ void init_build_context(TargetMetrics *cross_target) { bc->link_flags = str_lit("-arch arm64 "); break; } - if ((bc->command_kind & Command__does_build) != 0 && !bc->use_llvm_api) { - gb_printf_err("The arm64 architecture is only supported with -llvm-api\n");; - gb_exit(1); - } } else if (bc->metrics.arch == TargetArch_wasm32) { bc->link_flags = str_lit("--no-entry --export-table --export-all --allow-undefined "); diff --git a/src/check_builtin.cpp b/src/check_builtin.cpp index 5f4411b90..94e8dcee6 100644 --- a/src/check_builtin.cpp +++ b/src/check_builtin.cpp @@ -614,9 +614,6 @@ bool check_builtin_procedure(CheckerContext *c, Operand *operand, Ast *call, i32 } else if (type->kind == Type_SimdVector) { max_count = type->SimdVector.count; elem_type = type->SimdVector.elem; - if (!build_context.use_llvm_api) { - error(call, "'swizzle' with #simd vector is not supported on this backend"); - } } i64 arg_count = 0; @@ -1529,11 +1526,6 @@ bool check_builtin_procedure(CheckerContext *c, Operand *operand, Ast *call, i32 } case BuiltinProc_soa_zip: { - if (!build_context.use_llvm_api) { - error(call, "'soa_zip' is not supported with this backend"); - return false; - } - auto types = array_make(temporary_allocator(), 0, ce->args.count); auto names = array_make(temporary_allocator(), 0, ce->args.count); @@ -1681,11 +1673,6 @@ bool check_builtin_procedure(CheckerContext *c, Operand *operand, Ast *call, i32 } case BuiltinProc_soa_unzip: { - if (!build_context.use_llvm_api) { - error(call, "'soa_unzip' is not supported with this backend"); - return false; - } - Operand x = {}; check_expr(c, &x, ce->args[0]); if (x.mode == Addressing_Invalid) { @@ -1927,16 +1914,10 @@ bool check_builtin_procedure(CheckerContext *c, Operand *operand, Ast *call, i32 case BuiltinProc_trap: case BuiltinProc_debug_trap: - if (!build_context.use_llvm_api) { - error(ce->args[0], "'%.*s' is not supported on this backend", LIT(builtin_procs[id].name)); - } operand->mode = Addressing_NoValue; break; case BuiltinProc_read_cycle_counter: - if (!build_context.use_llvm_api) { - error(ce->args[0], "'%.*s' is not supported on this backend", LIT(builtin_procs[id].name)); - } operand->mode = Addressing_Value; operand->type = t_i64; break; @@ -1944,10 +1925,6 @@ bool check_builtin_procedure(CheckerContext *c, Operand *operand, Ast *call, i32 case BuiltinProc_count_ones: case BuiltinProc_trailing_zeros: case BuiltinProc_reverse_bits: - if (!build_context.use_llvm_api) { - error(ce->args[0], "'%.*s' is not supported on this backend", LIT(builtin_procs[id].name)); - // continue anyway - } { Operand x = {}; check_expr(c, &x, ce->args[0]); @@ -1971,10 +1948,6 @@ bool check_builtin_procedure(CheckerContext *c, Operand *operand, Ast *call, i32 break; case BuiltinProc_byte_swap: - if (!build_context.use_llvm_api) { - error(ce->args[0], "'%.*s' is not supported on this backend", LIT(builtin_procs[id].name)); - // continue anyway - } { Operand x = {}; check_expr(c, &x, ce->args[0]); @@ -2006,10 +1979,6 @@ bool check_builtin_procedure(CheckerContext *c, Operand *operand, Ast *call, i32 case BuiltinProc_overflow_add: case BuiltinProc_overflow_sub: case BuiltinProc_overflow_mul: - if (!build_context.use_llvm_api) { - error(ce->args[0], "'%.*s' is not supported on this backend", LIT(builtin_procs[id].name)); - // continue anyway - } { Operand x = {}; Operand y = {}; @@ -2189,11 +2158,6 @@ bool check_builtin_procedure(CheckerContext *c, Operand *operand, Ast *call, i32 case BuiltinProc_fixed_point_mul_sat: case BuiltinProc_fixed_point_div_sat: { - if (!build_context.use_llvm_api) { - error(ce->args[0], "'%.*s' is not supported on this backend", LIT(builtin_procs[id].name)); - // continue anyway - } - Operand x = {}; Operand y = {}; Operand z = {}; @@ -2255,10 +2219,6 @@ bool check_builtin_procedure(CheckerContext *c, Operand *operand, Ast *call, i32 case BuiltinProc_expect: - if (!build_context.use_llvm_api) { - error(ce->args[0], "'%.*s' is not supported on this backend", LIT(builtin_procs[id].name)); - // continue anyway - } { Operand x = {}; Operand y = {}; diff --git a/src/check_expr.cpp b/src/check_expr.cpp index 61cdf7822..2c83565a4 100644 --- a/src/check_expr.cpp +++ b/src/check_expr.cpp @@ -7903,10 +7903,6 @@ ExprKind check_expr_base_internal(CheckerContext *c, Operand *o, Ast *node, Type error(node, "Inline asm expressions are only allowed within a procedure body"); } - if (!build_context.use_llvm_api) { - error(node, "Inline asm expressions are only currently allowed with -llvm-api"); - } - auto param_types = array_make(heap_allocator(), ia->param_types.count); Type *return_type = nullptr; for_array(i, ia->param_types) { diff --git a/src/check_stmt.cpp b/src/check_stmt.cpp index cad2be85b..a3c9a529c 100644 --- a/src/check_stmt.cpp +++ b/src/check_stmt.cpp @@ -1795,9 +1795,6 @@ void check_stmt_internal(CheckerContext *ctx, Ast *node, u32 flags) { if (is_ptr) use_by_reference_for_value = true; array_add(&vals, t->Struct.soa_elem); array_add(&vals, t_int); - if (!build_context.use_llvm_api) { - error(operand.expr, "#soa structures do not yet support for in loop iteration"); - } } break; } diff --git a/src/checker.cpp b/src/checker.cpp index 5a2203cfb..ecd9b5ea4 100644 --- a/src/checker.cpp +++ b/src/checker.cpp @@ -755,7 +755,6 @@ void init_universal(void) { add_global_constant(str_lit("ODIN_DEBUG"), t_untyped_bool, exact_value_bool(bc->ODIN_DEBUG)); add_global_constant(str_lit("ODIN_DISABLE_ASSERT"), t_untyped_bool, exact_value_bool(bc->ODIN_DISABLE_ASSERT)); add_global_constant(str_lit("ODIN_DEFAULT_TO_NIL_ALLOCATOR"), t_untyped_bool, exact_value_bool(bc->ODIN_DEFAULT_TO_NIL_ALLOCATOR)); - add_global_constant(str_lit("ODIN_USE_LLVM_API"), t_untyped_bool, exact_value_bool(bc->use_llvm_api)); add_global_constant(str_lit("ODIN_NO_DYNAMIC_LITERALS"), t_untyped_bool, exact_value_bool(bc->no_dynamic_literals)); add_global_constant(str_lit("ODIN_TEST"), t_untyped_bool, exact_value_bool(bc->command_kind == Command_test)); @@ -1774,23 +1773,6 @@ void generate_minimum_dependency_set(Checker *c, Entity *start) { force_add_dependency_entity(c, c->info.runtime_package->scope, required_runtime_entities[i]); } - if (!build_context.use_llvm_api) { - String other_required_runtime_entities[] = { - str_lit("bswap_16"), - str_lit("bswap_32"), - str_lit("bswap_64"), - str_lit("bswap_128"), - - str_lit("bswap_f16"), - str_lit("bswap_f32"), - str_lit("bswap_f64"), - }; - - for (isize i = 0; i < gb_count_of(other_required_runtime_entities); i++) { - force_add_dependency_entity(c, c->info.runtime_package->scope, other_required_runtime_entities[i]); - } - } - if (build_context.no_crt) { String required_no_crt_entities[] = { // NOTE(bill): Only if these exist @@ -2741,7 +2723,7 @@ DECL_ATTRIBUTE_PROC(type_decl_attribute) { } } - if (valid && build_context.use_llvm_api) { + if (valid) { if (ac->atom_op_table == nullptr) { ac->atom_op_table = gb_alloc_item(permanent_allocator(), TypeAtomOpTable); } @@ -2800,7 +2782,7 @@ DECL_ATTRIBUTE_PROC(type_decl_attribute) { } } - if (valid && build_context.use_llvm_api) { + if (valid) { if (ac->atom_op_table == nullptr) { ac->atom_op_table = gb_alloc_item(permanent_allocator(), TypeAtomOpTable); } @@ -2882,7 +2864,7 @@ DECL_ATTRIBUTE_PROC(type_decl_attribute) { } } - if (valid && build_context.use_llvm_api) { + if (valid) { if (ac->atom_op_table == nullptr) { ac->atom_op_table = gb_alloc_item(permanent_allocator(), TypeAtomOpTable); } diff --git a/src/main.cpp b/src/main.cpp index 02a9b50f7..d2f84b29d 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1185,7 +1185,6 @@ bool parse_build_flags(Array args) { case BuildFlag_UseLLVMApi: gb_printf_err("-llvm-api flag is not required any more\n"); - build_context.use_llvm_api = true; bad_flags = true; break; -- cgit v1.2.3 From 1aa9c49172caedb57568c3d2f563981e5b558b0d Mon Sep 17 00:00:00 2001 From: gingerBill Date: Mon, 26 Apr 2021 19:17:25 +0100 Subject: Remove warning for "Redundant 'auto_cast' applied to expression" --- src/check_expr.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/check_expr.cpp') diff --git a/src/check_expr.cpp b/src/check_expr.cpp index 2c83565a4..6c4a78e53 100644 --- a/src/check_expr.cpp +++ b/src/check_expr.cpp @@ -7269,7 +7269,7 @@ ExprKind check_expr_base_internal(CheckerContext *c, Operand *o, Ast *node, Type if (build_context.vet) { error(node, "Redundant 'auto_cast' applied to expression"); } else { - warning(node, "Redundant 'auto_cast' applied to expression"); + // warning(node, "Redundant 'auto_cast' applied to expression"); } } -- cgit v1.2.3