mirror of
https://github.com/Ed94/Odin.git
synced 2026-07-28 18:30:06 +00:00
Merge branch 'master' into llvm-12.0.1-windows
This commit is contained in:
@@ -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
@@ -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
@@ -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(¶ms->Tuple.variables, heap_allocator(), param_types.count);
|
||||
slice_init(¶ms->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
@@ -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 ¶ms,
|
||||
void check_struct_fields(CheckerContext *ctx, Ast *node, Slice<Entity *> *fields, String **tags, Slice<Ast *> const ¶ms,
|
||||
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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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 ®_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++) {
|
||||
|
||||
@@ -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(¶ms->Tuple.variables, permanent_allocator(), 3);
|
||||
slice_init(¶ms->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(¶ms->Tuple.variables, permanent_allocator(), 2);
|
||||
slice_init(¶ms->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;
|
||||
|
||||
@@ -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
@@ -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;
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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) {
|
||||
|
||||
Reference in New Issue
Block a user