mirror of
https://github.com/Ed94/Odin.git
synced 2026-08-06 23:58:50 +00:00
Add CheckerInfo API functions
This commit is contained in:
+5
-1
@@ -43,7 +43,11 @@ Type *check_init_variable(Checker *c, Entity *e, Operand *operand, String contex
|
|||||||
if (is_type_bit_field_value(t)) {
|
if (is_type_bit_field_value(t)) {
|
||||||
t = default_bit_field_value_type(t);
|
t = default_bit_field_value_type(t);
|
||||||
}
|
}
|
||||||
|
if (is_type_variant(t)) {
|
||||||
|
Type *st = base_type(t);
|
||||||
|
GB_ASSERT(st->Record.variant_parent != NULL);
|
||||||
|
t = st->Record.variant_parent;
|
||||||
|
}
|
||||||
GB_ASSERT(is_type_typed(t));
|
GB_ASSERT(is_type_typed(t));
|
||||||
e->type = t;
|
e->type = t;
|
||||||
}
|
}
|
||||||
|
|||||||
+46
-43
@@ -634,7 +634,7 @@ void check_struct_type(Checker *c, Type *struct_type, AstNode *node) {
|
|||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
void check_union_type(Checker *c, Type *union_type, AstNode *node) {
|
void check_union_type(Checker *c, Type *named_type, Type *union_type, AstNode *node) {
|
||||||
GB_ASSERT(is_type_union(union_type));
|
GB_ASSERT(is_type_union(union_type));
|
||||||
ast_node(ut, UnionType, node);
|
ast_node(ut, UnionType, node);
|
||||||
|
|
||||||
@@ -718,6 +718,9 @@ void check_union_type(Checker *c, Type *union_type, AstNode *node) {
|
|||||||
base_type->Record.field_count = field_count;
|
base_type->Record.field_count = field_count;
|
||||||
base_type->Record.names = make_names_field_for_record(c, c->context.scope);
|
base_type->Record.names = make_names_field_for_record(c, c->context.scope);
|
||||||
base_type->Record.node = dummy_struct;
|
base_type->Record.node = dummy_struct;
|
||||||
|
base_type->Record.variant_parent = named_type != NULL ? named_type : union_type;
|
||||||
|
base_type->Record.variant_index = variant_index;
|
||||||
|
|
||||||
|
|
||||||
type_set_offsets(c->allocator, base_type);
|
type_set_offsets(c->allocator, base_type);
|
||||||
|
|
||||||
@@ -1935,7 +1938,7 @@ bool check_type_internal(Checker *c, AstNode *e, Type **type, Type *named_type)
|
|||||||
*type = make_type_union(c->allocator);
|
*type = make_type_union(c->allocator);
|
||||||
set_base_type(named_type, *type);
|
set_base_type(named_type, *type);
|
||||||
check_open_scope(c, e);
|
check_open_scope(c, e);
|
||||||
check_union_type(c, *type, e);
|
check_union_type(c, named_type, *type, e);
|
||||||
check_close_scope(c);
|
check_close_scope(c);
|
||||||
(*type)->Record.node = e;
|
(*type)->Record.node = e;
|
||||||
return true;
|
return true;
|
||||||
@@ -3636,8 +3639,8 @@ bool check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id
|
|||||||
|
|
||||||
case BuiltinProc_len:
|
case BuiltinProc_len:
|
||||||
case BuiltinProc_cap: {
|
case BuiltinProc_cap: {
|
||||||
// len :: proc(Type) -> int
|
// proc len(Type) -> int
|
||||||
// cap :: proc(Type) -> int
|
// proc cap(Type) -> int
|
||||||
Type *op_type = type_deref(operand->type);
|
Type *op_type = type_deref(operand->type);
|
||||||
Type *type = t_int;
|
Type *type = t_int;
|
||||||
AddressingMode mode = Addressing_Invalid;
|
AddressingMode mode = Addressing_Invalid;
|
||||||
@@ -3682,7 +3685,7 @@ bool check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id
|
|||||||
} break;
|
} break;
|
||||||
|
|
||||||
case BuiltinProc_new: {
|
case BuiltinProc_new: {
|
||||||
// new :: proc(Type) -> ^Type
|
// proc new(Type) -> ^Type
|
||||||
Operand op = {};
|
Operand op = {};
|
||||||
check_expr_or_type(c, &op, ce->args[0]);
|
check_expr_or_type(c, &op, ce->args[0]);
|
||||||
Type *type = op.type;
|
Type *type = op.type;
|
||||||
@@ -3695,8 +3698,8 @@ bool check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id
|
|||||||
} break;
|
} break;
|
||||||
#if 0
|
#if 0
|
||||||
case BuiltinProc_new_slice: {
|
case BuiltinProc_new_slice: {
|
||||||
// new_slice :: proc(Type, len: int) -> []Type
|
// proc new_slice(Type, len: int) -> []Type
|
||||||
// new_slice :: proc(Type, len, cap: int) -> []Type
|
// proc new_slice(Type, len, cap: int) -> []Type
|
||||||
Operand op = {};
|
Operand op = {};
|
||||||
check_expr_or_type(c, &op, ce->args[0]);
|
check_expr_or_type(c, &op, ce->args[0]);
|
||||||
Type *type = op.type;
|
Type *type = op.type;
|
||||||
@@ -3733,8 +3736,8 @@ bool check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id
|
|||||||
} break;
|
} break;
|
||||||
#endif
|
#endif
|
||||||
case BuiltinProc_make: {
|
case BuiltinProc_make: {
|
||||||
// make :: proc(Type, len: int) -> Type
|
// proc make(Type, len: int) -> Type
|
||||||
// make :: proc(Type, len, cap: int) -> Type
|
// proc make(Type, len, cap: int) -> Type
|
||||||
Operand op = {};
|
Operand op = {};
|
||||||
check_expr_or_type(c, &op, ce->args[0]);
|
check_expr_or_type(c, &op, ce->args[0]);
|
||||||
Type *type = op.type;
|
Type *type = op.type;
|
||||||
@@ -3789,10 +3792,10 @@ bool check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id
|
|||||||
} break;
|
} break;
|
||||||
|
|
||||||
case BuiltinProc_free: {
|
case BuiltinProc_free: {
|
||||||
// free :: proc(^Type)
|
// proc free(^Type)
|
||||||
// free :: proc([]Type)
|
// proc free([]Type)
|
||||||
// free :: proc(string)
|
// proc free(string)
|
||||||
// free :: proc(map[K]T)
|
// proc free(map[K]T)
|
||||||
Type *type = operand->type;
|
Type *type = operand->type;
|
||||||
bool ok = false;
|
bool ok = false;
|
||||||
if (is_type_pointer(type)) {
|
if (is_type_pointer(type)) {
|
||||||
@@ -3820,8 +3823,8 @@ bool check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id
|
|||||||
|
|
||||||
|
|
||||||
case BuiltinProc_reserve: {
|
case BuiltinProc_reserve: {
|
||||||
// reserve :: proc([dynamic]Type, count: int) {
|
// proc reserve([dynamic]Type, count: int) {
|
||||||
// reserve :: proc(map[Key]Type, count: int) {
|
// proc reserve(map[Key]Type, count: int) {
|
||||||
Type *type = operand->type;
|
Type *type = operand->type;
|
||||||
if (!is_type_dynamic_array(type) && !is_type_dynamic_map(type)) {
|
if (!is_type_dynamic_array(type) && !is_type_dynamic_map(type)) {
|
||||||
gbString str = type_to_string(type);
|
gbString str = type_to_string(type);
|
||||||
@@ -3862,8 +3865,8 @@ bool check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id
|
|||||||
} break;
|
} break;
|
||||||
|
|
||||||
case BuiltinProc_append: {
|
case BuiltinProc_append: {
|
||||||
// append :: proc([dynamic]Type, item: ..Type)
|
// proc append([dynamic]Type, item: ..Type)
|
||||||
// append :: proc([]Type, item: ..Type)
|
// proc append([]Type, item: ..Type)
|
||||||
Operand prev_operand = *operand;
|
Operand prev_operand = *operand;
|
||||||
|
|
||||||
Type *type = operand->type;
|
Type *type = operand->type;
|
||||||
@@ -3910,7 +3913,7 @@ bool check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id
|
|||||||
} break;
|
} break;
|
||||||
|
|
||||||
case BuiltinProc_delete: {
|
case BuiltinProc_delete: {
|
||||||
// delete :: proc(map[Key]Value, key: Key)
|
// proc delete(map[Key]Value, key: Key)
|
||||||
Type *type = operand->type;
|
Type *type = operand->type;
|
||||||
if (!is_type_map(type)) {
|
if (!is_type_map(type)) {
|
||||||
gbString str = type_to_string(type);
|
gbString str = type_to_string(type);
|
||||||
@@ -3942,7 +3945,7 @@ bool check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id
|
|||||||
|
|
||||||
|
|
||||||
case BuiltinProc_size_of: {
|
case BuiltinProc_size_of: {
|
||||||
// size_of :: proc(Type) -> untyped int
|
// proc size_of(Type) -> untyped int
|
||||||
Type *type = check_type(c, ce->args[0]);
|
Type *type = check_type(c, ce->args[0]);
|
||||||
if (type == NULL || type == t_invalid) {
|
if (type == NULL || type == t_invalid) {
|
||||||
error_node(ce->args[0], "Expected a type for `size_of`");
|
error_node(ce->args[0], "Expected a type for `size_of`");
|
||||||
@@ -3956,7 +3959,7 @@ bool check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id
|
|||||||
} break;
|
} break;
|
||||||
|
|
||||||
case BuiltinProc_size_of_val:
|
case BuiltinProc_size_of_val:
|
||||||
// size_of_val :: proc(val: Type) -> untyped int
|
// proc size_of_val(val: Type) -> untyped int
|
||||||
check_assignment(c, operand, NULL, str_lit("argument of `size_of_val`"));
|
check_assignment(c, operand, NULL, str_lit("argument of `size_of_val`"));
|
||||||
if (operand->mode == Addressing_Invalid) {
|
if (operand->mode == Addressing_Invalid) {
|
||||||
return false;
|
return false;
|
||||||
@@ -3968,7 +3971,7 @@ bool check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case BuiltinProc_align_of: {
|
case BuiltinProc_align_of: {
|
||||||
// align_of :: proc(Type) -> untyped int
|
// proc align_of(Type) -> untyped int
|
||||||
Type *type = check_type(c, ce->args[0]);
|
Type *type = check_type(c, ce->args[0]);
|
||||||
if (type == NULL || type == t_invalid) {
|
if (type == NULL || type == t_invalid) {
|
||||||
error_node(ce->args[0], "Expected a type for `align_of`");
|
error_node(ce->args[0], "Expected a type for `align_of`");
|
||||||
@@ -3980,7 +3983,7 @@ bool check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id
|
|||||||
} break;
|
} break;
|
||||||
|
|
||||||
case BuiltinProc_align_of_val:
|
case BuiltinProc_align_of_val:
|
||||||
// align_of_val :: proc(val: Type) -> untyped int
|
// proc align_of_val(val: Type) -> untyped int
|
||||||
check_assignment(c, operand, NULL, str_lit("argument of `align_of_val`"));
|
check_assignment(c, operand, NULL, str_lit("argument of `align_of_val`"));
|
||||||
if (operand->mode == Addressing_Invalid) {
|
if (operand->mode == Addressing_Invalid) {
|
||||||
return false;
|
return false;
|
||||||
@@ -3992,7 +3995,7 @@ bool check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case BuiltinProc_offset_of: {
|
case BuiltinProc_offset_of: {
|
||||||
// offset_of :: proc(Type, field) -> untyped int
|
// proc offset_of(Type, field) -> untyped int
|
||||||
Operand op = {};
|
Operand op = {};
|
||||||
Type *bt = check_type(c, ce->args[0]);
|
Type *bt = check_type(c, ce->args[0]);
|
||||||
Type *type = base_type(bt);
|
Type *type = base_type(bt);
|
||||||
@@ -4036,7 +4039,7 @@ bool check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id
|
|||||||
} break;
|
} break;
|
||||||
|
|
||||||
case BuiltinProc_offset_of_val: {
|
case BuiltinProc_offset_of_val: {
|
||||||
// offset_of_val :: proc(val: expression) -> untyped int
|
// proc offset_of_val(val: expression) -> untyped int
|
||||||
AstNode *arg = unparen_expr(ce->args[0]);
|
AstNode *arg = unparen_expr(ce->args[0]);
|
||||||
if (arg->kind != AstNode_SelectorExpr) {
|
if (arg->kind != AstNode_SelectorExpr) {
|
||||||
gbString str = expr_to_string(arg);
|
gbString str = expr_to_string(arg);
|
||||||
@@ -4085,7 +4088,7 @@ bool check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id
|
|||||||
} break;
|
} break;
|
||||||
|
|
||||||
case BuiltinProc_type_of_val:
|
case BuiltinProc_type_of_val:
|
||||||
// type_of_val :: proc(val: Type) -> type(Type)
|
// proc type_of_val(val: Type) -> type(Type)
|
||||||
check_assignment(c, operand, NULL, str_lit("argument of `type_of_val`"));
|
check_assignment(c, operand, NULL, str_lit("argument of `type_of_val`"));
|
||||||
if (operand->mode == Addressing_Invalid || operand->mode == Addressing_Builtin) {
|
if (operand->mode == Addressing_Invalid || operand->mode == Addressing_Builtin) {
|
||||||
return false;
|
return false;
|
||||||
@@ -4099,7 +4102,7 @@ bool check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id
|
|||||||
|
|
||||||
|
|
||||||
case BuiltinProc_type_info: {
|
case BuiltinProc_type_info: {
|
||||||
// type_info :: proc(Type) -> ^Type_Info
|
// proc type_info(Type) -> ^Type_Info
|
||||||
if (c->context.scope->is_global) {
|
if (c->context.scope->is_global) {
|
||||||
compiler_error("`type_info` Cannot be declared within a #shared_global_scope due to how the internals of the compiler works");
|
compiler_error("`type_info` Cannot be declared within a #shared_global_scope due to how the internals of the compiler works");
|
||||||
}
|
}
|
||||||
@@ -4120,7 +4123,7 @@ bool check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id
|
|||||||
} break;
|
} break;
|
||||||
|
|
||||||
case BuiltinProc_type_info_of_val: {
|
case BuiltinProc_type_info_of_val: {
|
||||||
// type_info_of_val :: proc(val: Type) -> ^Type_Info
|
// proc type_info_of_val(val: Type) -> ^Type_Info
|
||||||
if (c->context.scope->is_global) {
|
if (c->context.scope->is_global) {
|
||||||
compiler_error("`type_info` Cannot be declared within a #shared_global_scope due to how the internals of the compiler works");
|
compiler_error("`type_info` Cannot be declared within a #shared_global_scope due to how the internals of the compiler works");
|
||||||
}
|
}
|
||||||
@@ -4138,7 +4141,7 @@ bool check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id
|
|||||||
} break;
|
} break;
|
||||||
|
|
||||||
case BuiltinProc_compile_assert:
|
case BuiltinProc_compile_assert:
|
||||||
// compile_assert :: proc(cond: bool) -> bool
|
// proc compile_assert(cond: bool) -> bool
|
||||||
|
|
||||||
if (!is_type_boolean(operand->type) && operand->mode != Addressing_Constant) {
|
if (!is_type_boolean(operand->type) && operand->mode != Addressing_Constant) {
|
||||||
gbString str = expr_to_string(ce->args[0]);
|
gbString str = expr_to_string(ce->args[0]);
|
||||||
@@ -4157,7 +4160,7 @@ bool check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case BuiltinProc_assert:
|
case BuiltinProc_assert:
|
||||||
// assert :: proc(cond: bool) -> bool
|
// proc assert(cond: bool) -> bool
|
||||||
|
|
||||||
if (!is_type_boolean(operand->type)) {
|
if (!is_type_boolean(operand->type)) {
|
||||||
gbString str = expr_to_string(ce->args[0]);
|
gbString str = expr_to_string(ce->args[0]);
|
||||||
@@ -4171,7 +4174,7 @@ bool check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case BuiltinProc_panic:
|
case BuiltinProc_panic:
|
||||||
// panic :: proc(msg: string)
|
// proc panic(msg: string)
|
||||||
|
|
||||||
if (!is_type_string(operand->type)) {
|
if (!is_type_string(operand->type)) {
|
||||||
gbString str = expr_to_string(ce->args[0]);
|
gbString str = expr_to_string(ce->args[0]);
|
||||||
@@ -4184,7 +4187,7 @@ bool check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case BuiltinProc_copy: {
|
case BuiltinProc_copy: {
|
||||||
// copy :: proc(x, y: []Type) -> int
|
// proc copy(x, y: []Type) -> int
|
||||||
Type *dest_type = NULL, *src_type = NULL;
|
Type *dest_type = NULL, *src_type = NULL;
|
||||||
|
|
||||||
Type *d = base_type(operand->type);
|
Type *d = base_type(operand->type);
|
||||||
@@ -4226,7 +4229,7 @@ bool check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id
|
|||||||
} break;
|
} break;
|
||||||
|
|
||||||
case BuiltinProc_swizzle: {
|
case BuiltinProc_swizzle: {
|
||||||
// swizzle :: proc(v: {N}T, T..) -> {M}T
|
// proc swizzle(v: {N}T, T..) -> {M}T
|
||||||
Type *vector_type = base_type(operand->type);
|
Type *vector_type = base_type(operand->type);
|
||||||
if (!is_type_vector(vector_type)) {
|
if (!is_type_vector(vector_type)) {
|
||||||
gbString type_str = type_to_string(operand->type);
|
gbString type_str = type_to_string(operand->type);
|
||||||
@@ -4280,7 +4283,7 @@ bool check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id
|
|||||||
} break;
|
} break;
|
||||||
|
|
||||||
case BuiltinProc_complex: {
|
case BuiltinProc_complex: {
|
||||||
// complex :: proc(real, imag: float_type) -> complex_type
|
// proc complex(real, imag: float_type) -> complex_type
|
||||||
Operand x = *operand;
|
Operand x = *operand;
|
||||||
Operand y = {};
|
Operand y = {};
|
||||||
|
|
||||||
@@ -4340,8 +4343,8 @@ bool check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id
|
|||||||
|
|
||||||
case BuiltinProc_real:
|
case BuiltinProc_real:
|
||||||
case BuiltinProc_imag: {
|
case BuiltinProc_imag: {
|
||||||
// real :: proc(x: type) -> float_type
|
// proc real(x: type) -> float_type
|
||||||
// imag :: proc(x: type) -> float_type
|
// proc imag(x: type) -> float_type
|
||||||
|
|
||||||
Operand *x = operand;
|
Operand *x = operand;
|
||||||
if (is_type_untyped(x->type)) {
|
if (is_type_untyped(x->type)) {
|
||||||
@@ -4383,7 +4386,7 @@ bool check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id
|
|||||||
} break;
|
} break;
|
||||||
|
|
||||||
case BuiltinProc_conj: {
|
case BuiltinProc_conj: {
|
||||||
// conj :: proc(x: type) -> type
|
// proc conj(x: type) -> type
|
||||||
Operand *x = operand;
|
Operand *x = operand;
|
||||||
if (is_type_complex(x->type)) {
|
if (is_type_complex(x->type)) {
|
||||||
if (x->mode == Addressing_Constant) {
|
if (x->mode == Addressing_Constant) {
|
||||||
@@ -4405,8 +4408,8 @@ bool check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id
|
|||||||
} break;
|
} break;
|
||||||
|
|
||||||
case BuiltinProc_slice_ptr: {
|
case BuiltinProc_slice_ptr: {
|
||||||
// slice_ptr :: proc(a: ^T, len: int) -> []T
|
// proc slice_ptr(a: ^T, len: int) -> []T
|
||||||
// slice_ptr :: proc(a: ^T, len, cap: int) -> []T
|
// proc slice_ptr(a: ^T, len, cap: int) -> []T
|
||||||
// ^T cannot be rawptr
|
// ^T cannot be rawptr
|
||||||
Type *ptr_type = base_type(operand->type);
|
Type *ptr_type = base_type(operand->type);
|
||||||
if (!is_type_pointer(ptr_type)) {
|
if (!is_type_pointer(ptr_type)) {
|
||||||
@@ -4448,7 +4451,7 @@ bool check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id
|
|||||||
} break;
|
} break;
|
||||||
|
|
||||||
case BuiltinProc_slice_to_bytes: {
|
case BuiltinProc_slice_to_bytes: {
|
||||||
// slice_to_bytes :: proc(a: []T) -> []u8
|
// proc slice_to_bytes(a: []T) -> []u8
|
||||||
Type *slice_type = base_type(operand->type);
|
Type *slice_type = base_type(operand->type);
|
||||||
if (!is_type_slice(slice_type)) {
|
if (!is_type_slice(slice_type)) {
|
||||||
gbString type_str = type_to_string(operand->type);
|
gbString type_str = type_to_string(operand->type);
|
||||||
@@ -4462,7 +4465,7 @@ bool check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id
|
|||||||
} break;
|
} break;
|
||||||
|
|
||||||
case BuiltinProc_min: {
|
case BuiltinProc_min: {
|
||||||
// min :: proc(a, b: ordered) -> ordered
|
// proc min(a, b: ordered) -> ordered
|
||||||
Type *type = base_type(operand->type);
|
Type *type = base_type(operand->type);
|
||||||
if (!is_type_ordered(type) || !(is_type_numeric(type) || is_type_string(type))) {
|
if (!is_type_ordered(type) || !(is_type_numeric(type) || is_type_string(type))) {
|
||||||
gbString type_str = type_to_string(operand->type);
|
gbString type_str = type_to_string(operand->type);
|
||||||
@@ -4528,7 +4531,7 @@ bool check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id
|
|||||||
} break;
|
} break;
|
||||||
|
|
||||||
case BuiltinProc_max: {
|
case BuiltinProc_max: {
|
||||||
// min :: proc(a, b: ordered) -> ordered
|
// proc min(a, b: ordered) -> ordered
|
||||||
Type *type = base_type(operand->type);
|
Type *type = base_type(operand->type);
|
||||||
if (!is_type_ordered(type) || !(is_type_numeric(type) || is_type_string(type))) {
|
if (!is_type_ordered(type) || !(is_type_numeric(type) || is_type_string(type))) {
|
||||||
gbString type_str = type_to_string(operand->type);
|
gbString type_str = type_to_string(operand->type);
|
||||||
@@ -4596,7 +4599,7 @@ bool check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id
|
|||||||
} break;
|
} break;
|
||||||
|
|
||||||
case BuiltinProc_abs: {
|
case BuiltinProc_abs: {
|
||||||
// abs :: proc(n: numeric) -> numeric
|
// proc abs(n: numeric) -> numeric
|
||||||
if (!is_type_numeric(operand->type) && !is_type_vector(operand->type)) {
|
if (!is_type_numeric(operand->type) && !is_type_vector(operand->type)) {
|
||||||
gbString type_str = type_to_string(operand->type);
|
gbString type_str = type_to_string(operand->type);
|
||||||
error_node(call, "Expected a numeric type to `abs`, got `%s`", type_str);
|
error_node(call, "Expected a numeric type to `abs`, got `%s`", type_str);
|
||||||
@@ -4632,7 +4635,7 @@ bool check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id
|
|||||||
} break;
|
} break;
|
||||||
|
|
||||||
case BuiltinProc_clamp: {
|
case BuiltinProc_clamp: {
|
||||||
// clamp :: proc(a, min, max: ordered) -> ordered
|
// proc clamp(a, min, max: ordered) -> ordered
|
||||||
Type *type = base_type(operand->type);
|
Type *type = base_type(operand->type);
|
||||||
if (!is_type_ordered(type) || !(is_type_numeric(type) || is_type_string(type))) {
|
if (!is_type_ordered(type) || !(is_type_numeric(type) || is_type_string(type))) {
|
||||||
gbString type_str = type_to_string(operand->type);
|
gbString type_str = type_to_string(operand->type);
|
||||||
|
|||||||
+38
-3
@@ -757,7 +757,6 @@ void destroy_checker(Checker *c) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Entity *entity_of_ident(CheckerInfo *i, AstNode *identifier) {
|
Entity *entity_of_ident(CheckerInfo *i, AstNode *identifier) {
|
||||||
if (identifier->kind == AstNode_Ident) {
|
if (identifier->kind == AstNode_Ident) {
|
||||||
Entity **found = map_get(&i->definitions, hash_pointer(identifier));
|
Entity **found = map_get(&i->definitions, hash_pointer(identifier));
|
||||||
@@ -772,7 +771,6 @@ Entity *entity_of_ident(CheckerInfo *i, AstNode *identifier) {
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
TypeAndValue type_and_value_of_expr(CheckerInfo *i, AstNode *expression) {
|
TypeAndValue type_and_value_of_expr(CheckerInfo *i, AstNode *expression) {
|
||||||
TypeAndValue result = {};
|
TypeAndValue result = {};
|
||||||
TypeAndValue *found = map_get(&i->types, hash_pointer(expression));
|
TypeAndValue *found = map_get(&i->types, hash_pointer(expression));
|
||||||
@@ -780,7 +778,6 @@ TypeAndValue type_and_value_of_expr(CheckerInfo *i, AstNode *expression) {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Type *type_of_expr(CheckerInfo *i, AstNode *expr) {
|
Type *type_of_expr(CheckerInfo *i, AstNode *expr) {
|
||||||
TypeAndValue tav = type_and_value_of_expr(i, expr);
|
TypeAndValue tav = type_and_value_of_expr(i, expr);
|
||||||
if (tav.mode != Addressing_Invalid) {
|
if (tav.mode != Addressing_Invalid) {
|
||||||
@@ -796,6 +793,41 @@ Type *type_of_expr(CheckerInfo *i, AstNode *expr) {
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Entity *implicit_entity_of_node(CheckerInfo *i, AstNode *clause) {
|
||||||
|
Entity **found = map_get(&i->implicits, hash_pointer(clause));
|
||||||
|
if (found != NULL) {
|
||||||
|
return *found;
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
DeclInfo *decl_info_of_entity(CheckerInfo *i, Entity *e) {
|
||||||
|
if (e != NULL) {
|
||||||
|
DeclInfo **found = map_get(&i->entities, hash_pointer(e));
|
||||||
|
if (found != NULL) {
|
||||||
|
return *found;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
DeclInfo *decl_info_of_ident(CheckerInfo *i, AstNode *ident) {
|
||||||
|
return decl_info_of_entity(i, entity_of_ident(i, ident));
|
||||||
|
}
|
||||||
|
|
||||||
|
AstFile *ast_file_of_filename(CheckerInfo *i, String filename) {
|
||||||
|
AstFile **found = map_get(&i->files, hash_string(filename));
|
||||||
|
if (found != NULL) {
|
||||||
|
return *found;
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void add_untyped(CheckerInfo *i, AstNode *expression, bool lhs, AddressingMode mode, Type *basic_type, ExactValue value) {
|
void add_untyped(CheckerInfo *i, AstNode *expression, bool lhs, AddressingMode mode, Type *basic_type, ExactValue value) {
|
||||||
map_set(&i->untyped, hash_pointer(expression), make_expr_info(lhs, mode, basic_type, value));
|
map_set(&i->untyped, hash_pointer(expression), make_expr_info(lhs, mode, basic_type, value));
|
||||||
@@ -906,6 +938,9 @@ void add_implicit_entity(Checker *c, AstNode *node, Entity *e) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void add_type_info_type(Checker *c, Type *t) {
|
void add_type_info_type(Checker *c, Type *t) {
|
||||||
if (t == NULL) {
|
if (t == NULL) {
|
||||||
return;
|
return;
|
||||||
|
|||||||
+308
-338
@@ -1137,9 +1137,8 @@ irBlock *ir_new_block(irProcedure *proc, AstNode *node, char *label) {
|
|||||||
Scope **found = map_get(&proc->module->info->scopes, hash_pointer(node));
|
Scope **found = map_get(&proc->module->info->scopes, hash_pointer(node));
|
||||||
if (found) {
|
if (found) {
|
||||||
scope = *found;
|
scope = *found;
|
||||||
} else {
|
|
||||||
GB_PANIC("Block scope not found for %.*s", LIT(ast_node_strings[node->kind]));
|
|
||||||
}
|
}
|
||||||
|
GB_ASSERT_MSG(scope != NULL, "Block scope not found for %.*s", LIT(ast_node_strings[node->kind]));
|
||||||
}
|
}
|
||||||
|
|
||||||
irValue *v = ir_alloc_value(proc->module->allocator, irValue_Block);
|
irValue *v = ir_alloc_value(proc->module->allocator, irValue_Block);
|
||||||
@@ -1290,9 +1289,8 @@ irValue *ir_add_local(irProcedure *proc, Entity *e, AstNode *expr) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
irValue *ir_add_local_for_identifier(irProcedure *proc, AstNode *name, bool zero_initialized) {
|
irValue *ir_add_local_for_identifier(irProcedure *proc, AstNode *name, bool zero_initialized) {
|
||||||
Entity **found = map_get(&proc->module->info->definitions, hash_pointer(name));
|
Entity *e = entity_of_ident(proc->module->info, name);
|
||||||
if (found) {
|
if (e != NULL) {
|
||||||
Entity *e = *found;
|
|
||||||
ir_emit_comment(proc, e->token.string);
|
ir_emit_comment(proc, e->token.string);
|
||||||
return ir_add_local(proc, e, name);
|
return ir_add_local(proc, e, name);
|
||||||
}
|
}
|
||||||
@@ -3431,7 +3429,7 @@ String ir_mangle_name(irGen *s, String path, Entity *e) {
|
|||||||
irModule *m = &s->module;
|
irModule *m = &s->module;
|
||||||
CheckerInfo *info = m->info;
|
CheckerInfo *info = m->info;
|
||||||
gbAllocator a = m->allocator;
|
gbAllocator a = m->allocator;
|
||||||
AstFile *file = *map_get(&info->files, hash_string(path));
|
AstFile *file = ast_file_of_filename(info, path);
|
||||||
|
|
||||||
char *str = gb_alloc_array(a, char, path.len+1);
|
char *str = gb_alloc_array(a, char, path.len+1);
|
||||||
gb_memmove(str, path.text, path.len);
|
gb_memmove(str, path.text, path.len);
|
||||||
@@ -3500,9 +3498,7 @@ void ir_mangle_add_sub_type_name(irModule *m, Entity *field, String parent) {
|
|||||||
|
|
||||||
irBranchBlocks ir_lookup_branch_blocks(irProcedure *proc, AstNode *ident) {
|
irBranchBlocks ir_lookup_branch_blocks(irProcedure *proc, AstNode *ident) {
|
||||||
GB_ASSERT(ident->kind == AstNode_Ident);
|
GB_ASSERT(ident->kind == AstNode_Ident);
|
||||||
Entity **found = map_get(&proc->module->info->uses, hash_pointer(ident));
|
Entity *e = entity_of_ident(proc->module->info, ident);
|
||||||
GB_ASSERT(found != NULL);
|
|
||||||
Entity *e = *found;
|
|
||||||
GB_ASSERT(e->kind == Entity_Label);
|
GB_ASSERT(e->kind == Entity_Label);
|
||||||
for_array(i, proc->branch_blocks) {
|
for_array(i, proc->branch_blocks) {
|
||||||
irBranchBlocks *b = &proc->branch_blocks[i];
|
irBranchBlocks *b = &proc->branch_blocks[i];
|
||||||
@@ -3618,270 +3614,9 @@ bool is_double_pointer(Type *t) {
|
|||||||
return is_type_pointer(td);
|
return is_type_pointer(td);
|
||||||
}
|
}
|
||||||
|
|
||||||
irValue *ir_build_expr(irProcedure *proc, AstNode *expr) {
|
irValue *ir_build_builtin_proc(irProcedure *proc, AstNode *expr, TypeAndValue tv, Entity *e) {
|
||||||
expr = unparen_expr(expr);
|
ast_node(ce, CallExpr, expr);
|
||||||
|
|
||||||
TypeAndValue tv = type_and_value_of_expr(proc->module->info, expr);
|
|
||||||
GB_ASSERT(tv.mode != Addressing_Invalid);
|
|
||||||
|
|
||||||
if (tv.value.kind != ExactValue_Invalid) {
|
|
||||||
// NOTE(bill): Edge case
|
|
||||||
if (tv.value.kind != ExactValue_Compound &&
|
|
||||||
is_type_vector(tv.type)) {
|
|
||||||
Type *elem = base_vector_type(tv.type);
|
|
||||||
ExactValue value = convert_exact_value_for_type(tv.value, elem);
|
|
||||||
irValue *x = ir_add_module_constant(proc->module, elem, value);
|
|
||||||
return ir_emit_conv(proc, x, tv.type);
|
|
||||||
}
|
|
||||||
|
|
||||||
return ir_add_module_constant(proc->module, tv.type, tv.value);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (tv.mode == Addressing_Variable) {
|
|
||||||
return ir_addr_load(proc, ir_build_addr(proc, expr));
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (expr->kind) {
|
|
||||||
case_ast_node(bl, BasicLit, expr);
|
|
||||||
TokenPos pos = bl->pos;
|
|
||||||
GB_PANIC("Non-constant basic literal %.*s(%td:%td) - %.*s", LIT(pos.file), pos.line, pos.column, LIT(token_strings[bl->kind]));
|
|
||||||
case_end;
|
|
||||||
|
|
||||||
case_ast_node(bd, BasicDirective, expr);
|
|
||||||
TokenPos pos = bd->token.pos;
|
|
||||||
GB_PANIC("Non-constant basic literal %.*s(%td:%td) - %.*s", LIT(pos.file), pos.line, pos.column, LIT(bd->name));
|
|
||||||
case_end;
|
|
||||||
|
|
||||||
case_ast_node(i, Implicit, expr);
|
|
||||||
return ir_addr_load(proc, ir_build_addr(proc, expr));
|
|
||||||
case_end;
|
|
||||||
|
|
||||||
case_ast_node(i, Ident, expr);
|
|
||||||
Entity *e = *map_get(&proc->module->info->uses, hash_pointer(expr));
|
|
||||||
if (e->kind == Entity_Builtin) {
|
|
||||||
Token token = ast_node_token(expr);
|
|
||||||
GB_PANIC("TODO(bill): ir_build_single_expr Entity_Builtin `%.*s`\n"
|
|
||||||
"\t at %.*s(%td:%td)", LIT(builtin_procs[e->Builtin.id].name),
|
|
||||||
LIT(token.pos.file), token.pos.line, token.pos.column);
|
|
||||||
return NULL;
|
|
||||||
} else if (e->kind == Entity_Nil) {
|
|
||||||
return ir_value_nil(proc->module->allocator, tv.type);
|
|
||||||
}
|
|
||||||
|
|
||||||
irValue **found = map_get(&proc->module->values, hash_pointer(e));
|
|
||||||
if (found) {
|
|
||||||
irValue *v = *found;
|
|
||||||
if (v->kind == irValue_Proc) {
|
|
||||||
return v;
|
|
||||||
}
|
|
||||||
// if (e->kind == Entity_Variable && e->Variable.param) {
|
|
||||||
// return v;
|
|
||||||
// }
|
|
||||||
return ir_emit_load(proc, v);
|
|
||||||
} else if (e != NULL && e->kind == Entity_Variable) {
|
|
||||||
return ir_addr_load(proc, ir_build_addr(proc, expr));
|
|
||||||
}
|
|
||||||
GB_PANIC("NULL value for expression from identifier: %.*s", LIT(i->string));
|
|
||||||
return NULL;
|
|
||||||
case_end;
|
|
||||||
|
|
||||||
case_ast_node(re, RunExpr, expr);
|
|
||||||
// TODO(bill): Run Expression
|
|
||||||
return ir_build_expr(proc, re->expr);
|
|
||||||
case_end;
|
|
||||||
|
|
||||||
case_ast_node(de, DerefExpr, expr);
|
|
||||||
return ir_addr_load(proc, ir_build_addr(proc, expr));
|
|
||||||
case_end;
|
|
||||||
|
|
||||||
case_ast_node(se, SelectorExpr, expr);
|
|
||||||
TypeAndValue tav = type_and_value_of_expr(proc->module->info, expr);
|
|
||||||
GB_ASSERT(tav.mode != Addressing_Invalid);
|
|
||||||
return ir_addr_load(proc, ir_build_addr(proc, expr));
|
|
||||||
case_end;
|
|
||||||
|
|
||||||
case_ast_node(te, TernaryExpr, expr);
|
|
||||||
ir_emit_comment(proc, str_lit("TernaryExpr"));
|
|
||||||
|
|
||||||
Array<irValue *> edges = {};
|
|
||||||
array_init(&edges, proc->module->allocator, 2);
|
|
||||||
|
|
||||||
GB_ASSERT(te->y != NULL);
|
|
||||||
irBlock *then = ir_new_block(proc, NULL, "if.then");
|
|
||||||
irBlock *done = ir_new_block(proc, NULL, "if.done"); // NOTE(bill): Append later
|
|
||||||
irBlock *else_ = ir_new_block(proc, NULL, "if.else");
|
|
||||||
|
|
||||||
irValue *cond = ir_build_cond(proc, te->cond, then, else_);
|
|
||||||
ir_start_block(proc, then);
|
|
||||||
|
|
||||||
Type *type = type_of_expr(proc->module->info, expr);
|
|
||||||
|
|
||||||
ir_open_scope(proc);
|
|
||||||
array_add(&edges, ir_emit_conv(proc, ir_build_expr(proc, te->x), type));
|
|
||||||
ir_close_scope(proc, irDeferExit_Default, NULL);
|
|
||||||
|
|
||||||
ir_emit_jump(proc, done);
|
|
||||||
ir_start_block(proc, else_);
|
|
||||||
|
|
||||||
ir_open_scope(proc);
|
|
||||||
array_add(&edges, ir_emit_conv(proc, ir_build_expr(proc, te->y), type));
|
|
||||||
ir_close_scope(proc, irDeferExit_Default, NULL);
|
|
||||||
|
|
||||||
ir_emit_jump(proc, done);
|
|
||||||
ir_start_block(proc, done);
|
|
||||||
|
|
||||||
return ir_emit(proc, ir_instr_phi(proc, edges, type));
|
|
||||||
case_end;
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
case_ast_node(ie, IfExpr, expr);
|
|
||||||
ir_emit_comment(proc, str_lit("IfExpr"));
|
|
||||||
if (ie->init != NULL) {
|
|
||||||
irBlock *init = ir_new_block(proc, expr, "if.init");
|
|
||||||
ir_emit_jump(proc, init);
|
|
||||||
ir_start_block(proc, init);
|
|
||||||
ir_build_stmt(proc, ie->init);
|
|
||||||
}
|
|
||||||
|
|
||||||
Array<irValue *> edges = {};
|
|
||||||
array_init(&edges, proc->module->allocator, 2);
|
|
||||||
|
|
||||||
GB_ASSERT(ie->else_expr != NULL);
|
|
||||||
irBlock *then = ir_new_block(proc, expr, "if.then");
|
|
||||||
irBlock *done = ir_new_block(proc, expr, "if.done"); // NOTE(bill): Append later
|
|
||||||
irBlock *else_ = ir_new_block(proc, ie->else_expr, "if.else");
|
|
||||||
|
|
||||||
irValue *cond = ir_build_cond(proc, ie->cond, then, else_);
|
|
||||||
ir_start_block(proc, then);
|
|
||||||
|
|
||||||
ir_open_scope(proc);
|
|
||||||
array_add(&edges, ir_build_expr(proc, ie->body));
|
|
||||||
ir_close_scope(proc, irDeferExit_Default, NULL);
|
|
||||||
|
|
||||||
ir_emit_jump(proc, done);
|
|
||||||
ir_start_block(proc, else_);
|
|
||||||
|
|
||||||
ir_open_scope(proc);
|
|
||||||
array_add(&edges, ir_build_expr(proc, ie->else_expr));
|
|
||||||
ir_close_scope(proc, irDeferExit_Default, NULL);
|
|
||||||
|
|
||||||
ir_emit_jump(proc, done);
|
|
||||||
ir_start_block(proc, done);
|
|
||||||
|
|
||||||
Type *type = type_of_expr(proc->module->info, expr);
|
|
||||||
|
|
||||||
return ir_emit(proc, ir_instr_phi(proc, edges, type));
|
|
||||||
case_end;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
case_ast_node(ta, TypeAssertion, expr);
|
|
||||||
TokenPos pos = ast_node_token(expr).pos;
|
|
||||||
Type *type = tv.type;
|
|
||||||
irValue *e = ir_build_expr(proc, ta->expr);
|
|
||||||
Type *t = type_deref(ir_type(e));
|
|
||||||
if (is_type_union(t)) {
|
|
||||||
ir_emit_comment(proc, str_lit("cast - union_cast"));
|
|
||||||
return ir_emit_union_cast(proc, e, type, pos);
|
|
||||||
} else if (is_type_any(t)) {
|
|
||||||
ir_emit_comment(proc, str_lit("cast - any_cast"));
|
|
||||||
return ir_emit_any_cast(proc, e, type, pos);
|
|
||||||
} else {
|
|
||||||
GB_PANIC("TODO(bill): type assertion %s", type_to_string(ir_type(e)));
|
|
||||||
}
|
|
||||||
case_end;
|
|
||||||
|
|
||||||
case_ast_node(ue, UnaryExpr, expr);
|
|
||||||
switch (ue->op.kind) {
|
|
||||||
case Token_And:
|
|
||||||
return ir_emit_ptr_offset(proc, ir_build_addr(proc, ue->expr).addr, v_zero); // Make a copy of the pointer
|
|
||||||
default:
|
|
||||||
return ir_emit_unary_arith(proc, ue->op.kind, ir_build_expr(proc, ue->expr), tv.type);
|
|
||||||
}
|
|
||||||
case_end;
|
|
||||||
|
|
||||||
case_ast_node(be, BinaryExpr, expr);
|
|
||||||
irValue *left = ir_build_expr(proc, be->left);
|
|
||||||
Type *type = default_type(tv.type);
|
|
||||||
|
|
||||||
switch (be->op.kind) {
|
|
||||||
case Token_Add:
|
|
||||||
case Token_Sub:
|
|
||||||
case Token_Mul:
|
|
||||||
case Token_Quo:
|
|
||||||
case Token_Mod:
|
|
||||||
case Token_ModMod:
|
|
||||||
case Token_And:
|
|
||||||
case Token_Or:
|
|
||||||
case Token_Xor:
|
|
||||||
case Token_AndNot:
|
|
||||||
case Token_Shl:
|
|
||||||
case Token_Shr: {
|
|
||||||
irValue *right = ir_build_expr(proc, be->right);
|
|
||||||
return ir_emit_arith(proc, be->op.kind, left, right, type);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
case Token_CmpEq:
|
|
||||||
case Token_NotEq:
|
|
||||||
case Token_Lt:
|
|
||||||
case Token_LtEq:
|
|
||||||
case Token_Gt:
|
|
||||||
case Token_GtEq: {
|
|
||||||
irValue *right = ir_build_expr(proc, be->right);
|
|
||||||
irValue *cmp = ir_emit_comp(proc, be->op.kind, left, right);
|
|
||||||
return ir_emit_conv(proc, cmp, type);
|
|
||||||
} break;
|
|
||||||
|
|
||||||
case Token_CmpAnd:
|
|
||||||
case Token_CmpOr:
|
|
||||||
return ir_emit_logical_binary_expr(proc, expr);
|
|
||||||
|
|
||||||
default:
|
|
||||||
GB_PANIC("Invalid binary expression");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case_end;
|
|
||||||
|
|
||||||
case_ast_node(pl, ProcLit, expr);
|
|
||||||
// NOTE(bill): Generate a new name
|
|
||||||
// parent$count
|
|
||||||
isize name_len = proc->name.len + 1 + 8 + 1;
|
|
||||||
u8 *name_text = gb_alloc_array(proc->module->allocator, u8, name_len);
|
|
||||||
name_len = gb_snprintf(cast(char *)name_text, name_len, "%.*s$%d", LIT(proc->name), cast(i32)proc->children.count);
|
|
||||||
String name = make_string(name_text, name_len-1);
|
|
||||||
|
|
||||||
Type *type = type_of_expr(proc->module->info, expr);
|
|
||||||
irValue *value = ir_value_procedure(proc->module->allocator,
|
|
||||||
proc->module, NULL, type, pl->type, pl->body, name);
|
|
||||||
|
|
||||||
value->Proc.tags = pl->tags;
|
|
||||||
value->Proc.parent = proc;
|
|
||||||
|
|
||||||
array_add(&proc->children, &value->Proc);
|
|
||||||
array_add(&proc->module->procs_to_generate, value);
|
|
||||||
|
|
||||||
return value;
|
|
||||||
case_end;
|
|
||||||
|
|
||||||
|
|
||||||
case_ast_node(cl, CompoundLit, expr);
|
|
||||||
return ir_addr_load(proc, ir_build_addr(proc, expr));
|
|
||||||
case_end;
|
|
||||||
|
|
||||||
|
|
||||||
case_ast_node(ce, CallExpr, expr);
|
|
||||||
if (map_get(&proc->module->info->types, hash_pointer(ce->proc))->mode == Addressing_Type) {
|
|
||||||
GB_ASSERT(ce->args.count == 1);
|
|
||||||
irValue *x = ir_build_expr(proc, ce->args[0]);
|
|
||||||
irValue *y = ir_emit_conv(proc, x, tv.type);
|
|
||||||
return y;
|
|
||||||
}
|
|
||||||
|
|
||||||
AstNode *p = unparen_expr(ce->proc);
|
|
||||||
if (p->kind == AstNode_Ident) {
|
|
||||||
Entity **found = map_get(&proc->module->info->uses, hash_pointer(p));
|
|
||||||
if (found && (*found)->kind == Entity_Builtin) {
|
|
||||||
Entity *e = *found;
|
|
||||||
switch (e->Builtin.id) {
|
switch (e->Builtin.id) {
|
||||||
case BuiltinProc_type_info: {
|
case BuiltinProc_type_info: {
|
||||||
Type *t = default_type(type_of_expr(proc->module->info, ce->args[0]));
|
Type *t = default_type(type_of_expr(proc->module->info, ce->args[0]));
|
||||||
@@ -3954,62 +3689,39 @@ irValue *ir_build_expr(irProcedure *proc, AstNode *expr) {
|
|||||||
case BuiltinProc_new: {
|
case BuiltinProc_new: {
|
||||||
ir_emit_comment(proc, str_lit("new"));
|
ir_emit_comment(proc, str_lit("new"));
|
||||||
// new :: proc(Type) -> ^Type
|
// new :: proc(Type) -> ^Type
|
||||||
gbAllocator allocator = proc->module->allocator;
|
gbAllocator a = proc->module->allocator;
|
||||||
|
|
||||||
Type *type = type_of_expr(proc->module->info, ce->args[0]);
|
Type *type = type_of_expr(proc->module->info, ce->args[0]);
|
||||||
Type *ptr_type = make_type_pointer(allocator, type);
|
Type *allocation_type = type;
|
||||||
|
i32 variant_index = 0;
|
||||||
|
if (is_type_struct(type)) {
|
||||||
|
Type *st = base_type(type);
|
||||||
|
if (st->Record.variant_parent != NULL) {
|
||||||
|
allocation_type = st->Record.variant_parent;
|
||||||
|
variant_index = st->Record.variant_index;
|
||||||
|
GB_ASSERT(allocation_type != NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Type *ptr_type = make_type_pointer(a, type);
|
||||||
|
|
||||||
i64 s = type_size_of(allocator, type);
|
i64 size = type_size_of(a, allocation_type);
|
||||||
i64 a = type_align_of(allocator, type);
|
i64 align = type_align_of(a, allocation_type);
|
||||||
|
|
||||||
irValue **args = gb_alloc_array(allocator, irValue *, 2);
|
irValue **args = gb_alloc_array(a, irValue *, 2);
|
||||||
args[0] = ir_const_int(allocator, s);
|
args[0] = ir_const_int(a, size);
|
||||||
args[1] = ir_const_int(allocator, a);
|
args[1] = ir_const_int(a, align);
|
||||||
irValue *call = ir_emit_global_call(proc, "alloc_align", args, 2);
|
irValue *call = ir_emit_global_call(proc, "alloc_align", args, 2);
|
||||||
irValue *v = ir_emit_conv(proc, call, ptr_type);
|
irValue *v = ir_emit_conv(proc, call, ptr_type);
|
||||||
|
if (type != allocation_type) {
|
||||||
|
Type *u = base_type(allocation_type);
|
||||||
|
Type *uptr_type = make_type_pointer(a, u);
|
||||||
|
irValue *parent = ir_emit_conv(proc, call, uptr_type);
|
||||||
|
irValue *tag_ptr = ir_emit_union_tag_ptr(proc, parent);
|
||||||
|
ir_emit_store(proc, tag_ptr, ir_const_int(a, variant_index));
|
||||||
|
}
|
||||||
return v;
|
return v;
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
#if 0
|
|
||||||
case BuiltinProc_new_slice: {
|
|
||||||
ir_emit_comment(proc, str_lit("new_slice"));
|
|
||||||
// new_slice :: proc(Type, len: int) -> []Type
|
|
||||||
// new_slice :: proc(Type, len, cap: int) -> []Type
|
|
||||||
gbAllocator allocator = proc->module->allocator;
|
|
||||||
|
|
||||||
Type *type = type_of_expr(proc->module->info, ce->args[0]);
|
|
||||||
Type *ptr_type = make_type_pointer(allocator, type);
|
|
||||||
Type *slice_type = make_type_slice(allocator, type);
|
|
||||||
|
|
||||||
i64 s = type_size_of(allocator, type);
|
|
||||||
i64 a = type_align_of(allocator, type);
|
|
||||||
|
|
||||||
irValue *elem_size = ir_const_int(allocator, s);
|
|
||||||
irValue *elem_align = ir_const_int(allocator, a);
|
|
||||||
|
|
||||||
irValue *count = ir_emit_conv(proc, ir_build_expr(proc, ce->args[1]), t_int);
|
|
||||||
irValue *capacity = count;
|
|
||||||
|
|
||||||
if (ce->args.count == 3) {
|
|
||||||
capacity = ir_emit_conv(proc, ir_build_expr(proc, ce->args[2]), t_int);
|
|
||||||
}
|
|
||||||
|
|
||||||
ir_emit_slice_bounds_check(proc, ast_node_token(ce->args[1]), v_zero, count, capacity, false);
|
|
||||||
|
|
||||||
irValue *slice_size = ir_emit_arith(proc, Token_Mul, elem_size, capacity, t_int);
|
|
||||||
|
|
||||||
irValue **args = gb_alloc_array(allocator, irValue *, 2);
|
|
||||||
args[0] = slice_size;
|
|
||||||
args[1] = elem_align;
|
|
||||||
irValue *call = ir_emit_global_call(proc, "alloc_align", args, 2);
|
|
||||||
|
|
||||||
irValue *ptr = ir_emit_conv(proc, call, ptr_type);
|
|
||||||
irValue *slice = ir_add_local_generated(proc, slice_type);
|
|
||||||
|
|
||||||
ir_fill_slice(proc, slice, ptr, count, capacity);
|
|
||||||
return ir_emit_load(proc, slice);
|
|
||||||
} break;
|
|
||||||
#endif
|
|
||||||
case BuiltinProc_make: {
|
case BuiltinProc_make: {
|
||||||
ir_emit_comment(proc, str_lit("make"));
|
ir_emit_comment(proc, str_lit("make"));
|
||||||
gbAllocator a = proc->module->allocator;
|
gbAllocator a = proc->module->allocator;
|
||||||
@@ -4593,6 +4305,276 @@ irValue *ir_build_expr(irProcedure *proc, AstNode *expr) {
|
|||||||
ir_build_expr(proc, ce->args[2]));
|
ir_build_expr(proc, ce->args[2]));
|
||||||
} break;
|
} break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GB_PANIC("Unhandled built-in procedure");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
irValue *ir_build_expr(irProcedure *proc, AstNode *expr) {
|
||||||
|
expr = unparen_expr(expr);
|
||||||
|
|
||||||
|
TypeAndValue tv = type_and_value_of_expr(proc->module->info, expr);
|
||||||
|
GB_ASSERT(tv.mode != Addressing_Invalid);
|
||||||
|
|
||||||
|
if (tv.value.kind != ExactValue_Invalid) {
|
||||||
|
// NOTE(bill): Edge case
|
||||||
|
if (tv.value.kind != ExactValue_Compound &&
|
||||||
|
is_type_vector(tv.type)) {
|
||||||
|
Type *elem = base_vector_type(tv.type);
|
||||||
|
ExactValue value = convert_exact_value_for_type(tv.value, elem);
|
||||||
|
irValue *x = ir_add_module_constant(proc->module, elem, value);
|
||||||
|
return ir_emit_conv(proc, x, tv.type);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ir_add_module_constant(proc->module, tv.type, tv.value);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tv.mode == Addressing_Variable) {
|
||||||
|
return ir_addr_load(proc, ir_build_addr(proc, expr));
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (expr->kind) {
|
||||||
|
case_ast_node(bl, BasicLit, expr);
|
||||||
|
TokenPos pos = bl->pos;
|
||||||
|
GB_PANIC("Non-constant basic literal %.*s(%td:%td) - %.*s", LIT(pos.file), pos.line, pos.column, LIT(token_strings[bl->kind]));
|
||||||
|
case_end;
|
||||||
|
|
||||||
|
case_ast_node(bd, BasicDirective, expr);
|
||||||
|
TokenPos pos = bd->token.pos;
|
||||||
|
GB_PANIC("Non-constant basic literal %.*s(%td:%td) - %.*s", LIT(pos.file), pos.line, pos.column, LIT(bd->name));
|
||||||
|
case_end;
|
||||||
|
|
||||||
|
case_ast_node(i, Implicit, expr);
|
||||||
|
return ir_addr_load(proc, ir_build_addr(proc, expr));
|
||||||
|
case_end;
|
||||||
|
|
||||||
|
case_ast_node(i, Ident, expr);
|
||||||
|
Entity *e = entity_of_ident(proc->module->info, expr);
|
||||||
|
if (e->kind == Entity_Builtin) {
|
||||||
|
Token token = ast_node_token(expr);
|
||||||
|
GB_PANIC("TODO(bill): ir_build_single_expr Entity_Builtin `%.*s`\n"
|
||||||
|
"\t at %.*s(%td:%td)", LIT(builtin_procs[e->Builtin.id].name),
|
||||||
|
LIT(token.pos.file), token.pos.line, token.pos.column);
|
||||||
|
return NULL;
|
||||||
|
} else if (e->kind == Entity_Nil) {
|
||||||
|
return ir_value_nil(proc->module->allocator, tv.type);
|
||||||
|
}
|
||||||
|
|
||||||
|
irValue **found = map_get(&proc->module->values, hash_pointer(e));
|
||||||
|
if (found) {
|
||||||
|
irValue *v = *found;
|
||||||
|
if (v->kind == irValue_Proc) {
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
// if (e->kind == Entity_Variable && e->Variable.param) {
|
||||||
|
// return v;
|
||||||
|
// }
|
||||||
|
return ir_emit_load(proc, v);
|
||||||
|
} else if (e != NULL && e->kind == Entity_Variable) {
|
||||||
|
return ir_addr_load(proc, ir_build_addr(proc, expr));
|
||||||
|
}
|
||||||
|
GB_PANIC("NULL value for expression from identifier: %.*s", LIT(i->string));
|
||||||
|
return NULL;
|
||||||
|
case_end;
|
||||||
|
|
||||||
|
case_ast_node(re, RunExpr, expr);
|
||||||
|
// TODO(bill): Run Expression
|
||||||
|
return ir_build_expr(proc, re->expr);
|
||||||
|
case_end;
|
||||||
|
|
||||||
|
case_ast_node(de, DerefExpr, expr);
|
||||||
|
return ir_addr_load(proc, ir_build_addr(proc, expr));
|
||||||
|
case_end;
|
||||||
|
|
||||||
|
case_ast_node(se, SelectorExpr, expr);
|
||||||
|
TypeAndValue tav = type_and_value_of_expr(proc->module->info, expr);
|
||||||
|
GB_ASSERT(tav.mode != Addressing_Invalid);
|
||||||
|
return ir_addr_load(proc, ir_build_addr(proc, expr));
|
||||||
|
case_end;
|
||||||
|
|
||||||
|
case_ast_node(te, TernaryExpr, expr);
|
||||||
|
ir_emit_comment(proc, str_lit("TernaryExpr"));
|
||||||
|
|
||||||
|
Array<irValue *> edges = {};
|
||||||
|
array_init(&edges, proc->module->allocator, 2);
|
||||||
|
|
||||||
|
GB_ASSERT(te->y != NULL);
|
||||||
|
irBlock *then = ir_new_block(proc, NULL, "if.then");
|
||||||
|
irBlock *done = ir_new_block(proc, NULL, "if.done"); // NOTE(bill): Append later
|
||||||
|
irBlock *else_ = ir_new_block(proc, NULL, "if.else");
|
||||||
|
|
||||||
|
irValue *cond = ir_build_cond(proc, te->cond, then, else_);
|
||||||
|
ir_start_block(proc, then);
|
||||||
|
|
||||||
|
Type *type = type_of_expr(proc->module->info, expr);
|
||||||
|
|
||||||
|
ir_open_scope(proc);
|
||||||
|
array_add(&edges, ir_emit_conv(proc, ir_build_expr(proc, te->x), type));
|
||||||
|
ir_close_scope(proc, irDeferExit_Default, NULL);
|
||||||
|
|
||||||
|
ir_emit_jump(proc, done);
|
||||||
|
ir_start_block(proc, else_);
|
||||||
|
|
||||||
|
ir_open_scope(proc);
|
||||||
|
array_add(&edges, ir_emit_conv(proc, ir_build_expr(proc, te->y), type));
|
||||||
|
ir_close_scope(proc, irDeferExit_Default, NULL);
|
||||||
|
|
||||||
|
ir_emit_jump(proc, done);
|
||||||
|
ir_start_block(proc, done);
|
||||||
|
|
||||||
|
return ir_emit(proc, ir_instr_phi(proc, edges, type));
|
||||||
|
case_end;
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
case_ast_node(ie, IfExpr, expr);
|
||||||
|
ir_emit_comment(proc, str_lit("IfExpr"));
|
||||||
|
if (ie->init != NULL) {
|
||||||
|
irBlock *init = ir_new_block(proc, expr, "if.init");
|
||||||
|
ir_emit_jump(proc, init);
|
||||||
|
ir_start_block(proc, init);
|
||||||
|
ir_build_stmt(proc, ie->init);
|
||||||
|
}
|
||||||
|
|
||||||
|
Array<irValue *> edges = {};
|
||||||
|
array_init(&edges, proc->module->allocator, 2);
|
||||||
|
|
||||||
|
GB_ASSERT(ie->else_expr != NULL);
|
||||||
|
irBlock *then = ir_new_block(proc, expr, "if.then");
|
||||||
|
irBlock *done = ir_new_block(proc, expr, "if.done"); // NOTE(bill): Append later
|
||||||
|
irBlock *else_ = ir_new_block(proc, ie->else_expr, "if.else");
|
||||||
|
|
||||||
|
irValue *cond = ir_build_cond(proc, ie->cond, then, else_);
|
||||||
|
ir_start_block(proc, then);
|
||||||
|
|
||||||
|
ir_open_scope(proc);
|
||||||
|
array_add(&edges, ir_build_expr(proc, ie->body));
|
||||||
|
ir_close_scope(proc, irDeferExit_Default, NULL);
|
||||||
|
|
||||||
|
ir_emit_jump(proc, done);
|
||||||
|
ir_start_block(proc, else_);
|
||||||
|
|
||||||
|
ir_open_scope(proc);
|
||||||
|
array_add(&edges, ir_build_expr(proc, ie->else_expr));
|
||||||
|
ir_close_scope(proc, irDeferExit_Default, NULL);
|
||||||
|
|
||||||
|
ir_emit_jump(proc, done);
|
||||||
|
ir_start_block(proc, done);
|
||||||
|
|
||||||
|
Type *type = type_of_expr(proc->module->info, expr);
|
||||||
|
|
||||||
|
return ir_emit(proc, ir_instr_phi(proc, edges, type));
|
||||||
|
case_end;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
case_ast_node(ta, TypeAssertion, expr);
|
||||||
|
TokenPos pos = ast_node_token(expr).pos;
|
||||||
|
Type *type = tv.type;
|
||||||
|
irValue *e = ir_build_expr(proc, ta->expr);
|
||||||
|
Type *t = type_deref(ir_type(e));
|
||||||
|
if (is_type_union(t)) {
|
||||||
|
ir_emit_comment(proc, str_lit("cast - union_cast"));
|
||||||
|
return ir_emit_union_cast(proc, e, type, pos);
|
||||||
|
} else if (is_type_any(t)) {
|
||||||
|
ir_emit_comment(proc, str_lit("cast - any_cast"));
|
||||||
|
return ir_emit_any_cast(proc, e, type, pos);
|
||||||
|
} else {
|
||||||
|
GB_PANIC("TODO(bill): type assertion %s", type_to_string(ir_type(e)));
|
||||||
|
}
|
||||||
|
case_end;
|
||||||
|
|
||||||
|
case_ast_node(ue, UnaryExpr, expr);
|
||||||
|
switch (ue->op.kind) {
|
||||||
|
case Token_And:
|
||||||
|
return ir_emit_ptr_offset(proc, ir_build_addr(proc, ue->expr).addr, v_zero); // Make a copy of the pointer
|
||||||
|
default:
|
||||||
|
return ir_emit_unary_arith(proc, ue->op.kind, ir_build_expr(proc, ue->expr), tv.type);
|
||||||
|
}
|
||||||
|
case_end;
|
||||||
|
|
||||||
|
case_ast_node(be, BinaryExpr, expr);
|
||||||
|
irValue *left = ir_build_expr(proc, be->left);
|
||||||
|
Type *type = default_type(tv.type);
|
||||||
|
|
||||||
|
switch (be->op.kind) {
|
||||||
|
case Token_Add:
|
||||||
|
case Token_Sub:
|
||||||
|
case Token_Mul:
|
||||||
|
case Token_Quo:
|
||||||
|
case Token_Mod:
|
||||||
|
case Token_ModMod:
|
||||||
|
case Token_And:
|
||||||
|
case Token_Or:
|
||||||
|
case Token_Xor:
|
||||||
|
case Token_AndNot:
|
||||||
|
case Token_Shl:
|
||||||
|
case Token_Shr: {
|
||||||
|
irValue *right = ir_build_expr(proc, be->right);
|
||||||
|
return ir_emit_arith(proc, be->op.kind, left, right, type);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
case Token_CmpEq:
|
||||||
|
case Token_NotEq:
|
||||||
|
case Token_Lt:
|
||||||
|
case Token_LtEq:
|
||||||
|
case Token_Gt:
|
||||||
|
case Token_GtEq: {
|
||||||
|
irValue *right = ir_build_expr(proc, be->right);
|
||||||
|
irValue *cmp = ir_emit_comp(proc, be->op.kind, left, right);
|
||||||
|
return ir_emit_conv(proc, cmp, type);
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case Token_CmpAnd:
|
||||||
|
case Token_CmpOr:
|
||||||
|
return ir_emit_logical_binary_expr(proc, expr);
|
||||||
|
|
||||||
|
default:
|
||||||
|
GB_PANIC("Invalid binary expression");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case_end;
|
||||||
|
|
||||||
|
case_ast_node(pl, ProcLit, expr);
|
||||||
|
// NOTE(bill): Generate a new name
|
||||||
|
// parent$count
|
||||||
|
isize name_len = proc->name.len + 1 + 8 + 1;
|
||||||
|
u8 *name_text = gb_alloc_array(proc->module->allocator, u8, name_len);
|
||||||
|
name_len = gb_snprintf(cast(char *)name_text, name_len, "%.*s$%d", LIT(proc->name), cast(i32)proc->children.count);
|
||||||
|
String name = make_string(name_text, name_len-1);
|
||||||
|
|
||||||
|
Type *type = type_of_expr(proc->module->info, expr);
|
||||||
|
irValue *value = ir_value_procedure(proc->module->allocator,
|
||||||
|
proc->module, NULL, type, pl->type, pl->body, name);
|
||||||
|
|
||||||
|
value->Proc.tags = pl->tags;
|
||||||
|
value->Proc.parent = proc;
|
||||||
|
|
||||||
|
array_add(&proc->children, &value->Proc);
|
||||||
|
array_add(&proc->module->procs_to_generate, value);
|
||||||
|
|
||||||
|
return value;
|
||||||
|
case_end;
|
||||||
|
|
||||||
|
|
||||||
|
case_ast_node(cl, CompoundLit, expr);
|
||||||
|
return ir_addr_load(proc, ir_build_addr(proc, expr));
|
||||||
|
case_end;
|
||||||
|
|
||||||
|
|
||||||
|
case_ast_node(ce, CallExpr, expr);
|
||||||
|
if (type_and_value_of_expr(proc->module->info, ce->proc).mode == Addressing_Type) {
|
||||||
|
GB_ASSERT(ce->args.count == 1);
|
||||||
|
irValue *x = ir_build_expr(proc, ce->args[0]);
|
||||||
|
irValue *y = ir_emit_conv(proc, x, tv.type);
|
||||||
|
return y;
|
||||||
|
}
|
||||||
|
|
||||||
|
AstNode *p = unparen_expr(ce->proc);
|
||||||
|
if (p->kind == AstNode_Ident) {
|
||||||
|
Entity *e = entity_of_ident(proc->module->info, p);
|
||||||
|
if (e != NULL && e->kind == Entity_Builtin) {
|
||||||
|
return ir_build_builtin_proc(proc, expr, tv, e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -5794,9 +5776,8 @@ void ir_build_range_interval(irProcedure *proc, AstNodeBinaryExpr *node, Type *v
|
|||||||
}
|
}
|
||||||
|
|
||||||
void ir_store_type_case_implicit(irProcedure *proc, AstNode *clause, irValue *value) {
|
void ir_store_type_case_implicit(irProcedure *proc, AstNode *clause, irValue *value) {
|
||||||
Entity **found = map_get(&proc->module->info->implicits, hash_pointer(clause));
|
Entity *e = implicit_entity_of_node(proc->module->info, clause);
|
||||||
GB_ASSERT(found != NULL);
|
GB_ASSERT(e != NULL);
|
||||||
Entity *e = *found; GB_ASSERT(e != NULL);
|
|
||||||
irValue *x = ir_add_local(proc, e, NULL);
|
irValue *x = ir_add_local(proc, e, NULL);
|
||||||
ir_emit_store(proc, x, value);
|
ir_emit_store(proc, x, value);
|
||||||
}
|
}
|
||||||
@@ -5936,9 +5917,7 @@ void ir_build_stmt_internal(irProcedure *proc, AstNode *node) {
|
|||||||
AstNode *ident = pd->name;
|
AstNode *ident = pd->name;
|
||||||
GB_ASSERT(ident->kind == AstNode_Ident);
|
GB_ASSERT(ident->kind == AstNode_Ident);
|
||||||
Entity *e = entity_of_ident(proc->module->info, ident);
|
Entity *e = entity_of_ident(proc->module->info, ident);
|
||||||
DeclInfo **decl_info = map_get(&proc->module->info->entities, hash_pointer(e));
|
DeclInfo *dl = decl_info_of_entity(proc->module->info, e);
|
||||||
GB_ASSERT(decl_info != NULL);
|
|
||||||
DeclInfo *dl = *decl_info;
|
|
||||||
|
|
||||||
if (pd->body != NULL) {
|
if (pd->body != NULL) {
|
||||||
CheckerInfo *info = proc->module->info;
|
CheckerInfo *info = proc->module->info;
|
||||||
@@ -6599,13 +6578,7 @@ void ir_build_stmt_internal(irProcedure *proc, AstNode *node) {
|
|||||||
ir_start_block(proc, next);
|
ir_start_block(proc, next);
|
||||||
}
|
}
|
||||||
|
|
||||||
Entity *case_entity = NULL;
|
Entity *case_entity = implicit_entity_of_node(proc->module->info, clause);
|
||||||
{
|
|
||||||
Entity **found = map_get(&proc->module->info->implicits, hash_pointer(clause));
|
|
||||||
GB_ASSERT(found != NULL);
|
|
||||||
case_entity = *found;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
irValue *value = parent_value;
|
irValue *value = parent_value;
|
||||||
|
|
||||||
@@ -6771,9 +6744,8 @@ void ir_begin_procedure_body(irProcedure *proc) {
|
|||||||
array_init(&proc->children, heap_allocator());
|
array_init(&proc->children, heap_allocator());
|
||||||
array_init(&proc->branch_blocks, heap_allocator());
|
array_init(&proc->branch_blocks, heap_allocator());
|
||||||
|
|
||||||
DeclInfo **found = map_get(&proc->module->info->entities, hash_pointer(proc->entity));
|
DeclInfo *decl = decl_info_of_entity(proc->module->info, proc->entity);
|
||||||
if (found != NULL) {
|
if (decl != NULL) {
|
||||||
DeclInfo *decl = *found;
|
|
||||||
for_array(i, decl->labels) {
|
for_array(i, decl->labels) {
|
||||||
BlockLabel bl = decl->labels[i];
|
BlockLabel bl = decl->labels[i];
|
||||||
irBranchBlocks bb = {bl.label, NULL, NULL};
|
irBranchBlocks bb = {bl.label, NULL, NULL};
|
||||||
@@ -6866,9 +6838,7 @@ void ir_build_proc(irValue *value, irProcedure *parent) {
|
|||||||
CheckerInfo *info = m->info;
|
CheckerInfo *info = m->info;
|
||||||
Entity *e = proc->entity;
|
Entity *e = proc->entity;
|
||||||
String filename = e->token.pos.file;
|
String filename = e->token.pos.file;
|
||||||
AstFile **found = map_get(&info->files, hash_string(filename));
|
AstFile *f = ast_file_of_filename(info, filename);
|
||||||
GB_ASSERT(found != NULL);
|
|
||||||
AstFile *f = *found;
|
|
||||||
irDebugInfo *di_file = NULL;
|
irDebugInfo *di_file = NULL;
|
||||||
|
|
||||||
irDebugInfo **di_file_found = map_get(&m->debug_info, hash_pointer(f));
|
irDebugInfo **di_file_found = map_get(&m->debug_info, hash_pointer(f));
|
||||||
|
|||||||
@@ -95,6 +95,8 @@ struct TypeRecord {
|
|||||||
Entity * union__tag;
|
Entity * union__tag;
|
||||||
i64 variant_block_size; // NOTE(bill): Internal use only
|
i64 variant_block_size; // NOTE(bill): Internal use only
|
||||||
|
|
||||||
|
Type * variant_parent;
|
||||||
|
i32 variant_index;
|
||||||
|
|
||||||
i64 * offsets;
|
i64 * offsets;
|
||||||
bool are_offsets_set;
|
bool are_offsets_set;
|
||||||
@@ -838,6 +840,14 @@ bool is_type_union(Type *t) {
|
|||||||
t = base_type(t);
|
t = base_type(t);
|
||||||
return (t->kind == Type_Record && t->Record.kind == TypeRecord_Union);
|
return (t->kind == Type_Record && t->Record.kind == TypeRecord_Union);
|
||||||
}
|
}
|
||||||
|
bool is_type_variant(Type *t) {
|
||||||
|
t = base_type(t);
|
||||||
|
if (t->kind == Type_Record) {
|
||||||
|
return t->Record.kind == TypeRecord_Struct && t->Record.variant_parent != NULL;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
bool is_type_raw_union(Type *t) {
|
bool is_type_raw_union(Type *t) {
|
||||||
t = base_type(t);
|
t = base_type(t);
|
||||||
return (t->kind == Type_Record && t->Record.kind == TypeRecord_RawUnion);
|
return (t->kind == Type_Record && t->Record.kind == TypeRecord_RawUnion);
|
||||||
|
|||||||
Reference in New Issue
Block a user