Merge branch 'master' into llvm-12.0.1-windows

This commit is contained in:
gingerBill
2021-09-18 12:55:13 +01:00
committed by GitHub
99 changed files with 112397 additions and 4769 deletions
+13
View File
@@ -150,6 +150,19 @@ void slice_copy(Slice<T> *slice, Slice<T> const &data, isize offset, isize count
template <typename T>
gb_inline Slice<T> slice(Slice<T> const &array, isize lo, isize hi) {
GB_ASSERT(0 <= lo && lo <= hi && hi <= array.count);
Slice<T> out = {};
isize len = hi-lo;
if (len > 0) {
out.data = array.data+lo;
out.count = len;
}
return out;
}
template <typename T>
void slice_ordered_remove(Slice<T> *array, isize index) {
GB_ASSERT(0 <= index && index < array->count);
+23 -19
View File
@@ -64,13 +64,13 @@ void check_or_else_split_types(CheckerContext *c, Operand *x, String const &name
Type *right_type = nullptr;
if (x->type->kind == Type_Tuple) {
auto const &vars = x->type->Tuple.variables;
auto lhs = array_slice(vars, 0, vars.count-1);
auto lhs = slice(vars, 0, vars.count-1);
auto rhs = vars[vars.count-1];
if (lhs.count == 1) {
left_type = lhs[0]->type;
} else if (lhs.count != 0) {
left_type = alloc_type_tuple();
left_type->Tuple.variables = array_make_from_ptr(lhs.data, lhs.count, lhs.count);
left_type->Tuple.variables = lhs;
}
right_type = rhs->type;
@@ -120,13 +120,13 @@ void check_or_return_split_types(CheckerContext *c, Operand *x, String const &na
Type *right_type = nullptr;
if (x->type->kind == Type_Tuple) {
auto const &vars = x->type->Tuple.variables;
auto lhs = array_slice(vars, 0, vars.count-1);
auto lhs = slice(vars, 0, vars.count-1);
auto rhs = vars[vars.count-1];
if (lhs.count == 1) {
left_type = lhs[0]->type;
} else if (lhs.count != 0) {
left_type = alloc_type_tuple();
left_type->Tuple.variables = array_make_from_ptr(lhs.data, lhs.count, lhs.count);
left_type->Tuple.variables = lhs;
}
right_type = rhs->type;
@@ -1156,12 +1156,12 @@ bool check_builtin_procedure(CheckerContext *c, Operand *operand, Ast *call, i32
if (is_type_struct(type)) {
isize variable_count = type->Struct.fields.count;
array_init(&tuple->Tuple.variables, a, variable_count);
slice_init(&tuple->Tuple.variables, a, variable_count);
// TODO(bill): Should I copy each of the entities or is this good enough?
gb_memmove_array(tuple->Tuple.variables.data, type->Struct.fields.data, variable_count);
} else if (is_type_array(type)) {
isize variable_count = cast(isize)type->Array.count;
array_init(&tuple->Tuple.variables, a, variable_count);
slice_init(&tuple->Tuple.variables, a, variable_count);
for (isize i = 0; i < variable_count; i++) {
tuple->Tuple.variables[i] = alloc_entity_array_elem(nullptr, blank_token, type->Array.elem, cast(i32)i);
}
@@ -1240,14 +1240,14 @@ bool check_builtin_procedure(CheckerContext *c, Operand *operand, Ast *call, i32
} else if (is_type_enum(type)) {
operand->mode = Addressing_Constant;
operand->type = original_type;
operand->value = type->Enum.min_value;
operand->value = *type->Enum.min_value;
return true;
} else if (is_type_enumerated_array(type)) {
Type *bt = base_type(type);
GB_ASSERT(bt->kind == Type_EnumeratedArray);
operand->mode = Addressing_Constant;
operand->type = bt->EnumeratedArray.index;
operand->value = bt->EnumeratedArray.min_value;
operand->value = *bt->EnumeratedArray.min_value;
return true;
}
gbString type_str = type_to_string(original_type);
@@ -1414,14 +1414,14 @@ bool check_builtin_procedure(CheckerContext *c, Operand *operand, Ast *call, i32
} else if (is_type_enum(type)) {
operand->mode = Addressing_Constant;
operand->type = original_type;
operand->value = type->Enum.max_value;
operand->value = *type->Enum.max_value;
return true;
} else if (is_type_enumerated_array(type)) {
Type *bt = base_type(type);
GB_ASSERT(bt->kind == Type_EnumeratedArray);
operand->mode = Addressing_Constant;
operand->type = bt->EnumeratedArray.index;
operand->value = bt->EnumeratedArray.max_value;
operand->value = *bt->EnumeratedArray.max_value;
return true;
}
gbString type_str = type_to_string(original_type);
@@ -1788,8 +1788,8 @@ bool check_builtin_procedure(CheckerContext *c, Operand *operand, Ast *call, i32
if (elem == nullptr) {
elem = alloc_type_struct();
elem->Struct.scope = s;
elem->Struct.fields = fields;
elem->Struct.tags = array_make<String>(permanent_allocator(), fields.count);
elem->Struct.fields = slice_from_array(fields);
elem->Struct.tags = gb_alloc_array(permanent_allocator(), String, fields.count);
elem->Struct.node = dummy_node_struct;
type_set_offsets(elem);
}
@@ -1938,12 +1938,12 @@ bool check_builtin_procedure(CheckerContext *c, Operand *operand, Ast *call, i32
if (is_type_array(elem)) {
Type *old_array = base_type(elem);
soa_struct = alloc_type_struct();
soa_struct->Struct.fields = array_make<Entity *>(heap_allocator(), cast(isize)old_array->Array.count);
soa_struct->Struct.tags = array_make<String>(heap_allocator(), cast(isize)old_array->Array.count);
soa_struct->Struct.fields = slice_make<Entity *>(heap_allocator(), cast(isize)old_array->Array.count);
soa_struct->Struct.tags = gb_alloc_array(permanent_allocator(), String, cast(isize)old_array->Array.count);
soa_struct->Struct.node = operand->expr;
soa_struct->Struct.soa_kind = StructSoa_Fixed;
soa_struct->Struct.soa_elem = elem;
soa_struct->Struct.soa_count = count;
soa_struct->Struct.soa_count = cast(i32)count;
scope = create_scope(c->info, c->scope);
soa_struct->Struct.scope = scope;
@@ -1971,12 +1971,16 @@ bool check_builtin_procedure(CheckerContext *c, Operand *operand, Ast *call, i32
Type *old_struct = base_type(elem);
soa_struct = alloc_type_struct();
soa_struct->Struct.fields = array_make<Entity *>(heap_allocator(), old_struct->Struct.fields.count);
soa_struct->Struct.tags = array_make<String>(heap_allocator(), old_struct->Struct.tags.count);
soa_struct->Struct.fields = slice_make<Entity *>(heap_allocator(), old_struct->Struct.fields.count);
soa_struct->Struct.tags = gb_alloc_array(permanent_allocator(), String, old_struct->Struct.fields.count);
soa_struct->Struct.node = operand->expr;
soa_struct->Struct.soa_kind = StructSoa_Fixed;
soa_struct->Struct.soa_elem = elem;
soa_struct->Struct.soa_count = count;
if (count > I32_MAX) {
count = I32_MAX;
error(call, "Array count too large for an #soa struct, got %lld", cast(long long)count);
}
soa_struct->Struct.soa_count = cast(i32)count;
scope = create_scope(c->info, old_struct->Struct.scope->parent);
soa_struct->Struct.scope = scope;
@@ -1985,7 +1989,7 @@ bool check_builtin_procedure(CheckerContext *c, Operand *operand, Ast *call, i32
Entity *old_field = old_struct->Struct.fields[i];
if (old_field->kind == Entity_Variable) {
Type *array_type = alloc_type_array(old_field->type, count);
Entity *new_field = alloc_entity_field(scope, old_field->token, array_type, false, old_field->Variable.field_src_index);
Entity *new_field = alloc_entity_field(scope, old_field->token, array_type, false, old_field->Variable.field_index);
soa_struct->Struct.fields[i] = new_field;
add_entity(c, scope, nullptr, new_field);
} else {
+25 -13
View File
@@ -1023,10 +1023,10 @@ bool is_polymorphic_type_assignable(CheckerContext *c, Type *poly, Type *source,
if (poly->EnumeratedArray.count != source->EnumeratedArray.count) {
return false;
}
if (compare_exact_values(Token_NotEq, poly->EnumeratedArray.min_value, source->EnumeratedArray.min_value)) {
if (compare_exact_values(Token_NotEq, *poly->EnumeratedArray.min_value, *source->EnumeratedArray.min_value)) {
return false;
}
if (compare_exact_values(Token_NotEq, poly->EnumeratedArray.max_value, source->EnumeratedArray.max_value)) {
if (compare_exact_values(Token_NotEq, *poly->EnumeratedArray.max_value, *source->EnumeratedArray.max_value)) {
return false;
}
return is_polymorphic_type_assignable(c, poly->EnumeratedArray.index, source->EnumeratedArray.index, true, modify_type);
@@ -3425,8 +3425,8 @@ bool check_index_value(CheckerContext *c, Type *main_type, bool open_range, Ast
if (is_type_enum(index_type)) {
Type *bt = base_type(index_type);
GB_ASSERT(bt->kind == Type_Enum);
ExactValue lo = bt->Enum.min_value;
ExactValue hi = bt->Enum.max_value;
ExactValue const &lo = *bt->Enum.min_value;
ExactValue const &hi = *bt->Enum.max_value;
String lo_str = {};
String hi_str = {};
if (bt->Enum.fields.count > 0) {
@@ -3556,7 +3556,7 @@ ExactValue get_constant_field_single(CheckerContext *c, ExactValue value, i32 in
if (is_type_enumerated_array(node->tav.type)) {
Type *bt = base_type(node->tav.type);
GB_ASSERT(bt->kind == Type_EnumeratedArray);
corrected_index = index + exact_value_to_i64(bt->EnumeratedArray.min_value);
corrected_index = index + exact_value_to_i64(*bt->EnumeratedArray.min_value);
}
if (op != Token_RangeHalf) {
if (lo <= corrected_index && corrected_index <= hi) {
@@ -3580,7 +3580,7 @@ ExactValue get_constant_field_single(CheckerContext *c, ExactValue value, i32 in
if (is_type_enumerated_array(node->tav.type)) {
Type *bt = base_type(node->tav.type);
GB_ASSERT(bt->kind == Type_EnumeratedArray);
index_value = exact_value_sub(index_value, bt->EnumeratedArray.min_value);
index_value = exact_value_sub(index_value, *bt->EnumeratedArray.min_value);
}
i64 field_index = exact_value_to_i64(index_value);
@@ -3738,6 +3738,18 @@ void check_did_you_mean_type(String const &name, Array<Entity *> const &fields)
check_did_you_mean_print(&d);
}
void check_did_you_mean_type(String const &name, Slice<Entity *> const &fields) {
ERROR_BLOCK();
DidYouMeanAnswers d = did_you_mean_make(heap_allocator(), fields.count, name);
defer (did_you_mean_destroy(&d));
for_array(i, fields) {
did_you_mean_append(&d, fields[i]->token.string);
}
check_did_you_mean_print(&d);
}
void check_did_you_mean_scope(String const &name, Scope *scope) {
ERROR_BLOCK();
@@ -4942,7 +4954,7 @@ Entity **populate_proc_parameter_list(CheckerContext *c, Type *proc_type, isize
} else {
lhs_count = pt->params->Tuple.variables.count;
}
lhs = gb_alloc_array(heap_allocator(), Entity *, lhs_count);
lhs = gb_alloc_array(permanent_allocator(), Entity *, lhs_count);
for (isize i = 0; i < lhs_count; i++) {
Entity *e = pt->params->Tuple.variables[i];
if (!is_type_polymorphic(e->type)) {
@@ -7305,8 +7317,8 @@ ExprKind check_expr_base_internal(CheckerContext *c, Operand *o, Ast *node, Type
gbString index_type_str = type_to_string(index_type);
defer (gb_string_free(index_type_str));
i64 total_lo = exact_value_to_i64(t->EnumeratedArray.min_value);
i64 total_hi = exact_value_to_i64(t->EnumeratedArray.max_value);
i64 total_lo = exact_value_to_i64(*t->EnumeratedArray.min_value);
i64 total_hi = exact_value_to_i64(*t->EnumeratedArray.max_value);
String total_lo_string = {};
String total_hi_string = {};
@@ -7319,10 +7331,10 @@ ExprKind check_expr_base_internal(CheckerContext *c, Operand *o, Ast *node, Type
if (f->kind != Entity_Constant) {
continue;
}
if (total_lo_string.len == 0 && compare_exact_values(Token_CmpEq, f->Constant.value, t->EnumeratedArray.min_value)) {
if (total_lo_string.len == 0 && compare_exact_values(Token_CmpEq, f->Constant.value, *t->EnumeratedArray.min_value)) {
total_lo_string = f->token.string;
}
if (total_hi_string.len == 0 && compare_exact_values(Token_CmpEq, f->Constant.value, t->EnumeratedArray.max_value)) {
if (total_hi_string.len == 0 && compare_exact_values(Token_CmpEq, f->Constant.value, *t->EnumeratedArray.max_value)) {
total_hi_string = f->token.string;
}
if (total_lo_string.len != 0 && total_hi_string.len != 0) {
@@ -8472,13 +8484,13 @@ ExprKind check_expr_base_internal(CheckerContext *c, Operand *o, Ast *node, Type
Type *params = alloc_type_tuple();
Type *results = alloc_type_tuple();
if (param_types.count != 0) {
array_init(&params->Tuple.variables, heap_allocator(), param_types.count);
slice_init(&params->Tuple.variables, heap_allocator(), param_types.count);
for_array(i, param_types) {
params->Tuple.variables[i] = alloc_entity_param(scope, blank_token, param_types[i], false, true);
}
}
if (return_type != nullptr) {
array_init(&results->Tuple.variables, heap_allocator(), 1);
slice_init(&results->Tuple.variables, heap_allocator(), 1);
results->Tuple.variables[0] = alloc_entity_param(scope, blank_token, return_type, false, true);
}
+44 -49
View File
@@ -92,10 +92,10 @@ bool does_field_type_allow_using(Type *t) {
return false;
}
void check_struct_fields(CheckerContext *ctx, Ast *node, Array<Entity *> *fields, Array<String> *tags, Slice<Ast *> const &params,
void check_struct_fields(CheckerContext *ctx, Ast *node, Slice<Entity *> *fields, String **tags, Slice<Ast *> const &params,
isize init_field_capacity, Type *struct_type, String context) {
*fields = array_make<Entity *>(heap_allocator(), 0, init_field_capacity);
*tags = array_make<String>(heap_allocator(), 0, init_field_capacity);
auto fields_array = array_make<Entity *>(heap_allocator(), 0, init_field_capacity);
auto tags_array = array_make<String>(heap_allocator(), 0, init_field_capacity);
GB_ASSERT(node->kind == Ast_StructType);
GB_ASSERT(struct_type->kind == Type_Struct);
@@ -153,20 +153,20 @@ void check_struct_fields(CheckerContext *ctx, Ast *node, Array<Entity *> *fields
Entity *field = alloc_entity_field(ctx->scope, name_token, type, is_using, field_src_index);
add_entity(ctx, ctx->scope, name, field);
array_add(fields, field);
array_add(&fields_array, field);
String tag = p->tag.string;
if (tag.len != 0 && !unquote_string(permanent_allocator(), &tag, 0, tag.text[0] == '`')) {
error(p->tag, "Invalid string literal");
tag = {};
}
array_add(tags, tag);
array_add(&tags_array, tag);
field_src_index += 1;
}
if (is_using && p->names.count > 0) {
Type *first_type = (*fields)[fields->count-1]->type;
Type *first_type = fields_array[fields_array.count-1]->type;
Type *t = base_type(type_deref(first_type));
if (!does_field_type_allow_using(t) &&
@@ -182,16 +182,12 @@ void check_struct_fields(CheckerContext *ctx, Ast *node, Array<Entity *> *fields
populate_using_entity_scope(ctx, node, p, type);
}
}
*fields = slice_from_array(fields_array);
*tags = tags_array.data;
}
Entity *make_names_field_for_struct(CheckerContext *ctx, Scope *scope) {
Entity *e = alloc_entity_field(scope, make_token_ident(str_lit("names")), t_string_slice, false, 0);
e->flags |= EntityFlag_TypeField;
e->flags |= EntityFlag_Value;
return e;
}
bool check_custom_align(CheckerContext *ctx, Ast *node, i64 *align_) {
GB_ASSERT(align_ != nullptr);
Operand o = {};
@@ -219,13 +215,7 @@ bool check_custom_align(CheckerContext *ctx, Ast *node, i64 *align_) {
error(node, "#align must be a power of 2, got %lld", align);
return false;
}
// NOTE(bill): Success!!!
i64 custom_align = gb_clamp(align, 1, build_context.max_align);
if (custom_align < align) {
warning(node, "Custom alignment has been clamped to %lld from %lld", align, custom_align);
}
*align_ = custom_align;
*align_ = align;
return true;
}
}
@@ -498,7 +488,7 @@ Type *check_record_polymorphic_params(CheckerContext *ctx, Ast *polymorphic_para
if (entities.count > 0) {
Type *tuple = alloc_type_tuple();
tuple->Tuple.variables = entities;
tuple->Tuple.variables = slice_from_array(entities);
polymorphic_params_type = tuple;
}
}
@@ -562,8 +552,7 @@ void check_struct_type(CheckerContext *ctx, Type *struct_type, Ast *node, Array<
case_end;
}
}
struct_type->Struct.names = make_names_field_for_struct(ctx, ctx->scope);
scope_reserve(ctx->scope, min_field_count);
if (st->is_raw_union && min_field_count > 1) {
@@ -655,7 +644,7 @@ void check_union_type(CheckerContext *ctx, Type *union_type, Ast *node, Array<Op
}
}
union_type->Union.variants = variants;
union_type->Union.variants = slice_from_array(variants);
union_type->Union.no_nil = ut->no_nil;
union_type->Union.maybe = ut->maybe;
if (union_type->Union.no_nil) {
@@ -815,9 +804,8 @@ void check_enum_type(CheckerContext *ctx, Type *enum_type, Type *named_type, Ast
enum_type->Enum.fields = fields;
enum_type->Enum.names = make_names_field_for_struct(ctx, ctx->scope);
enum_type->Enum.min_value = min_value;
enum_type->Enum.max_value = max_value;
*enum_type->Enum.min_value = min_value;
*enum_type->Enum.max_value = max_value;
enum_type->Enum.min_value_index = min_value_index;
enum_type->Enum.max_value_index = max_value_index;
@@ -838,7 +826,7 @@ void check_bit_set_type(CheckerContext *c, Type *type, Type *named_type, Ast *no
GB_ASSERT(type->kind == Type_BitSet);
type->BitSet.node = node;
i64 const DEFAULT_BITS = cast(i64)(8*build_context.word_size);
/* i64 const DEFAULT_BITS = cast(i64)(8*build_context.word_size); */
i64 const MAX_BITS = 128;
Ast *base = unparen_expr(bs->elem);
@@ -1705,7 +1693,7 @@ Type *check_get_params(CheckerContext *ctx, Scope *scope, Ast *_params, bool *is
}
Type *tuple = alloc_type_tuple();
tuple->Tuple.variables = variables;
tuple->Tuple.variables = slice_from_array(variables);
if (success_) *success_ = success;
if (specialization_count_) *specialization_count_ = specialization_count;
@@ -1815,7 +1803,7 @@ Type *check_get_results(CheckerContext *ctx, Scope *scope, Ast *_results) {
}
}
tuple->Tuple.variables = variables;
tuple->Tuple.variables = slice_from_array(variables);
return tuple;
}
@@ -2059,7 +2047,7 @@ i64 check_array_count(CheckerContext *ctx, Operand *o, Ast *e) {
Type *make_optional_ok_type(Type *value, bool typed) {
gbAllocator a = permanent_allocator();
Type *t = alloc_type_tuple();
array_init(&t->Tuple.variables, a, 2);
slice_init(&t->Tuple.variables, a, 2);
t->Tuple.variables[0] = alloc_entity_field(nullptr, blank_token, value, false, 0);
t->Tuple.variables[1] = alloc_entity_field(nullptr, blank_token, typed ? t_bool : t_untyped_bool, false, 1);
return t;
@@ -2083,11 +2071,11 @@ void init_map_entry_type(Type *type) {
*/
Scope *s = create_scope(nullptr, builtin_pkg->scope);
auto fields = array_make<Entity *>(permanent_allocator(), 0, 4);
array_add(&fields, alloc_entity_field(s, make_token_ident(str_lit("hash")), t_uintptr, false, cast(i32)fields.count, EntityState_Resolved));
array_add(&fields, alloc_entity_field(s, make_token_ident(str_lit("next")), t_int, false, cast(i32)fields.count, EntityState_Resolved));
array_add(&fields, alloc_entity_field(s, make_token_ident(str_lit("key")), type->Map.key, false, cast(i32)fields.count, EntityState_Resolved));
array_add(&fields, alloc_entity_field(s, make_token_ident(str_lit("value")), type->Map.value, false, cast(i32)fields.count, EntityState_Resolved));
auto fields = slice_make<Entity *>(permanent_allocator(), 4);
fields[0] = alloc_entity_field(s, make_token_ident(str_lit("hash")), t_uintptr, false, cast(i32)fields.count, EntityState_Resolved);
fields[1] = alloc_entity_field(s, make_token_ident(str_lit("next")), t_int, false, cast(i32)fields.count, EntityState_Resolved);
fields[2] = alloc_entity_field(s, make_token_ident(str_lit("key")), type->Map.key, false, cast(i32)fields.count, EntityState_Resolved);
fields[3] = alloc_entity_field(s, make_token_ident(str_lit("value")), type->Map.value, false, cast(i32)fields.count, EntityState_Resolved);
entry_type->Struct.fields = fields;
@@ -2120,9 +2108,9 @@ void init_map_internal_types(Type *type) {
Type *entries_type = alloc_type_dynamic_array(type->Map.entry_type);
auto fields = array_make<Entity *>(permanent_allocator(), 0, 2);
array_add(&fields, alloc_entity_field(s, make_token_ident(str_lit("hashes")), hashes_type, false, 0, EntityState_Resolved));
array_add(&fields, alloc_entity_field(s, make_token_ident(str_lit("entries")), entries_type, false, 1, EntityState_Resolved));
auto fields = slice_make<Entity *>(permanent_allocator(), 2);
fields[0] = alloc_entity_field(s, make_token_ident(str_lit("hashes")), hashes_type, false, 0, EntityState_Resolved);
fields[1] = alloc_entity_field(s, make_token_ident(str_lit("entries")), entries_type, false, 1, EntityState_Resolved);
generated_struct_type->Struct.fields = fields;
@@ -2239,8 +2227,8 @@ Type *make_soa_struct_internal(CheckerContext *ctx, Ast *array_typ_expr, Ast *el
field_count = 0;
soa_struct = alloc_type_struct();
soa_struct->Struct.fields = array_make<Entity *>(heap_allocator(), field_count+extra_field_count);
soa_struct->Struct.tags = array_make<String>(heap_allocator(), field_count+extra_field_count);
soa_struct->Struct.fields = slice_make<Entity *>(permanent_allocator(), field_count+extra_field_count);
soa_struct->Struct.tags = gb_alloc_array(permanent_allocator(), String, field_count+extra_field_count);
soa_struct->Struct.node = array_typ_expr;
soa_struct->Struct.soa_kind = soa_kind;
soa_struct->Struct.soa_elem = elem;
@@ -2254,12 +2242,16 @@ Type *make_soa_struct_internal(CheckerContext *ctx, Ast *array_typ_expr, Ast *el
field_count = cast(isize)old_array->Array.count;
soa_struct = alloc_type_struct();
soa_struct->Struct.fields = array_make<Entity *>(heap_allocator(), field_count+extra_field_count);
soa_struct->Struct.tags = array_make<String>(heap_allocator(), field_count+extra_field_count);
soa_struct->Struct.fields = slice_make<Entity *>(permanent_allocator(), field_count+extra_field_count);
soa_struct->Struct.tags = gb_alloc_array(permanent_allocator(), String, field_count+extra_field_count);
soa_struct->Struct.node = array_typ_expr;
soa_struct->Struct.soa_kind = soa_kind;
soa_struct->Struct.soa_elem = elem;
soa_struct->Struct.soa_count = count;
if (count > I32_MAX) {
count = I32_MAX;
error(array_typ_expr, "Array count too large for an #soa struct, got %lld", cast(long long)count);
}
soa_struct->Struct.soa_count = cast(i32)count;
scope = create_scope(ctx->info, ctx->scope, 8);
soa_struct->Struct.scope = scope;
@@ -2293,15 +2285,18 @@ Type *make_soa_struct_internal(CheckerContext *ctx, Ast *array_typ_expr, Ast *el
Type *old_struct = base_type(elem);
field_count = old_struct->Struct.fields.count;
GB_ASSERT(old_struct->Struct.tags.count == field_count);
soa_struct = alloc_type_struct();
soa_struct->Struct.fields = array_make<Entity *>(heap_allocator(), field_count+extra_field_count);
soa_struct->Struct.tags = array_make<String>(heap_allocator(), field_count+extra_field_count);
soa_struct->Struct.fields = slice_make<Entity *>(permanent_allocator(), field_count+extra_field_count);
soa_struct->Struct.tags = gb_alloc_array(permanent_allocator(), String, field_count+extra_field_count);
soa_struct->Struct.node = array_typ_expr;
soa_struct->Struct.soa_kind = soa_kind;
soa_struct->Struct.soa_elem = elem;
soa_struct->Struct.soa_count = count;
if (count > I32_MAX) {
count = I32_MAX;
error(array_typ_expr, "Array count too large for an #soa struct, got %lld", cast(long long)count);
}
soa_struct->Struct.soa_count = cast(i32)count;
scope = create_scope(ctx->info, old_struct->Struct.scope->parent);
soa_struct->Struct.scope = scope;
@@ -2316,7 +2311,7 @@ Type *make_soa_struct_internal(CheckerContext *ctx, Ast *array_typ_expr, Ast *el
} else {
field_type = alloc_type_pointer(old_field->type);
}
Entity *new_field = alloc_entity_field(scope, old_field->token, field_type, false, old_field->Variable.field_src_index);
Entity *new_field = alloc_entity_field(scope, old_field->token, field_type, false, old_field->Variable.field_index);
soa_struct->Struct.fields[i] = new_field;
add_entity(ctx, scope, nullptr, new_field);
add_entity_use(ctx, nullptr, new_field);
+22 -17
View File
@@ -4865,22 +4865,25 @@ void check_deferred_procedures(Checker *c) {
Entity *dst = src->Procedure.deferred_procedure.entity;
GB_ASSERT(dst != nullptr);
GB_ASSERT(dst->kind == Entity_Procedure);
char const *attribute = "deferred_none";
switch (dst_kind) {
case DeferredProcedure_none:
attribute = "deferred_none";
break;
case DeferredProcedure_in:
attribute = "deferred_in";
break;
case DeferredProcedure_out:
attribute = "deferred_out";
break;
case DeferredProcedure_in_out:
attribute = "deferred_in_out";
break;
}
if (is_type_polymorphic(src->type) || is_type_polymorphic(dst->type)) {
switch (dst_kind) {
case DeferredProcedure_none:
error(src->token, "'deferred_none' cannot be used with a polymorphic procedure");
break;
case DeferredProcedure_in:
error(src->token, "'deferred_in' cannot be used with a polymorphic procedure");
break;
case DeferredProcedure_out:
error(src->token, "'deferred_out' cannot be used with a polymorphic procedure");
break;
case DeferredProcedure_in_out:
error(src->token, "'deferred_in_out' cannot be used with a polymorphic procedure");
break;
}
error(src->token, "'%s' cannot be used with a polymorphic procedure", attribute);
continue;
}
@@ -4974,17 +4977,19 @@ void check_deferred_procedures(Checker *c) {
GB_ASSERT(src_results->kind == Type_Tuple);
len += src_results->Tuple.variables.count;
}
array_init(&sv, heap_allocator(), 0, len);
slice_init(&sv, heap_allocator(), len);
isize offset = 0;
if (src_params != nullptr) {
for_array(i, src_params->Tuple.variables) {
array_add(&sv, src_params->Tuple.variables[i]);
sv[offset++] = src_params->Tuple.variables[i];
}
}
if (src_results != nullptr) {
for_array(i, src_results->Tuple.variables) {
array_add(&sv, src_results->Tuple.variables[i]);
sv[offset++] = src_results->Tuple.variables[i];
}
}
GB_ASSERT(offset == len);
if (are_types_identical(tsrc, dst_params)) {
+121
View File
@@ -850,6 +850,127 @@ ReadDirectoryError read_directory(String path, Array<FileInfo> *fi) {
struct MemoryMappedFile {
void *handle;
void *data;
i32 size;
};
enum MemoryMappedFileError {
MemoryMappedFile_None,
MemoryMappedFile_Empty,
MemoryMappedFile_FileTooLarge,
MemoryMappedFile_Invalid,
MemoryMappedFile_NotExists,
MemoryMappedFile_Permission,
MemoryMappedFile_COUNT,
};
MemoryMappedFileError memory_map_file_32(char const *fullpath, MemoryMappedFile *memory_mapped_file, bool copy_file_contents) {
MemoryMappedFileError err = MemoryMappedFile_None;
if (!copy_file_contents) {
#if defined(GB_SYSTEM_WINDOWS)
isize w_len = 0;
wchar_t *w_str = gb__alloc_utf8_to_ucs2(temporary_allocator(), fullpath, &w_len);
if (w_str == nullptr) {
return MemoryMappedFile_Invalid;
}
i64 file_size = 0;
LARGE_INTEGER li_file_size = {};
HANDLE handle = nullptr;
HANDLE file_mapping = nullptr;
void *file_data = nullptr;
handle = CreateFileW(w_str, GENERIC_READ, FILE_SHARE_READ, nullptr, OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, NULL);
if (handle == INVALID_HANDLE_VALUE) {
handle = nullptr;
goto window_handle_file_error;
}
li_file_size = {};
if (!GetFileSizeEx(handle, &li_file_size)) {
goto window_handle_file_error;
}
file_size = cast(i64)li_file_size.QuadPart;
if (file_size > I32_MAX) {
CloseHandle(handle);
return MemoryMappedFile_FileTooLarge;
}
if (file_size == 0) {
CloseHandle(handle);
err = MemoryMappedFile_Empty;
memory_mapped_file->handle = nullptr;
memory_mapped_file->data = nullptr;
memory_mapped_file->size = 0;
return err;
}
file_mapping = CreateFileMappingW(handle, nullptr, PAGE_READONLY, 0, 0, nullptr);
CloseHandle(handle);
file_data = MapViewOfFileEx(file_mapping, FILE_MAP_READ, 0, 0, 0/*file_size*/, nullptr/*base address*/);
memory_mapped_file->handle = cast(void *)file_mapping;
memory_mapped_file->data = file_data;
memory_mapped_file->size = cast(i32)file_size;
return err;
window_handle_file_error:;
{
DWORD handle_err = GetLastError();
CloseHandle(handle);
err = MemoryMappedFile_Invalid;
switch (handle_err) {
case ERROR_FILE_NOT_FOUND:
case ERROR_PATH_NOT_FOUND:
case ERROR_INVALID_DRIVE:
err = MemoryMappedFile_NotExists;
break;
case ERROR_ACCESS_DENIED:
case ERROR_INVALID_ACCESS:
err = MemoryMappedFile_Permission;
break;
}
return err;
}
#endif
}
gbFileContents fc = gb_file_read_contents(heap_allocator(), true, fullpath);
if (fc.size > I32_MAX) {
err = MemoryMappedFile_FileTooLarge;
gb_file_free_contents(&fc);
} else if (fc.data != nullptr) {
memory_mapped_file->handle = nullptr;
memory_mapped_file->data = fc.data;
memory_mapped_file->size = cast(i32)fc.size;
} else {
gbFile f = {};
gbFileError file_err = gb_file_open(&f, fullpath);
defer (gb_file_close(&f));
switch (file_err) {
case gbFileError_Invalid: err = MemoryMappedFile_Invalid; break;
case gbFileError_NotExists: err = MemoryMappedFile_NotExists; break;
case gbFileError_Permission: err = MemoryMappedFile_Permission; break;
}
if (err == MemoryMappedFile_None && gb_file_size(&f) == 0) {
err = MemoryMappedFile_Empty;
}
}
return err;
}
#define USE_DAMERAU_LEVENSHTEIN 1
isize levenstein_distance_case_insensitive(String const &a, String const &b) {
+9 -15
View File
@@ -50,17 +50,16 @@ void virtual_memory_init(void) {
struct MemoryBlock {
MemoryBlock *prev;
u8 * base;
isize size;
isize used;
MemoryBlock *prev;
};
struct Arena {
MemoryBlock *curr_block;
isize minimum_block_size;
bool use_local_mutex;
BlockingMutex local_mutex;
bool ignore_mutex;
};
enum { DEFAULT_MINIMUM_BLOCK_SIZE = 8ll*1024ll*1024ll };
@@ -72,10 +71,6 @@ void virtual_memory_dealloc(MemoryBlock *block);
void *arena_alloc(Arena *arena, isize min_size, isize alignment);
void arena_free_all(Arena *arena);
void arena_init_local_mutex(Arena *arena) {
mutex_init(&arena->local_mutex);
arena->use_local_mutex = true;
}
isize arena_align_forward_offset(Arena *arena, isize alignment) {
isize alignment_offset = 0;
@@ -91,11 +86,9 @@ void *arena_alloc(Arena *arena, isize min_size, isize alignment) {
GB_ASSERT(gb_is_power_of_two(alignment));
BlockingMutex *mutex = &global_memory_allocator_mutex;
if (arena->use_local_mutex) {
mutex = &arena->local_mutex;
if (!arena->ignore_mutex) {
mutex_lock(mutex);
}
mutex_lock(mutex);
isize size = 0;
if (arena->curr_block != nullptr) {
@@ -122,7 +115,9 @@ void *arena_alloc(Arena *arena, isize min_size, isize alignment) {
curr_block->used += size;
GB_ASSERT(curr_block->used <= curr_block->size);
mutex_unlock(mutex);
if (!arena->ignore_mutex) {
mutex_unlock(mutex);
}
// NOTE(bill): memory will be zeroed by default due to virtual memory
return ptr;
@@ -296,14 +291,13 @@ GB_ALLOCATOR_PROC(arena_allocator_proc) {
}
gb_global Arena permanent_arena = {};
gb_global gb_thread_local Arena permanent_arena = {nullptr, DEFAULT_MINIMUM_BLOCK_SIZE, true};
gbAllocator permanent_allocator() {
return arena_allocator(&permanent_arena);
}
gb_global Arena temporary_arena = {};
gbAllocator temporary_allocator() {
return arena_allocator(&temporary_arena);
return permanent_allocator();
}
+5 -8
View File
@@ -155,8 +155,7 @@ struct Entity {
} Constant;
struct {
Ast *init_expr; // only used for some variables within procedure bodies
i32 field_index;
i32 field_src_index;
i32 field_index;
ParameterValue param_value;
Ast * param_expr;
@@ -319,20 +318,18 @@ Entity *alloc_entity_const_param(Scope *scope, Token token, Type *type, ExactVal
}
Entity *alloc_entity_field(Scope *scope, Token token, Type *type, bool is_using, i32 field_src_index, EntityState state = EntityState_Unresolved) {
Entity *alloc_entity_field(Scope *scope, Token token, Type *type, bool is_using, i32 field_index, EntityState state = EntityState_Unresolved) {
Entity *entity = alloc_entity_variable(scope, token, type);
entity->Variable.field_src_index = field_src_index;
entity->Variable.field_index = field_src_index;
entity->Variable.field_index = field_index;
if (is_using) entity->flags |= EntityFlag_Using;
entity->flags |= EntityFlag_Field;
entity->state = state;
return entity;
}
Entity *alloc_entity_array_elem(Scope *scope, Token token, Type *type, i32 field_src_index) {
Entity *alloc_entity_array_elem(Scope *scope, Token token, Type *type, i32 field_index) {
Entity *entity = alloc_entity_variable(scope, token, type);
entity->Variable.field_src_index = field_src_index;
entity->Variable.field_index = field_src_index;
entity->Variable.field_index = field_index;
entity->flags |= EntityFlag_Field;
entity->flags |= EntityFlag_ArrayElem;
entity->state = EntityState_Resolved;
+1 -1
View File
@@ -832,7 +832,7 @@ ExactValue exact_binary_operator_value(TokenKind op, ExactValue x, ExactValue y)
String sx = x.value_string;
String sy = y.value_string;
isize len = sx.len+sy.len;
u8 *data = gb_alloc_array(heap_allocator(), u8, len);
u8 *data = gb_alloc_array(permanent_allocator(), u8, len);
gb_memmove(data, sx.text, sx.len);
gb_memmove(data+sx.len, sy.text, sy.len);
return exact_value_string(make_string(data, len));
+6 -6
View File
@@ -82,7 +82,7 @@ LLVMTypeRef lb_function_type_to_llvm_ptr(lbFunctionType *ft, bool is_var_arg) {
GB_ASSERT_MSG(ret != nullptr, "%d", ft->ret.kind);
unsigned maximum_arg_count = offset+arg_count;
LLVMTypeRef *args = gb_alloc_array(heap_allocator(), LLVMTypeRef, maximum_arg_count);
LLVMTypeRef *args = gb_alloc_array(permanent_allocator(), LLVMTypeRef, maximum_arg_count);
if (offset == 1) {
GB_ASSERT(ft->ret.kind == lbArg_Indirect);
args[0] = LLVMPointerType(ft->ret.type, 0);
@@ -300,7 +300,7 @@ namespace lbAbi386 {
lbArgType compute_return_type(LLVMContextRef c, LLVMTypeRef return_type, bool return_is_defined);
LB_ABI_INFO(abi_info) {
lbFunctionType *ft = gb_alloc_item(heap_allocator(), lbFunctionType);
lbFunctionType *ft = gb_alloc_item(permanent_allocator(), lbFunctionType);
ft->ctx = c;
ft->args = compute_arg_types(c, arg_types, arg_count);
ft->ret = compute_return_type(c, return_type, return_is_defined);
@@ -378,7 +378,7 @@ namespace lbAbiAmd64Win64 {
LB_ABI_INFO(abi_info) {
lbFunctionType *ft = gb_alloc_item(heap_allocator(), lbFunctionType);
lbFunctionType *ft = gb_alloc_item(permanent_allocator(), lbFunctionType);
ft->ctx = c;
ft->args = compute_arg_types(c, arg_types, arg_count);
ft->ret = lbAbi386::compute_return_type(c, return_type, return_is_defined);
@@ -469,7 +469,7 @@ namespace lbAbiAmd64SysV {
LLVMTypeRef llreg(LLVMContextRef c, Array<RegClass> const &reg_classes);
LB_ABI_INFO(abi_info) {
lbFunctionType *ft = gb_alloc_item(heap_allocator(), lbFunctionType);
lbFunctionType *ft = gb_alloc_item(permanent_allocator(), lbFunctionType);
ft->ctx = c;
ft->calling_convention = calling_convention;
@@ -849,7 +849,7 @@ namespace lbAbiArm64 {
bool is_homogenous_aggregate(LLVMContextRef c, LLVMTypeRef type, LLVMTypeRef *base_type_, unsigned *member_count_);
LB_ABI_INFO(abi_info) {
lbFunctionType *ft = gb_alloc_item(heap_allocator(), lbFunctionType);
lbFunctionType *ft = gb_alloc_item(permanent_allocator(), lbFunctionType);
ft->ctx = c;
ft->ret = compute_return_type(c, return_type, return_is_defined);
ft -> args = compute_arg_types(c, arg_types, arg_count);
@@ -1034,7 +1034,7 @@ LB_ABI_INFO(lb_get_abi_info) {
case ProcCC_None:
case ProcCC_InlineAsm:
{
lbFunctionType *ft = gb_alloc_item(heap_allocator(), lbFunctionType);
lbFunctionType *ft = gb_alloc_item(permanent_allocator(), lbFunctionType);
ft->ctx = c;
ft->args = array_make<lbArgType>(heap_allocator(), arg_count);
for (unsigned i = 0; i < arg_count; i++) {
+5 -7
View File
@@ -763,7 +763,7 @@ lbProcedure *lb_create_main_procedure(lbModule *m, lbProcedure *startup_runtime)
if (build_context.metrics.os == TargetOs_windows && build_context.build_mode == BuildMode_DynamicLibrary) {
is_dll_main = true;
name = str_lit("DllMain");
array_init(&params->Tuple.variables, permanent_allocator(), 3);
slice_init(&params->Tuple.variables, permanent_allocator(), 3);
params->Tuple.variables[0] = alloc_entity_param(nullptr, make_token_ident("hinstDLL"), t_rawptr, false, true);
params->Tuple.variables[1] = alloc_entity_param(nullptr, make_token_ident("fdwReason"), t_u32, false, true);
params->Tuple.variables[2] = alloc_entity_param(nullptr, make_token_ident("lpReserved"), t_rawptr, false, true);
@@ -771,12 +771,12 @@ lbProcedure *lb_create_main_procedure(lbModule *m, lbProcedure *startup_runtime)
name = str_lit("mainCRTStartup");
} else {
has_args = true;
array_init(&params->Tuple.variables, permanent_allocator(), 2);
slice_init(&params->Tuple.variables, permanent_allocator(), 2);
params->Tuple.variables[0] = alloc_entity_param(nullptr, make_token_ident("argc"), t_i32, false, true);
params->Tuple.variables[1] = alloc_entity_param(nullptr, make_token_ident("argv"), t_ptr_cstring, false, true);
}
array_init(&results->Tuple.variables, permanent_allocator(), 1);
slice_init(&results->Tuple.variables, permanent_allocator(), 1);
results->Tuple.variables[0] = alloc_entity_param(nullptr, blank_token, t_i32, false, true);
Type *proc_type = alloc_type_proc(nullptr,
@@ -808,8 +808,6 @@ lbProcedure *lb_create_main_procedure(lbModule *m, lbProcedure *startup_runtime)
lbAddr all_tests_array_addr = lb_add_global_generated(p->module, array_type, {});
lbValue all_tests_array = lb_addr_get_ptr(p, all_tests_array_addr);
LLVMTypeRef lbt_Internal_Test = lb_type(m, t_Internal_Test);
LLVMValueRef indices[2] = {};
indices[0] = LLVMConstInt(lb_type(m, t_i32), 0, false);
@@ -836,7 +834,7 @@ lbProcedure *lb_create_main_procedure(lbModule *m, lbProcedure *startup_runtime)
GB_ASSERT(LLVMIsConstant(vals[2]));
LLVMValueRef dst = LLVMConstInBoundsGEP(all_tests_array.value, indices, gb_count_of(indices));
LLVMValueRef src = llvm_const_named_struct(lbt_Internal_Test, vals, gb_count_of(vals));
LLVMValueRef src = llvm_const_named_struct(m, t_Internal_Test, vals, gb_count_of(vals));
LLVMBuildStore(p->builder, src, dst);
}
@@ -1689,7 +1687,7 @@ void lb_generate_code(lbGenerator *gen) {
array_add(&gen->output_object_paths, filepath_obj);
array_add(&gen->output_temp_paths, filepath_ll);
auto *wd = gb_alloc_item(heap_allocator(), lbLLVMEmitWorker);
auto *wd = gb_alloc_item(permanent_allocator(), lbLLVMEmitWorker);
wd->target_machine = target_machines[j];
wd->code_gen_file_type = code_gen_file_type;
wd->filepath_obj = filepath_obj;
+3
View File
@@ -432,6 +432,7 @@ void lb_build_nested_proc(lbProcedure *p, AstProcLit *pd, Entity *e);
lbValue lb_emit_logical_binary_expr(lbProcedure *p, TokenKind op, Ast *left, Ast *right, Type *type);
lbValue lb_build_cond(lbProcedure *p, Ast *cond, lbBlock *true_block, lbBlock *false_block);
LLVMValueRef llvm_const_named_struct(lbModule *m, Type *t, LLVMValueRef *values, isize value_count_);
LLVMValueRef llvm_const_named_struct(LLVMTypeRef t, LLVMValueRef *values, isize value_count_);
void lb_set_entity_from_other_modules_linkage_correctly(lbModule *other_module, Entity *e, String const &name);
@@ -446,6 +447,8 @@ lbCopyElisionHint lb_set_copy_elision_hint(lbProcedure *p, lbAddr const &addr, A
void lb_reset_copy_elision_hint(lbProcedure *p, lbCopyElisionHint prev_hint);
lbValue lb_consume_copy_elision_hint(lbProcedure *p);
bool lb_struct_has_padding_prefix(Type *t);
#define LB_STARTUP_RUNTIME_PROC_NAME "__$startup_runtime"
#define LB_STARTUP_TYPE_INFO_PROC_NAME "__$startup_type_info"
#define LB_TYPE_INFO_DATA_NAME "__$type_info_data"
+62 -26
View File
@@ -99,7 +99,7 @@ LLVMValueRef llvm_const_cast(LLVMValueRef val, LLVMTypeRef dst) {
return LLVMConstNull(dst);
}
GB_ASSERT(LLVMSizeOf(dst) == LLVMSizeOf(src));
GB_ASSERT_MSG(LLVMSizeOf(dst) == LLVMSizeOf(src), "%s vs %s", LLVMPrintTypeToString(dst), LLVMPrintTypeToString(src));
LLVMTypeKind kind = LLVMGetTypeKind(dst);
switch (kind) {
case LLVMPointerTypeKind:
@@ -125,11 +125,43 @@ lbValue lb_const_ptr_cast(lbModule *m, lbValue value, Type *t) {
return res;
}
LLVMValueRef llvm_const_named_struct(lbModule *m, Type *t, LLVMValueRef *values, isize value_count_) {
LLVMTypeRef struct_type = lb_type(m, t);
GB_ASSERT(LLVMGetTypeKind(struct_type) == LLVMStructTypeKind);
unsigned value_count = cast(unsigned)value_count_;
unsigned elem_count = LLVMCountStructElementTypes(struct_type);
if (elem_count == value_count) {
return llvm_const_named_struct(struct_type, values, value_count_);
}
Type *bt = base_type(t);
GB_ASSERT(bt->kind == Type_Struct);
GB_ASSERT(value_count_ == bt->Struct.fields.count);
unsigned field_offset = 0;
if (lb_struct_has_padding_prefix(bt)) {
field_offset = 1;
}
unsigned values_with_padding_count = field_offset + cast(unsigned)(bt->Struct.fields.count*2 + 1);
LLVMValueRef *values_with_padding = gb_alloc_array(permanent_allocator(), LLVMValueRef, values_with_padding_count);
for (unsigned i = 0; i < value_count; i++) {
values_with_padding[field_offset + i*2 + 1] = values[i];
}
for (unsigned i = 0; i < values_with_padding_count; i++) {
if (values_with_padding[i] == nullptr) {
values_with_padding[i] = LLVMConstNull(LLVMStructGetTypeAtIndex(struct_type, i));
}
}
return llvm_const_named_struct(struct_type, values_with_padding, values_with_padding_count);
}
LLVMValueRef llvm_const_named_struct(LLVMTypeRef t, LLVMValueRef *values, isize value_count_) {
unsigned value_count = cast(unsigned)value_count_;
unsigned elem_count = LLVMCountStructElementTypes(t);
GB_ASSERT(value_count == elem_count);
GB_ASSERT_MSG(value_count == elem_count, "%s %u %u", LLVMPrintTypeToString(t), value_count, elem_count);
for (unsigned i = 0; i < elem_count; i++) {
LLVMTypeRef elem_type = LLVMStructGetTypeAtIndex(t, i);
values[i] = llvm_const_cast(values[i], elem_type);
@@ -235,7 +267,7 @@ lbValue lb_emit_source_code_location(lbProcedure *p, String const &procedure, To
fields[3]/*procedure*/ = lb_find_or_add_entity_string(p->module, procedure).value;
lbValue res = {};
res.value = llvm_const_named_struct(lb_type(m, t_source_code_location), fields, gb_count_of(fields));
res.value = llvm_const_named_struct(m, t_source_code_location, fields, gb_count_of(fields));
res.type = t_source_code_location;
return res;
}
@@ -422,7 +454,7 @@ lbValue lb_const_value(lbModule *m, Type *type, ExactValue value, bool allow_loc
LLVMValueRef len = LLVMConstInt(lb_type(m, t_int), count, true);
LLVMValueRef values[2] = {ptr, len};
res.value = llvm_const_named_struct(lb_type(m, original_type), values, 2);
res.value = llvm_const_named_struct(m, original_type, values, 2);
return res;
}
}
@@ -512,7 +544,7 @@ lbValue lb_const_value(lbModule *m, Type *type, ExactValue value, bool allow_loc
LLVMValueRef values[2] = {ptr, str_len};
GB_ASSERT(is_type_string(original_type));
res.value = llvm_const_named_struct(lb_type(m, original_type), values, 2);
res.value = llvm_const_named_struct(m, original_type, values, 2);
}
return res;
@@ -554,7 +586,7 @@ lbValue lb_const_value(lbModule *m, Type *type, ExactValue value, bool allow_loc
break;
}
res.value = llvm_const_named_struct(lb_type(m, original_type), values, 2);
res.value = llvm_const_named_struct(m, original_type, values, 2);
return res;
}
break;
@@ -585,7 +617,7 @@ lbValue lb_const_value(lbModule *m, Type *type, ExactValue value, bool allow_loc
break;
}
res.value = llvm_const_named_struct(lb_type(m, original_type), values, 4);
res.value = llvm_const_named_struct(m, original_type, values, 4);
return res;
}
break;
@@ -690,8 +722,8 @@ lbValue lb_const_value(lbModule *m, Type *type, ExactValue value, bool allow_loc
isize value_index = 0;
i64 total_lo = exact_value_to_i64(type->EnumeratedArray.min_value);
i64 total_hi = exact_value_to_i64(type->EnumeratedArray.max_value);
i64 total_lo = exact_value_to_i64(*type->EnumeratedArray.min_value);
i64 total_hi = exact_value_to_i64(*type->EnumeratedArray.max_value);
for (i64 i = total_lo; i <= total_hi; i++) {
bool found = false;
@@ -802,11 +834,15 @@ lbValue lb_const_value(lbModule *m, Type *type, ExactValue value, bool allow_loc
}
isize offset = 0;
if (type->Struct.custom_align > 0) {
if (lb_struct_has_padding_prefix(type)) {
offset = 1;
}
LLVMTypeRef struct_type = lb_type(m, original_type);
isize value_count = type->Struct.fields.count + offset;
unsigned value_count = cast(unsigned)(offset + type->Struct.fields.count*2 + 1);
GB_ASSERT(LLVMCountStructElementTypes(struct_type) == value_count);
LLVMValueRef *values = gb_alloc_array(temporary_allocator(), LLVMValueRef, value_count);
bool *visited = gb_alloc_array(temporary_allocator(), bool, value_count);
@@ -822,9 +858,11 @@ lbValue lb_const_value(lbModule *m, Type *type, ExactValue value, bool allow_loc
Selection sel = lookup_field(type, name, false);
Entity *f = type->Struct.fields[sel.index[0]];
isize index = offset + f->Variable.field_index*2 + 1;
if (elem_type_can_be_constant(f->type)) {
values[offset+f->Variable.field_index] = lb_const_value(m, f->type, tav.value, allow_local).value;
visited[offset+f->Variable.field_index] = true;
values[index] = lb_const_value(m, f->type, tav.value, allow_local).value;
visited[index] = true;
}
}
} else {
@@ -835,25 +873,24 @@ lbValue lb_const_value(lbModule *m, Type *type, ExactValue value, bool allow_loc
if (tav.mode != Addressing_Invalid) {
val = tav.value;
}
isize index = offset + f->Variable.field_index*2 + 1;
if (elem_type_can_be_constant(f->type)) {
values[offset+f->Variable.field_index] = lb_const_value(m, f->type, val, allow_local).value;
visited[offset+f->Variable.field_index] = true;
values[index] = lb_const_value(m, f->type, val, allow_local).value;
visited[index] = true;
}
}
}
}
for (isize i = 0; i < type->Struct.fields.count; i++) {
if (!visited[offset+i]) {
GB_ASSERT(values[offset+i] == nullptr);
values[offset+i] = lb_const_nil(m, get_struct_field_type(type, i)).value;
for (isize i = 0; i < value_count; i++) {
if (!visited[i]) {
GB_ASSERT(values[i] == nullptr);
LLVMTypeRef type = LLVMStructGetTypeAtIndex(struct_type, cast(unsigned)i);
values[i] = LLVMConstNull(type);
}
}
if (type->Struct.custom_align > 0) {
values[0] = LLVMConstNull(lb_alignment_prefix_type_hack(m, type->Struct.custom_align));
}
bool is_constant = true;
for (isize i = 0; i < value_count; i++) {
@@ -866,7 +903,7 @@ lbValue lb_const_value(lbModule *m, Type *type, ExactValue value, bool allow_loc
}
if (is_constant) {
res.value = llvm_const_named_struct(lb_type(m, original_type), values, cast(unsigned)value_count);
res.value = llvm_const_named_struct(struct_type, values, cast(unsigned)value_count);
return res;
} else {
// TODO(bill): THIS IS HACK BUT IT WORKS FOR WHAT I NEED
@@ -880,8 +917,7 @@ lbValue lb_const_value(lbModule *m, Type *type, ExactValue value, bool allow_loc
new_values[i] = LLVMConstNull(LLVMTypeOf(old_value));
}
}
LLVMValueRef constant_value = llvm_const_named_struct(lb_type(m, original_type), new_values, cast(unsigned)value_count);
LLVMValueRef constant_value = llvm_const_named_struct(struct_type, new_values, cast(unsigned)value_count);
GB_ASSERT(is_local);
lbProcedure *p = m->curr_procedure;
+4 -4
View File
@@ -50,8 +50,8 @@ LLVMMetadataRef lb_debug_type_internal_proc(lbModule *m, Type *type) {
GB_ASSERT(type != t_invalid);
unsigned const word_size = cast(unsigned)build_context.word_size;
unsigned const word_bits = cast(unsigned)(8*build_context.word_size);
/* unsigned const word_size = cast(unsigned)build_context.word_size;
unsigned const word_bits = cast(unsigned)(8*build_context.word_size); */
GB_ASSERT(type->kind == Type_Proc);
unsigned parameter_count = 1;
@@ -129,7 +129,7 @@ LLVMMetadataRef lb_debug_type_internal(lbModule *m, Type *type) {
GB_ASSERT(type != t_invalid);
unsigned const word_size = cast(unsigned)build_context.word_size;
/* unsigned const word_size = cast(unsigned)build_context.word_size; */
unsigned const word_bits = cast(unsigned)(8*build_context.word_size);
switch (type->kind) {
@@ -564,7 +564,7 @@ LLVMMetadataRef lb_debug_type(lbModule *m, Type *type) {
}
void lb_debug_complete_types(lbModule *m) {
unsigned const word_size = cast(unsigned)build_context.word_size;
/* unsigned const word_size = cast(unsigned)build_context.word_size; */
unsigned const word_bits = cast(unsigned)(8*build_context.word_size);
for_array(debug_incomplete_type_index, m->debug_incomplete_types) {
+9 -10
View File
@@ -1923,9 +1923,9 @@ lbValue lb_emit_comp_against_nil(lbProcedure *p, TokenKind op_kind, lbValue x) {
lbValue map_ptr = lb_address_from_load_or_generate_local(p, x);
unsigned indices[2] = {0, 0};
LLVMValueRef hashes_data = LLVMBuildStructGEP(p->builder, map_ptr.value, 0, "");
LLVMValueRef hashes_data_ptr_ptr = LLVMBuildStructGEP(p->builder, hashes_data, 0, "");
LLVMValueRef hashes_data_ptr = LLVMBuildLoad(p->builder, hashes_data_ptr_ptr, "");
lbValue hashes_data = lb_emit_struct_ep(p, map_ptr, 0);
lbValue hashes_data_ptr_ptr = lb_emit_struct_ep(p, hashes_data, 0);
LLVMValueRef hashes_data_ptr = LLVMBuildLoad(p->builder, hashes_data_ptr_ptr.value, "");
if (op_kind == Token_CmpEq) {
res.value = LLVMBuildIsNull(p->builder, hashes_data_ptr, "");
@@ -2786,7 +2786,7 @@ lbAddr lb_build_addr(lbProcedure *p, Ast *expr) {
bool deref = is_type_pointer(t);
t = base_type(type_deref(t));
if (is_type_soa_struct(t)) {
if (is_type_soa_struct(t)) {
// SOA STRUCTURES!!!!
lbValue val = lb_build_addr_ptr(p, ie->expr);
if (deref) {
@@ -2821,7 +2821,6 @@ lbAddr lb_build_addr(lbProcedure *p, Ast *expr) {
// lbValue len = ir_soa_struct_len(p, base_struct);
// lb_emit_bounds_check(p, ast_token(ie->index), index, len);
}
lbValue val = lb_emit_ptr_offset(p, field, index);
return lb_addr(val);
}
@@ -2872,13 +2871,13 @@ lbAddr lb_build_addr(lbProcedure *p, Ast *expr) {
auto index_tv = type_and_value_of_expr(ie->index);
lbValue index = {};
if (compare_exact_values(Token_NotEq, t->EnumeratedArray.min_value, exact_value_i64(0))) {
if (compare_exact_values(Token_NotEq, *t->EnumeratedArray.min_value, exact_value_i64(0))) {
if (index_tv.mode == Addressing_Constant) {
ExactValue idx = exact_value_sub(index_tv.value, t->EnumeratedArray.min_value);
ExactValue idx = exact_value_sub(index_tv.value, *t->EnumeratedArray.min_value);
index = lb_const_value(p->module, index_type, idx);
} else {
index = lb_emit_conv(p, lb_build_expr(p, ie->index), t_int);
index = lb_emit_arith(p, Token_Sub, index, lb_const_value(p->module, index_type, t->EnumeratedArray.min_value), index_type);
index = lb_emit_arith(p, Token_Sub, index, lb_const_value(p->module, index_type, *t->EnumeratedArray.min_value), index_type);
}
} else {
index = lb_emit_conv(p, lb_build_expr(p, ie->index), t_int);
@@ -3259,7 +3258,7 @@ lbAddr lb_build_addr(lbProcedure *p, Ast *expr) {
TypeAndValue tav = type_and_value_of_expr(elem);
} else {
TypeAndValue tav = type_and_value_of_expr(elem);
Selection sel = lookup_field_from_index(bt, st->fields[field_index]->Variable.field_src_index);
Selection sel = lookup_field_from_index(bt, st->fields[field_index]->Variable.field_index);
index = sel.index[0];
}
@@ -3472,7 +3471,7 @@ lbAddr lb_build_addr(lbProcedure *p, Ast *expr) {
}
i32 index_offset = cast(i32)exact_value_to_i64(bt->EnumeratedArray.min_value);
i32 index_offset = cast(i32)exact_value_to_i64(*bt->EnumeratedArray.min_value);
for_array(i, temp_data) {
i32 index = temp_data[i].elem_index - index_offset;
+58 -18
View File
@@ -1109,7 +1109,7 @@ lbValue lb_emit_union_tag_ptr(lbProcedure *p, lbValue u) {
LLVMTypeRef uvt = LLVMGetElementType(LLVMTypeOf(u.value));
unsigned element_count = LLVMCountStructElementTypes(uvt);
GB_ASSERT_MSG(element_count == 3, "(%s) != (%s)", type_to_string(ut), LLVMPrintTypeToString(uvt));
GB_ASSERT_MSG(element_count == 3, "element_count=%u (%s) != (%s)", element_count, type_to_string(ut), LLVMPrintTypeToString(uvt));
lbValue tag_ptr = {};
tag_ptr.value = LLVMBuildStructGEP(p->builder, u.value, 2, "");
@@ -1160,13 +1160,9 @@ LLVMTypeRef lb_alignment_prefix_type_hack(lbModule *m, i64 alignment) {
return LLVMArrayType(lb_type(m, t_u32), 0);
case 8:
return LLVMArrayType(lb_type(m, t_u64), 0);
case 16:
default: case 16:
return LLVMArrayType(LLVMVectorType(lb_type(m, t_u32), 4), 0);
default:
GB_PANIC("Invalid alignment %d", cast(i32)alignment);
break;
}
return nullptr;
}
String lb_mangle_name(lbModule *m, Entity *e) {
@@ -1650,11 +1646,17 @@ LLVMTypeRef lb_type_internal(lbModule *m, Type *type) {
GB_ASSERT(field_count == 2);
LLVMTypeRef *fields = gb_alloc_array(temporary_allocator(), LLVMTypeRef, field_count);
LLVMTypeRef entries_fields[4] = {
lb_type(m, t_rawptr),
LLVMTypeRef padding_type = LLVMArrayType(lb_type(m, t_uintptr), 0);
LLVMTypeRef entries_fields[] = {
padding_type,
lb_type(m, t_rawptr), // data
padding_type,
lb_type(m, t_int), // len
padding_type,
lb_type(m, t_int), // cap
padding_type,
lb_type(m, t_allocator), // allocator
padding_type,
};
fields[0] = lb_type(m, internal_type->Struct.fields[0]->type);
@@ -1670,31 +1672,69 @@ LLVMTypeRef lb_type_internal(lbModule *m, Type *type) {
LLVMTypeRef *fields = gb_alloc_array(permanent_allocator(), LLVMTypeRef, field_count);
i64 alignment = type_align_of(type);
unsigned size_of_union = cast(unsigned)type_size_of(type);
fields[0] = lb_alignment_prefix_type_hack(m, alignment);
fields[0] = lb_alignment_prefix_type_hack(m, gb_min(alignment, 16));
fields[1] = LLVMArrayType(lb_type(m, t_u8), size_of_union);
return LLVMStructTypeInContext(ctx, fields, field_count, false);
}
isize offset = 0;
if (type->Struct.custom_align > 0) {
if (lb_struct_has_padding_prefix(type)) {
offset = 1;
}
m->internal_type_level += 1;
defer (m->internal_type_level -= 1);
unsigned field_count = cast(unsigned)(type->Struct.fields.count + offset);
unsigned field_count = cast(unsigned)(offset + type->Struct.fields.count*2 + 1);
LLVMTypeRef *fields = gb_alloc_array(temporary_allocator(), LLVMTypeRef, field_count);
LLVMTypeRef type_u8 = lb_type(m, t_u8);
LLVMTypeRef type_u16 = lb_type(m, t_u16);
LLVMTypeRef type_u32 = lb_type(m, t_u32);
LLVMTypeRef type_u64 = lb_type(m, t_u64);
i64 padding_offset = 0;
for_array(i, type->Struct.fields) {
Entity *field = type->Struct.fields[i];
fields[i+offset] = lb_type(m, field->type);
i64 padding = type->Struct.offsets[i]-padding_offset;
LLVMTypeRef padding_type = nullptr;
if (padding_offset == 0) {
padding_type = lb_alignment_prefix_type_hack(m, type_align_of(type));
} else {
i64 alignment = type_align_of(field->type);
// NOTE(bill): limit to `[N x u64]` to prevent ABI issues
alignment = gb_min(alignment, 8);
if (padding % alignment == 0) {
isize len = padding/alignment;
switch (alignment) {
case 1: padding_type = LLVMArrayType(type_u8, cast(unsigned)len); break;
case 2: padding_type = LLVMArrayType(type_u16, cast(unsigned)len); break;
case 4: padding_type = LLVMArrayType(type_u32, cast(unsigned)len); break;
case 8: padding_type = LLVMArrayType(type_u64, cast(unsigned)len); break;
}
} else {
padding_type = LLVMArrayType(type_u8, cast(unsigned)padding);
}
}
fields[offset + i*2 + 0] = padding_type;
fields[offset + i*2 + 1] = lb_type(m, field->type);
if (!type->Struct.is_packed) {
padding_offset = align_formula(padding_offset, type_align_of(field->type));
}
padding_offset += type_size_of(field->type);
}
i64 end_padding = type_size_of(type)-padding_offset;
fields[field_count-1] = LLVMArrayType(type_u8, cast(unsigned)end_padding);
if (type->Struct.custom_align > 0) {
if (offset != 0) {
GB_ASSERT(offset == 1);
fields[0] = lb_alignment_prefix_type_hack(m, type->Struct.custom_align);
}
for (unsigned i = 0; i < field_count; i++) {
GB_ASSERT(fields[i] != nullptr);
}
return LLVMStructTypeInContext(ctx, fields, field_count, type->Struct.is_packed);
}
@@ -1789,7 +1829,7 @@ LLVMTypeRef lb_type_internal(lbModule *m, Type *type) {
defer (m->internal_type_level -= 1);
LLVMTypeRef ret = nullptr;
LLVMTypeRef *params = gb_alloc_array(heap_allocator(), LLVMTypeRef, param_count);
LLVMTypeRef *params = gb_alloc_array(permanent_allocator(), LLVMTypeRef, param_count);
if (type->Proc.result_count != 0) {
Type *single_ret = reduce_tuple_to_single_type(type->Proc.results);
ret = lb_type(m, single_ret);
@@ -1883,7 +1923,7 @@ LLVMTypeRef lb_type_internal(lbModule *m, Type *type) {
LLVMTypeRef base_integer = lb_type_internal(m, type->RelativeSlice.base_integer);
unsigned field_count = 2;
LLVMTypeRef *fields = gb_alloc_array(heap_allocator(), LLVMTypeRef, field_count);
LLVMTypeRef *fields = gb_alloc_array(permanent_allocator(), LLVMTypeRef, field_count);
fields[0] = base_integer;
fields[1] = base_integer;
return LLVMStructTypeInContext(ctx, fields, field_count, false);
@@ -2230,7 +2270,7 @@ lbValue lb_find_or_add_entity_string(lbModule *m, String const &str) {
LLVMValueRef values[2] = {ptr, str_len};
lbValue res = {};
res.value = llvm_const_named_struct(lb_type(m, t_string), values, 2);
res.value = llvm_const_named_struct(m, t_string, values, 2);
res.type = t_string;
return res;
}
@@ -2265,7 +2305,7 @@ lbValue lb_find_or_add_entity_string_byte_slice(lbModule *m, String const &str)
LLVMValueRef values[2] = {ptr, len};
lbValue res = {};
res.value = llvm_const_named_struct(lb_type(m, t_u8_slice), values, 2);
res.value = llvm_const_named_struct(m, t_u8_slice, values, 2);
res.type = t_u8_slice;
return res;
}
+2 -2
View File
@@ -1393,7 +1393,7 @@ lbValue lb_build_builtin_proc(lbProcedure *p, Ast *expr, TypeAndValue const &tv,
Type *res_type = nullptr;
gbAllocator a = permanent_allocator();
res_type = alloc_type_tuple();
array_init(&res_type->Tuple.variables, a, 2);
slice_init(&res_type->Tuple.variables, a, 2);
res_type->Tuple.variables[0] = alloc_entity_field(nullptr, blank_token, type, false, 0);
res_type->Tuple.variables[1] = alloc_entity_field(nullptr, blank_token, t_llvm_bool, false, 1);
@@ -1738,7 +1738,7 @@ lbValue lb_build_builtin_proc(lbProcedure *p, Ast *expr, TypeAndValue const &tv,
if (tv.type->kind == Type_Tuple) {
Type *fix_typed = alloc_type_tuple();
array_init(&fix_typed->Tuple.variables, permanent_allocator(), 2);
slice_init(&fix_typed->Tuple.variables, permanent_allocator(), 2);
fix_typed->Tuple.variables[0] = tv.type->Tuple.variables[0];
fix_typed->Tuple.variables[1] = alloc_entity_field(nullptr, blank_token, t_llvm_bool, false, 1);
+4 -5
View File
@@ -332,8 +332,8 @@ void lb_build_range_indexed(lbProcedure *p, lbValue expr, Type *val_type, lbValu
val = lb_emit_load(p, lb_emit_array_ep(p, expr, idx));
// NOTE(bill): Override the idx value for the enumeration
Type *index_type = expr_type->EnumeratedArray.index;
if (compare_exact_values(Token_NotEq, expr_type->EnumeratedArray.min_value, exact_value_u64(0))) {
idx = lb_emit_arith(p, Token_Add, idx, lb_const_value(m, index_type, expr_type->EnumeratedArray.min_value), index_type);
if (compare_exact_values(Token_NotEq, *expr_type->EnumeratedArray.min_value, exact_value_u64(0))) {
idx = lb_emit_arith(p, Token_Add, idx, lb_const_value(m, index_type, *expr_type->EnumeratedArray.min_value), index_type);
}
}
break;
@@ -357,8 +357,7 @@ void lb_build_range_indexed(lbProcedure *p, lbValue expr, Type *val_type, lbValu
lbValue entries = lb_map_entries_ptr(p, expr);
lbValue elem = lb_emit_struct_ep(p, entries, 0);
elem = lb_emit_load(p, elem);
lbValue entry = lb_emit_ptr_offset(p, elem, idx);
lbValue entry = lb_emit_ptr_offset(p, elem, idx);
idx = lb_emit_load(p, lb_emit_struct_ep(p, entry, 2));
val = lb_emit_load(p, lb_emit_struct_ep(p, entry, 3));
@@ -984,7 +983,7 @@ void lb_build_unroll_range_stmt(lbProcedure *p, AstUnrollRangeStmt *rs, Scope *s
lb_addr_store(p, val0_addr, lb_emit_load(p, elem));
}
if (val1_type) {
ExactValue idx = exact_value_add(exact_value_i64(i), t->EnumeratedArray.min_value);
ExactValue idx = exact_value_add(exact_value_i64(i), *t->EnumeratedArray.min_value);
lb_addr_store(p, val1_addr, lb_const_value(m, val1_type, idx));
}
+65 -36
View File
@@ -157,12 +157,14 @@ lbValue lb_type_info_member_tags_offset(lbProcedure *p, isize count) {
void lb_setup_type_info_data(lbProcedure *p) { // NOTE(bill): Setup type_info data
lbModule *m = p->module;
CheckerInfo *info = m->info;
i64 global_type_info_data_entity_count = 0;
{
// NOTE(bill): Set the type_table slice with the global backing array
lbValue global_type_table = lb_find_runtime_value(m, str_lit("type_table"));
Type *type = base_type(lb_global_type_info_data_entity->type);
GB_ASSERT(is_type_array(type));
global_type_info_data_entity_count = type->Array.count;
LLVMValueRef indices[2] = {llvm_zero(m), llvm_zero(m)};
LLVMValueRef values[2] = {
@@ -179,6 +181,11 @@ void lb_setup_type_info_data(lbProcedure *p) { // NOTE(bill): Setup type_info da
Entity *type_info_flags_entity = find_core_entity(info->checker, str_lit("Type_Info_Flags"));
Type *t_type_info_flags = type_info_flags_entity->type;
auto entries_handled = slice_make<bool>(heap_allocator(), cast(isize)global_type_info_data_entity_count);
defer (gb_free(heap_allocator(), entries_handled.data));
entries_handled[0] = true;
for_array(type_info_type_index, info->type_info_types) {
Type *t = info->type_info_types[type_info_type_index];
if (t == nullptr || t == t_invalid) {
@@ -189,19 +196,36 @@ void lb_setup_type_info_data(lbProcedure *p) { // NOTE(bill): Setup type_info da
if (entry_index <= 0) {
continue;
}
if (entries_handled[entry_index]) {
continue;
}
entries_handled[entry_index] = true;
lbValue global_data_ptr = lb_global_type_info_data_ptr(m);
lbValue tag = {};
lbValue ti_ptr = lb_emit_array_epi(p, lb_global_type_info_data_ptr(m), cast(i32)entry_index);
lbValue ti_ptr = lb_emit_array_epi(p, global_data_ptr, cast(i32)entry_index);
i64 size = type_size_of(t);
i64 align = type_align_of(t);
u32 flags = type_info_flags_of_type(t);
lbValue id = lb_typeid(m, t);
GB_ASSERT_MSG(align != 0, "%lld %s", align, type_to_string(t));
lbValue type_info_flags = lb_const_int(p->module, t_type_info_flags, flags);
lbValue size_ptr = lb_emit_struct_ep(p, ti_ptr, 0);
lbValue align_ptr = lb_emit_struct_ep(p, ti_ptr, 1);
lbValue flags_ptr = lb_emit_struct_ep(p, ti_ptr, 2);
lbValue id_ptr = lb_emit_struct_ep(p, ti_ptr, 3);
lb_emit_store(p, size_ptr, lb_const_int(m, t_int, size));
lb_emit_store(p, align_ptr, lb_const_int(m, t_int, align));
lb_emit_store(p, flags_ptr, type_info_flags);
lb_emit_store(p, id_ptr, id);
lbValue variant_ptr = lb_emit_struct_ep(p, ti_ptr, 4);
lbValue type_info_flags = lb_const_int(p->module, t_type_info_flags, type_info_flags_of_type(t));
lb_emit_store(p, lb_emit_struct_ep(p, ti_ptr, 0), lb_const_int(m, t_int, type_size_of(t)));
lb_emit_store(p, lb_emit_struct_ep(p, ti_ptr, 1), lb_const_int(m, t_int, type_align_of(t)));
lb_emit_store(p, lb_emit_struct_ep(p, ti_ptr, 2), type_info_flags);
lb_emit_store(p, lb_emit_struct_ep(p, ti_ptr, 3), lb_typeid(m, t));
switch (t->kind) {
case Type_Named: {
tag = lb_const_ptr_cast(m, variant_ptr, t_type_info_named_ptr);
@@ -233,7 +257,7 @@ void lb_setup_type_info_data(lbProcedure *p) { // NOTE(bill): Setup type_info da
lbValue res = {};
res.type = type_deref(tag.type);
res.value = llvm_const_named_struct(lb_type(m, res.type), vals, gb_count_of(vals));
res.value = llvm_const_named_struct(m, res.type, vals, gb_count_of(vals));
lb_emit_store(p, tag, res);
break;
}
@@ -298,7 +322,7 @@ void lb_setup_type_info_data(lbProcedure *p) { // NOTE(bill): Setup type_info da
lbValue res = {};
res.type = type_deref(tag.type);
res.value = llvm_const_named_struct(lb_type(m, res.type), vals, gb_count_of(vals));
res.value = llvm_const_named_struct(m, res.type, vals, gb_count_of(vals));
lb_emit_store(p, tag, res);
break;
}
@@ -334,7 +358,7 @@ void lb_setup_type_info_data(lbProcedure *p) { // NOTE(bill): Setup type_info da
lbValue res = {};
res.type = type_deref(tag.type);
res.value = llvm_const_named_struct(lb_type(m, res.type), vals, gb_count_of(vals));
res.value = llvm_const_named_struct(m, res.type, vals, gb_count_of(vals));
lb_emit_store(p, tag, res);
}
break;
@@ -368,7 +392,7 @@ void lb_setup_type_info_data(lbProcedure *p) { // NOTE(bill): Setup type_info da
lbValue res = {};
res.type = type_deref(tag.type);
res.value = llvm_const_named_struct(lb_type(m, res.type), vals, gb_count_of(vals));
res.value = llvm_const_named_struct(m, res.type, vals, gb_count_of(vals));
lb_emit_store(p, tag, res);
}
break;
@@ -393,7 +417,7 @@ void lb_setup_type_info_data(lbProcedure *p) { // NOTE(bill): Setup type_info da
lbValue res = {};
res.type = type_deref(tag.type);
res.value = llvm_const_named_struct(lb_type(m, res.type), vals, gb_count_of(vals));
res.value = llvm_const_named_struct(m, res.type, vals, gb_count_of(vals));
lb_emit_store(p, tag, res);
break;
}
@@ -407,7 +431,7 @@ void lb_setup_type_info_data(lbProcedure *p) { // NOTE(bill): Setup type_info da
lbValue res = {};
res.type = type_deref(tag.type);
res.value = llvm_const_named_struct(lb_type(m, res.type), vals, gb_count_of(vals));
res.value = llvm_const_named_struct(m, res.type, vals, gb_count_of(vals));
lb_emit_store(p, tag, res);
break;
}
@@ -423,7 +447,7 @@ void lb_setup_type_info_data(lbProcedure *p) { // NOTE(bill): Setup type_info da
lbValue res = {};
res.type = type_deref(tag.type);
res.value = llvm_const_named_struct(lb_type(m, res.type), vals, gb_count_of(vals));
res.value = llvm_const_named_struct(m, res.type, vals, gb_count_of(vals));
lb_emit_store(p, tag, res);
break;
}
@@ -443,15 +467,15 @@ void lb_setup_type_info_data(lbProcedure *p) { // NOTE(bill): Setup type_info da
lbValue res = {};
res.type = type_deref(tag.type);
res.value = llvm_const_named_struct(lb_type(m, res.type), vals, gb_count_of(vals));
res.value = llvm_const_named_struct(m, res.type, vals, gb_count_of(vals));
lb_emit_store(p, tag, res);
// NOTE(bill): Union assignment
lbValue min_value = lb_emit_struct_ep(p, tag, 4);
lbValue max_value = lb_emit_struct_ep(p, tag, 5);
lbValue min_v = lb_const_value(m, t_i64, t->EnumeratedArray.min_value);
lbValue max_v = lb_const_value(m, t_i64, t->EnumeratedArray.max_value);
lbValue min_v = lb_const_value(m, t_i64, *t->EnumeratedArray.min_value);
lbValue max_v = lb_const_value(m, t_i64, *t->EnumeratedArray.max_value);
lb_emit_store(p, min_value, min_v);
lb_emit_store(p, max_value, max_v);
@@ -467,7 +491,7 @@ void lb_setup_type_info_data(lbProcedure *p) { // NOTE(bill): Setup type_info da
lbValue res = {};
res.type = type_deref(tag.type);
res.value = llvm_const_named_struct(lb_type(m, res.type), vals, gb_count_of(vals));
res.value = llvm_const_named_struct(m, res.type, vals, gb_count_of(vals));
lb_emit_store(p, tag, res);
break;
}
@@ -481,7 +505,7 @@ void lb_setup_type_info_data(lbProcedure *p) { // NOTE(bill): Setup type_info da
lbValue res = {};
res.type = type_deref(tag.type);
res.value = llvm_const_named_struct(lb_type(m, res.type), vals, gb_count_of(vals));
res.value = llvm_const_named_struct(m, res.type, vals, gb_count_of(vals));
lb_emit_store(p, tag, res);
break;
}
@@ -506,7 +530,7 @@ void lb_setup_type_info_data(lbProcedure *p) { // NOTE(bill): Setup type_info da
lbValue res = {};
res.type = type_deref(tag.type);
res.value = llvm_const_named_struct(lb_type(m, res.type), vals, gb_count_of(vals));
res.value = llvm_const_named_struct(m, res.type, vals, gb_count_of(vals));
lb_emit_store(p, tag, res);
break;
}
@@ -545,7 +569,7 @@ void lb_setup_type_info_data(lbProcedure *p) { // NOTE(bill): Setup type_info da
lbValue res = {};
res.type = type_deref(tag.type);
res.value = llvm_const_named_struct(lb_type(m, res.type), vals, gb_count_of(vals));
res.value = llvm_const_named_struct(m, res.type, vals, gb_count_of(vals));
lb_emit_store(p, tag, res);
break;
@@ -596,7 +620,7 @@ void lb_setup_type_info_data(lbProcedure *p) { // NOTE(bill): Setup type_info da
lbValue res = {};
res.type = type_deref(tag.type);
res.value = llvm_const_named_struct(lb_type(m, res.type), vals, gb_count_of(vals));
res.value = llvm_const_named_struct(m, res.type, vals, gb_count_of(vals));
lb_emit_store(p, tag, res);
}
break;
@@ -650,7 +674,7 @@ void lb_setup_type_info_data(lbProcedure *p) { // NOTE(bill): Setup type_info da
lbValue res = {};
res.type = type_deref(tag.type);
res.value = llvm_const_named_struct(lb_type(m, res.type), vals, gb_count_of(vals));
res.value = llvm_const_named_struct(m, res.type, vals, gb_count_of(vals));
lb_emit_store(p, tag, res);
}
@@ -688,7 +712,7 @@ void lb_setup_type_info_data(lbProcedure *p) { // NOTE(bill): Setup type_info da
vals[11] = soa_len.value;
}
}
isize count = t->Struct.fields.count;
if (count > 0) {
lbValue memory_types = lb_type_info_member_types_offset (p, count);
@@ -721,7 +745,7 @@ void lb_setup_type_info_data(lbProcedure *p) { // NOTE(bill): Setup type_info da
lb_emit_store(p, offset, lb_const_int(m, t_uintptr, foffset));
lb_emit_store(p, is_using, lb_const_bool(m, t_bool, (f->flags&EntityFlag_Using) != 0));
if (t->Struct.tags.count > 0) {
if (t->Struct.tags != nullptr) {
String tag_string = t->Struct.tags[source_index];
if (tag_string.len > 0) {
lbValue tag_ptr = lb_emit_ptr_offset(p, memory_tags, index);
@@ -743,11 +767,10 @@ void lb_setup_type_info_data(lbProcedure *p) { // NOTE(bill): Setup type_info da
vals[i] = LLVMConstNull(lb_type(m, get_struct_field_type(tag.type, i)));
}
}
lbValue res = {};
res.type = type_deref(tag.type);
res.value = llvm_const_named_struct(lb_type(m, res.type), vals, gb_count_of(vals));
res.value = llvm_const_named_struct(m, res.type, vals, gb_count_of(vals));
lb_emit_store(p, tag, res);
break;
@@ -767,7 +790,7 @@ void lb_setup_type_info_data(lbProcedure *p) { // NOTE(bill): Setup type_info da
lbValue res = {};
res.type = type_deref(tag.type);
res.value = llvm_const_named_struct(lb_type(m, res.type), vals, gb_count_of(vals));
res.value = llvm_const_named_struct(m, res.type, vals, gb_count_of(vals));
lb_emit_store(p, tag, res);
break;
}
@@ -791,7 +814,7 @@ void lb_setup_type_info_data(lbProcedure *p) { // NOTE(bill): Setup type_info da
lbValue res = {};
res.type = type_deref(tag.type);
res.value = llvm_const_named_struct(lb_type(m, res.type), vals, gb_count_of(vals));
res.value = llvm_const_named_struct(m, res.type, vals, gb_count_of(vals));
lb_emit_store(p, tag, res);
}
break;
@@ -808,7 +831,7 @@ void lb_setup_type_info_data(lbProcedure *p) { // NOTE(bill): Setup type_info da
lbValue res = {};
res.type = type_deref(tag.type);
res.value = llvm_const_named_struct(lb_type(m, res.type), vals, gb_count_of(vals));
res.value = llvm_const_named_struct(m, res.type, vals, gb_count_of(vals));
lb_emit_store(p, tag, res);
}
break;
@@ -823,7 +846,7 @@ void lb_setup_type_info_data(lbProcedure *p) { // NOTE(bill): Setup type_info da
lbValue res = {};
res.type = type_deref(tag.type);
res.value = llvm_const_named_struct(lb_type(m, res.type), vals, gb_count_of(vals));
res.value = llvm_const_named_struct(m, res.type, vals, gb_count_of(vals));
lb_emit_store(p, tag, res);
}
break;
@@ -837,7 +860,7 @@ void lb_setup_type_info_data(lbProcedure *p) { // NOTE(bill): Setup type_info da
lbValue res = {};
res.type = type_deref(tag.type);
res.value = llvm_const_named_struct(lb_type(m, res.type), vals, gb_count_of(vals));
res.value = llvm_const_named_struct(m, res.type, vals, gb_count_of(vals));
lb_emit_store(p, tag, res);
}
break;
@@ -856,4 +879,10 @@ void lb_setup_type_info_data(lbProcedure *p) { // NOTE(bill): Setup type_info da
}
}
}
for_array(i, entries_handled) {
if (!entries_handled[i]) {
GB_PANIC("UNHANDLED ENTRY %td (%td)", i, entries_handled.count);
}
}
}
+56 -9
View File
@@ -807,6 +807,47 @@ lbValue lb_address_from_load(lbProcedure *p, lbValue value) {
return {};
}
bool lb_struct_has_padding_prefix(Type *t) {
Type *bt = base_type(t);
GB_ASSERT(bt->kind == Type_Struct);
return bt->Struct.custom_align != 0 && bt->Struct.fields.count == 0;
}
i32 lb_convert_struct_index(lbModule *m, Type *t, i32 index) {
if (t->kind == Type_Struct) {
index = index*2 + 1;
if (lb_struct_has_padding_prefix(t)) {
index += 1;
}
unsigned count = LLVMCountStructElementTypes(lb_type(m, t));
GB_ASSERT(count >= cast(unsigned)index);
}
return index;
}
char const *llvm_type_kinds[] = {
"LLVMVoidTypeKind",
"LLVMHalfTypeKind",
"LLVMFloatTypeKind",
"LLVMDoubleTypeKind",
"LLVMX86_FP80TypeKind",
"LLVMFP128TypeKind",
"LLVMPPC_FP128TypeKind",
"LLVMLabelTypeKind",
"LLVMIntegerTypeKind",
"LLVMFunctionTypeKind",
"LLVMStructTypeKind",
"LLVMArrayTypeKind",
"LLVMPointerTypeKind",
"LLVMVectorTypeKind",
"LLVMMetadataTypeKind",
"LLVMX86_MMXTypeKind",
"LLVMTokenTypeKind",
"LLVMScalableVectorTypeKind",
"LLVMBFloatTypeKind",
};
lbValue lb_emit_struct_ep(lbProcedure *p, lbValue s, i32 index) {
GB_ASSERT(is_type_pointer(s.type));
Type *t = base_type(type_deref(s.type));
@@ -871,6 +912,7 @@ lbValue lb_emit_struct_ep(lbProcedure *p, lbValue s, i32 index) {
case 0: result_type = get_struct_field_type(gst, 0); break;
case 1: result_type = get_struct_field_type(gst, 1); break;
}
index = index*2 + 1;
} else if (is_type_array(t)) {
return lb_emit_array_epi(p, s, index);
} else if (is_type_relative_slice(t)) {
@@ -883,10 +925,9 @@ lbValue lb_emit_struct_ep(lbProcedure *p, lbValue s, i32 index) {
}
GB_ASSERT_MSG(result_type != nullptr, "%s %d", type_to_string(t), index);
if (t->kind == Type_Struct && t->Struct.custom_align != 0) {
index += 1;
}
index = lb_convert_struct_index(p->module, t, index);
if (lb_is_const(s)) {
lbModule *m = p->module;
lbValue res = {};
@@ -896,6 +937,14 @@ lbValue lb_emit_struct_ep(lbProcedure *p, lbValue s, i32 index) {
return res;
} else {
lbValue res = {};
LLVMTypeRef st = LLVMGetElementType(LLVMTypeOf(s.value));
// gb_printf_err("%s\n", type_to_string(s.type));
// gb_printf_err("%s\n", LLVMPrintTypeToString(LLVMTypeOf(s.value)));
// gb_printf_err("%d\n", index);
GB_ASSERT_MSG(LLVMGetTypeKind(st) == LLVMStructTypeKind, "%s", llvm_type_kinds[LLVMGetTypeKind(st)]);
unsigned count = LLVMCountStructElementTypes(st);
GB_ASSERT(count >= cast(unsigned)index);
res.value = LLVMBuildStructGEP(p->builder, s.value, cast(unsigned)index, "");
res.type = alloc_type_pointer(result_type);
return res;
@@ -1006,10 +1055,8 @@ lbValue lb_emit_struct_ev(lbProcedure *p, lbValue s, i32 index) {
}
GB_ASSERT_MSG(result_type != nullptr, "%s, %d", type_to_string(s.type), index);
if (t->kind == Type_Struct && t->Struct.custom_align != 0) {
index += 1;
}
index = lb_convert_struct_index(p->module, t, index);
lbValue res = {};
res.value = LLVMBuildExtractValue(p->builder, s.value, cast(unsigned)index, "");
@@ -1228,7 +1275,7 @@ lbValue lb_map_entries_ptr(lbProcedure *p, lbValue value) {
GB_ASSERT_MSG(t->kind == Type_Map, "%s", type_to_string(t));
init_map_internal_types(t);
i32 index = 1;
lbValue entries = lb_emit_struct_ep(p, value, index);
lbValue entries = lb_emit_struct_ep(p, value, index);
return entries;
}
-2
View File
@@ -2220,7 +2220,6 @@ int strip_semicolons(Parser *parser) {
int main(int arg_count, char const **arg_ptr) {
#define TIME_SECTION(str) do { debugf("[Section] %s\n", str); timings_start_section(&global_timings, str_lit(str)); } while (0)
if (arg_count < 2) {
usage(make_string_c(arg_ptr[0]));
return 1;
@@ -2490,7 +2489,6 @@ int main(int arg_count, char const **arg_ptr) {
}
remove_temp_files(gen);
arena_free_all(&temporary_arena);
if (run_output) {
#if defined(GB_SYSTEM_WINDOWS)
+6 -10
View File
@@ -1196,7 +1196,7 @@ CommentGroup *consume_comment_group(AstFile *f, isize n, isize *end_line_) {
CommentGroup *comments = nullptr;
if (list.count > 0) {
comments = gb_alloc_item(heap_allocator(), CommentGroup);
comments = gb_alloc_item(permanent_allocator(), CommentGroup);
comments->list = slice_from_array(list);
array_add(&f->comments, comments);
}
@@ -4645,7 +4645,8 @@ ParseFileError init_ast_file(AstFile *f, String fullpath, TokenPos *err_pos) {
zero_item(&f->tokenizer);
f->tokenizer.curr_file_id = f->id;
TokenizerInitError err = init_tokenizer_from_fullpath(&f->tokenizer, f->fullpath);
bool copy_file_contents = build_context.command_kind == Command_strip_semicolon;
TokenizerInitError err = init_tokenizer_from_fullpath(&f->tokenizer, f->fullpath, copy_file_contents);
if (err != TokenizerInit_None) {
switch (err) {
case TokenizerInit_Empty:
@@ -4710,9 +4711,6 @@ ParseFileError init_ast_file(AstFile *f, String fullpath, TokenPos *err_pos) {
block_size = ((block_size + page_size-1)/page_size) * page_size;
block_size = gb_clamp(block_size, page_size, DEFAULT_MINIMUM_BLOCK_SIZE);
f->arena.minimum_block_size = block_size;
#if 0
arena_init_local_mutex(&f->arena);
#endif
array_init(&f->comments, heap_allocator(), 0, 0);
array_init(&f->imports, heap_allocator(), 0, 0);
@@ -4727,8 +4725,6 @@ void destroy_ast_file(AstFile *f) {
array_free(&f->tokens);
array_free(&f->comments);
array_free(&f->imports);
gb_free(heap_allocator(), f->tokenizer.fullpath.text);
destroy_tokenizer(&f->tokenizer);
}
bool init_parser(Parser *p) {
@@ -4795,7 +4791,7 @@ WORKER_TASK_PROC(parser_worker_proc) {
void parser_add_file_to_process(Parser *p, AstPackage *pkg, FileInfo fi, TokenPos pos) {
// TODO(bill): Use a better allocator
ImportedFile f = {pkg, fi, pos, p->file_to_process_count++};
auto wd = gb_alloc_item(heap_allocator(), ParserWorkerData);
auto wd = gb_alloc_item(permanent_allocator(), ParserWorkerData);
wd->parser = p;
wd->imported_file = f;
global_thread_pool_add_task(parser_worker_proc, wd);
@@ -4833,7 +4829,7 @@ WORKER_TASK_PROC(foreign_file_worker_proc) {
void parser_add_foreign_file_to_process(Parser *p, AstPackage *pkg, AstForeignFileKind kind, FileInfo fi, TokenPos pos) {
// TODO(bill): Use a better allocator
ImportedFile f = {pkg, fi, pos, p->file_to_process_count++};
auto wd = gb_alloc_item(heap_allocator(), ForeignFileWorkerData);
auto wd = gb_alloc_item(permanent_allocator(), ForeignFileWorkerData);
wd->parser = p;
wd->imported_file = f;
wd->foreign_kind = kind;
@@ -4854,7 +4850,7 @@ AstPackage *try_add_import_path(Parser *p, String const &path, String const &rel
string_set_add(&p->imported_files, path);
AstPackage *pkg = gb_alloc_item(heap_allocator(), AstPackage);
AstPackage *pkg = gb_alloc_item(permanent_allocator(), AstPackage);
pkg->kind = kind;
pkg->fullpath = path;
array_init(&pkg->files, heap_allocator());
+28 -38
View File
@@ -371,7 +371,7 @@ void begin_error_block(void) {
void end_error_block(void) {
if (global_error_collector.error_buffer.count > 0) {
isize n = global_error_collector.error_buffer.count;
u8 *text = gb_alloc_array(heap_allocator(), u8, n+1);
u8 *text = gb_alloc_array(permanent_allocator(), u8, n+1);
gb_memmove(text, global_error_collector.error_buffer.data, n);
text[n] = 0;
String s = {text, n};
@@ -404,7 +404,7 @@ ERROR_OUT_PROC(default_error_out_va) {
} else {
mutex_lock(&global_error_collector.error_out_mutex);
{
u8 *text = gb_alloc_array(heap_allocator(), u8, n+1);
u8 *text = gb_alloc_array(permanent_allocator(), u8, n+1);
gb_memmove(text, buf, n);
text[n] = 0;
array_add(&global_error_collector.errors, make_string(text, n));
@@ -722,6 +722,8 @@ struct Tokenizer {
i32 error_count;
bool insert_semicolon;
MemoryMappedFile memory_mapped_file;
};
@@ -802,48 +804,36 @@ void init_tokenizer_with_data(Tokenizer *t, String const &fullpath, void *data,
}
}
TokenizerInitError init_tokenizer_from_fullpath(Tokenizer *t, String const &fullpath) {
TokenizerInitError err = TokenizerInit_None;
TokenizerInitError memory_mapped_file_error_map_to_tokenizer[MemoryMappedFile_COUNT] = {
TokenizerInit_None, /*MemoryMappedFile_None*/
TokenizerInit_Empty, /*MemoryMappedFile_Empty*/
TokenizerInit_FileTooLarge, /*MemoryMappedFile_FileTooLarge*/
TokenizerInit_Invalid, /*MemoryMappedFile_Invalid*/
TokenizerInit_NotExists, /*MemoryMappedFile_NotExists*/
TokenizerInit_Permission, /*MemoryMappedFile_Permission*/
};
char *c_str = alloc_cstring(temporary_allocator(), fullpath);
// TODO(bill): Memory map rather than copy contents
gbFileContents fc = gb_file_read_contents(heap_allocator(), true, c_str);
if (fc.size > I32_MAX) {
TokenizerInitError init_tokenizer_from_fullpath(Tokenizer *t, String const &fullpath, bool copy_file_contents) {
MemoryMappedFileError mmf_err = memory_map_file_32(
alloc_cstring(temporary_allocator(), fullpath),
&t->memory_mapped_file,
copy_file_contents
);
TokenizerInitError err = memory_mapped_file_error_map_to_tokenizer[mmf_err];
switch (mmf_err) {
case MemoryMappedFile_None:
init_tokenizer_with_data(t, fullpath, t->memory_mapped_file.data, cast(isize)t->memory_mapped_file.size);
break;
case MemoryMappedFile_FileTooLarge:
case MemoryMappedFile_Empty:
t->fullpath = fullpath;
t->line_count = 1;
err = TokenizerInit_FileTooLarge;
gb_file_free_contents(&fc);
} else if (fc.data != nullptr) {
init_tokenizer_with_data(t, fullpath, fc.data, fc.size);
} else {
t->fullpath = fullpath;
t->line_count = 1;
gbFile f = {};
gbFileError file_err = gb_file_open(&f, c_str);
defer (gb_file_close(&f));
switch (file_err) {
case gbFileError_Invalid: err = TokenizerInit_Invalid; break;
case gbFileError_NotExists: err = TokenizerInit_NotExists; break;
case gbFileError_Permission: err = TokenizerInit_Permission; break;
}
if (err == TokenizerInit_None && gb_file_size(&f) == 0) {
err = TokenizerInit_Empty;
}
}
break;
}
return err;
}
gb_inline void destroy_tokenizer(Tokenizer *t) {
if (t->start != nullptr) {
gb_free(heap_allocator(), t->start);
}
}
gb_inline i32 digit_value(Rune r) {
switch (r) {
case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9':
+49 -76
View File
@@ -121,7 +121,7 @@ struct BasicType {
String name;
};
enum StructSoaKind {
enum StructSoaKind : u8 {
StructSoa_None = 0,
StructSoa_Fixed = 1,
StructSoa_Slice = 2,
@@ -129,44 +129,45 @@ enum StructSoaKind {
};
struct TypeStruct {
Array<Entity *> fields;
Array<String> tags;
Array<i64> offsets;
Slice<Entity *> fields;
String * tags; // count == fields.count
i64 * offsets; // count == fields.count
Ast * node;
Scope * scope;
Type * polymorphic_params; // Type_Tuple
Type * polymorphic_parent;
i64 custom_align;
Type * polymorphic_params; // Type_Tuple
Type * polymorphic_parent;
i64 custom_align;
Entity * names;
Type * soa_elem;
i32 soa_count;
StructSoaKind soa_kind;
Type * soa_elem;
i64 soa_count;
StructSoaKind soa_kind;
bool are_offsets_set;
bool are_offsets_being_processed;
bool is_packed;
bool is_raw_union;
bool is_polymorphic;
bool is_poly_specialized;
bool is_polymorphic;
bool are_offsets_set : 1;
bool are_offsets_being_processed : 1;
bool is_packed : 1;
bool is_raw_union : 1;
bool is_poly_specialized : 1;
};
struct TypeUnion {
Array<Type *> variants;
Slice<Type *> variants;
Ast * node;
Scope * scope;
i64 variant_block_size;
i64 custom_align;
i64 tag_size;
Type * polymorphic_params; // Type_Tuple
Type * polymorphic_parent;
bool no_nil;
bool maybe;
i16 tag_size;
bool is_polymorphic;
bool is_poly_specialized;
bool is_poly_specialized : 1;
bool no_nil : 1;
bool maybe : 1;
};
struct TypeProc {
@@ -216,8 +217,8 @@ struct TypeProc {
TYPE_KIND(EnumeratedArray, struct { \
Type *elem; \
Type *index; \
ExactValue min_value; \
ExactValue max_value; \
ExactValue *min_value; \
ExactValue *max_value; \
i64 count; \
TokenKind op; \
}) \
@@ -237,16 +238,15 @@ struct TypeProc {
Array<Entity *> fields; \
Ast *node; \
Scope * scope; \
Entity * names; \
Type * base_type; \
ExactValue min_value; \
ExactValue max_value; \
ExactValue *min_value; \
ExactValue *max_value; \
isize min_value_index; \
isize max_value_index; \
}) \
TYPE_KIND(Tuple, struct { \
Array<Entity *> variables; /* Entity_Variable */ \
Array<i64> offsets; \
Slice<Entity *> variables; /* Entity_Variable */ \
i64 * offsets; \
bool are_offsets_being_processed; \
bool are_offsets_set; \
bool is_packed; \
@@ -803,15 +803,17 @@ Type *alloc_type_array(Type *elem, i64 count, Type *generic_count = nullptr) {
return t;
}
Type *alloc_type_enumerated_array(Type *elem, Type *index, ExactValue min_value, ExactValue max_value, TokenKind op) {
Type *alloc_type_enumerated_array(Type *elem, Type *index, ExactValue const *min_value, ExactValue const *max_value, TokenKind op) {
Type *t = alloc_type(Type_EnumeratedArray);
t->EnumeratedArray.elem = elem;
t->EnumeratedArray.index = index;
t->EnumeratedArray.min_value = min_value;
t->EnumeratedArray.max_value = max_value;
t->EnumeratedArray.min_value = gb_alloc_item(permanent_allocator(), ExactValue);
t->EnumeratedArray.max_value = gb_alloc_item(permanent_allocator(), ExactValue);
gb_memmove(t->EnumeratedArray.min_value, min_value, gb_size_of(ExactValue));
gb_memmove(t->EnumeratedArray.max_value, max_value, gb_size_of(ExactValue));
t->EnumeratedArray.op = op;
t->EnumeratedArray.count = 1 + exact_value_to_i64(exact_value_sub(max_value, min_value));
t->EnumeratedArray.count = 1 + exact_value_to_i64(exact_value_sub(*max_value, *min_value));
return t;
}
@@ -841,6 +843,8 @@ Type *alloc_type_union() {
Type *alloc_type_enum() {
Type *t = alloc_type(Type_Enum);
t->Enum.min_value = gb_alloc_item(permanent_allocator(), ExactValue);
t->Enum.max_value = gb_alloc_item(permanent_allocator(), ExactValue);
return t;
}
@@ -2169,12 +2173,6 @@ bool are_types_identical(Type *x, Type *y) {
if (xf_is_using ^ yf_is_using) {
return false;
}
if (x->Struct.tags.count != y->Struct.tags.count) {
return false;
}
if (x->Struct.tags.count > 0 && x->Struct.tags[i] != y->Struct.tags[i]) {
return false;
}
}
return true;
}
@@ -2307,7 +2305,7 @@ i64 union_tag_size(Type *u) {
}
}
u->Union.tag_size = gb_min3(max_align, build_context.max_align, 8);
u->Union.tag_size = cast(i16)gb_min3(max_align, build_context.max_align, 8);
return u->Union.tag_size;
}
@@ -2434,7 +2432,7 @@ Selection lookup_field_from_index(Type *type, i64 index) {
for (isize i = 0; i < max_count; i++) {
Entity *f = type->Struct.fields[i];
if (f->kind == Entity_Variable) {
if (f->Variable.field_src_index == index) {
if (f->Variable.field_index == index) {
auto sel_array = array_make<i32>(a, 1);
sel_array[0] = cast(i32)i;
return make_selection(f, sel_array, false);
@@ -2474,24 +2472,6 @@ Selection lookup_field_with_selection(Type *type_, String field_name, bool is_ty
type = base_type(type);
if (is_type) {
switch (type->kind) {
case Type_Struct:
if (type->Struct.names != nullptr &&
field_name == "names") {
sel.entity = type->Struct.names;
return sel;
}
break;
case Type_Enum:
if (type->Enum.names != nullptr &&
field_name == "names") {
sel.entity = type->Enum.names;
return sel;
}
break;
}
if (is_type_enum(type)) {
// NOTE(bill): These may not have been added yet, so check in case
for_array(i, type->Enum.fields) {
@@ -2992,7 +2972,7 @@ i64 type_align_of_internal(Type *t, TypePath *path) {
return 1;
}
if (t->Union.custom_align > 0) {
return gb_clamp(t->Union.custom_align, 1, build_context.max_align);
return gb_max(t->Union.custom_align, 1);
}
i64 max = 1;
@@ -3013,7 +2993,7 @@ i64 type_align_of_internal(Type *t, TypePath *path) {
case Type_Struct: {
if (t->Struct.custom_align > 0) {
return gb_clamp(t->Struct.custom_align, 1, build_context.max_align);
return gb_max(t->Struct.custom_align, 1);
}
if (t->Struct.is_raw_union) {
i64 max = 1;
@@ -3080,9 +3060,9 @@ i64 type_align_of_internal(Type *t, TypePath *path) {
return gb_clamp(next_pow2(type_size_of_internal(t, path)), 1, build_context.word_size);
}
Array<i64> type_set_offsets_of(Array<Entity *> const &fields, bool is_packed, bool is_raw_union) {
i64 *type_set_offsets_of(Slice<Entity *> const &fields, bool is_packed, bool is_raw_union) {
gbAllocator a = permanent_allocator();
auto offsets = array_make<i64>(a, fields.count);
auto offsets = gb_alloc_array(a, i64, fields.count);
i64 curr_offset = 0;
if (is_raw_union) {
for_array(i, fields) {
@@ -3116,7 +3096,6 @@ bool type_set_offsets(Type *t) {
if (!t->Struct.are_offsets_set) {
t->Struct.are_offsets_being_processed = true;
t->Struct.offsets = type_set_offsets_of(t->Struct.fields, t->Struct.is_packed, t->Struct.is_raw_union);
GB_ASSERT(t->Struct.offsets.count == t->Struct.fields.count);
t->Struct.are_offsets_being_processed = false;
t->Struct.are_offsets_set = true;
return true;
@@ -3265,7 +3244,7 @@ i64 type_size_of_internal(Type *t, TypePath *path) {
i64 tag_size = union_tag_size(t);
size = align_formula(max, tag_size);
// NOTE(bill): Calculate the padding between the common fields and the tag
t->Union.tag_size = tag_size;
t->Union.tag_size = cast(i16)tag_size;
t->Union.variant_block_size = size - field_size;
size += tag_size;
@@ -3301,18 +3280,12 @@ i64 type_size_of_internal(Type *t, TypePath *path) {
if (path->failure) {
return FAILURE_SIZE;
}
if (t->Struct.are_offsets_being_processed && t->Struct.offsets.data == nullptr) {
if (t->Struct.are_offsets_being_processed && t->Struct.offsets == nullptr) {
type_path_print_illegal_cycle(path, path->path.count-1);
return FAILURE_SIZE;
}
if (t->Struct.are_offsets_set && t->Struct.offsets.count != t->Struct.fields.count) {
// TODO(bill, 2019-04-28): Determine exactly why the offsets length is different thatn the field length
// Are the the same at some point and then the struct length is increased?
// Why is this not handled by the type cycle checker?
t->Struct.are_offsets_set = false;
}
type_set_offsets(t);
GB_ASSERT_MSG(t->Struct.offsets.count == t->Struct.fields.count, "%s", type_to_string(t));
GB_ASSERT(t->Struct.fields.count == 0 || t->Struct.offsets != nullptr);
size = t->Struct.offsets[cast(isize)count-1] + type_size_of_internal(t->Struct.fields[cast(isize)count-1]->type, path);
return align_formula(size, align);
}
@@ -3463,7 +3436,7 @@ Type *reduce_tuple_to_single_type(Type *original_type) {
Type *alloc_type_struct_from_field_types(Type **field_types, isize field_count, bool is_packed) {
Type *t = alloc_type_struct();
t->Struct.fields = array_make<Entity *>(heap_allocator(), field_count);
t->Struct.fields = slice_make<Entity *>(heap_allocator(), field_count);
Scope *scope = nullptr;
for_array(i, t->Struct.fields) {
@@ -3483,7 +3456,7 @@ Type *alloc_type_tuple_from_field_types(Type **field_types, isize field_count, b
}
Type *t = alloc_type_tuple();
t->Tuple.variables = array_make<Entity *>(heap_allocator(), field_count);
t->Tuple.variables = slice_make<Entity *>(heap_allocator(), field_count);
Scope *scope = nullptr;
for_array(i, t->Tuple.variables) {