Add CheckerInfo API functions

This commit is contained in:
Ginger Bill
2017-06-15 12:14:56 +01:00
parent a134307dcd
commit 23f9f9064e
5 changed files with 813 additions and 791 deletions
+5 -1
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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));
+10
View File
@@ -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);