aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorgingerBill <gingerBill@users.noreply.github.com>2021-09-13 18:23:58 +0100
committerGitHub <noreply@github.com>2021-09-13 18:23:58 +0100
commit4e4ac460e53272140fa5af3a2e005d9091ba8654 (patch)
tree15d6dd8f98f9b47b4efd0d9b906299054d6424de /src
parente9b9d15de7bc08bdf2891586589e215832c9a3cc (diff)
parent526a42c6caac9bc39b9217e58c297d084c3d694a (diff)
Merge pull request #1164 from odin-lang/llvm-explicit-padding
LLVM Struct Types with Explicit Padding
Diffstat (limited to 'src')
-rw-r--r--src/check_builtin.cpp2
-rw-r--r--src/check_type.cpp10
-rw-r--r--src/entity.cpp13
-rw-r--r--src/llvm_backend.cpp4
-rw-r--r--src/llvm_backend.hpp3
-rw-r--r--src/llvm_backend_const.cpp84
-rw-r--r--src/llvm_backend_expr.cpp11
-rw-r--r--src/llvm_backend_general.cpp70
-rw-r--r--src/llvm_backend_stmt.cpp3
-rw-r--r--src/llvm_backend_type.cpp95
-rw-r--r--src/llvm_backend_utility.cpp65
-rw-r--r--src/types.cpp6
12 files changed, 254 insertions, 112 deletions
diff --git a/src/check_builtin.cpp b/src/check_builtin.cpp
index 96feb6701..399de98a0 100644
--- a/src/check_builtin.cpp
+++ b/src/check_builtin.cpp
@@ -1989,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 {
diff --git a/src/check_type.cpp b/src/check_type.cpp
index b80d6c05e..00a4c4ab2 100644
--- a/src/check_type.cpp
+++ b/src/check_type.cpp
@@ -215,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;
}
}
@@ -2317,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);
diff --git a/src/entity.cpp b/src/entity.cpp
index 8343ba557..11954113d 100644
--- a/src/entity.cpp
+++ b/src/entity.cpp
@@ -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;
diff --git a/src/llvm_backend.cpp b/src/llvm_backend.cpp
index 8ba0a3b87..67160101d 100644
--- a/src/llvm_backend.cpp
+++ b/src/llvm_backend.cpp
@@ -806,8 +806,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);
@@ -834,7 +832,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);
}
diff --git a/src/llvm_backend.hpp b/src/llvm_backend.hpp
index 19e5ffdb6..d0ba29964 100644
--- a/src/llvm_backend.hpp
+++ b/src/llvm_backend.hpp
@@ -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"
diff --git a/src/llvm_backend_const.cpp b/src/llvm_backend_const.cpp
index d46992976..cb9369c72 100644
--- a/src/llvm_backend_const.cpp
+++ b/src/llvm_backend_const.cpp
@@ -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;
@@ -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;
diff --git a/src/llvm_backend_expr.cpp b/src/llvm_backend_expr.cpp
index efd0eaf40..b2ef6d0d0 100644
--- a/src/llvm_backend_expr.cpp
+++ b/src/llvm_backend_expr.cpp
@@ -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);
}
@@ -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];
}
diff --git a/src/llvm_backend_general.cpp b/src/llvm_backend_general.cpp
index 85fd9153d..b6959c425 100644
--- a/src/llvm_backend_general.cpp
+++ b/src/llvm_backend_general.cpp
@@ -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);
@@ -1676,25 +1678,63 @@ LLVMTypeRef lb_type_internal(lbModule *m, Type *type) {
}
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);
}
@@ -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;
}
diff --git a/src/llvm_backend_stmt.cpp b/src/llvm_backend_stmt.cpp
index ac922b642..82ad199bb 100644
--- a/src/llvm_backend_stmt.cpp
+++ b/src/llvm_backend_stmt.cpp
@@ -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));
diff --git a/src/llvm_backend_type.cpp b/src/llvm_backend_type.cpp
index f17b8df6a..1defadca3 100644
--- a/src/llvm_backend_type.cpp
+++ b/src/llvm_backend_type.cpp
@@ -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,7 +467,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);
// NOTE(bill): Union assignment
@@ -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);
@@ -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);
+ }
+ }
}
diff --git a/src/llvm_backend_utility.cpp b/src/llvm_backend_utility.cpp
index db3cb443e..d1613a354 100644
--- a/src/llvm_backend_utility.cpp
+++ b/src/llvm_backend_utility.cpp
@@ -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;
}
diff --git a/src/types.cpp b/src/types.cpp
index 23834bfc1..7a5ea489b 100644
--- a/src/types.cpp
+++ b/src/types.cpp
@@ -2432,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);
@@ -2972,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;
@@ -2993,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;