types sized and aligned with LLVM target data layout API
parent
b04e64d300
commit
b28f7d0808
|
@ -807,6 +807,11 @@ struct TypeTableEntryPointer {
|
|||
|
||||
struct TypeTableEntryInt {
|
||||
bool is_signed;
|
||||
int bit_count;
|
||||
};
|
||||
|
||||
struct TypeTableEntryFloat {
|
||||
int bit_count;
|
||||
};
|
||||
|
||||
struct TypeTableEntryArray {
|
||||
|
@ -910,17 +915,17 @@ enum TypeTableEntryId {
|
|||
|
||||
struct TypeTableEntry {
|
||||
TypeTableEntryId id;
|
||||
Buf name;
|
||||
|
||||
LLVMTypeRef type_ref;
|
||||
LLVMZigDIType *di_type;
|
||||
uint64_t size_in_bits;
|
||||
uint64_t align_in_bits;
|
||||
|
||||
Buf name;
|
||||
bool zero_bits;
|
||||
|
||||
union {
|
||||
TypeTableEntryPointer pointer;
|
||||
TypeTableEntryInt integral;
|
||||
TypeTableEntryFloat floating;
|
||||
TypeTableEntryArray array;
|
||||
TypeTableEntryStruct structure;
|
||||
TypeTableEntryMaybe maybe;
|
||||
|
@ -988,6 +993,7 @@ enum BuiltinFnId {
|
|||
BuiltinFnIdMemcpy,
|
||||
BuiltinFnIdMemset,
|
||||
BuiltinFnIdSizeof,
|
||||
BuiltinFnIdAlignof,
|
||||
BuiltinFnIdMaxValue,
|
||||
BuiltinFnIdMinValue,
|
||||
BuiltinFnIdMemberCount,
|
||||
|
|
434
src/analyze.cpp
434
src/analyze.cpp
|
@ -200,27 +200,21 @@ TypeTableEntry *get_pointer_to_type(CodeGen *g, TypeTableEntry *child_type, bool
|
|||
TypeTableEntry *canon_child_type = get_underlying_type(child_type);
|
||||
assert(canon_child_type->id != TypeTableEntryIdInvalid);
|
||||
|
||||
bool zero_bits;
|
||||
if (canon_child_type->size_in_bits == 0) {
|
||||
if (canon_child_type->id == TypeTableEntryIdStruct) {
|
||||
zero_bits = canon_child_type->data.structure.complete;
|
||||
} else if (canon_child_type->id == TypeTableEntryIdEnum) {
|
||||
zero_bits = canon_child_type->data.enumeration.complete;
|
||||
|
||||
if (type_is_complete(canon_child_type)) {
|
||||
entry->zero_bits = !type_has_bits(canon_child_type);
|
||||
} else {
|
||||
zero_bits = true;
|
||||
}
|
||||
} else {
|
||||
zero_bits = false;
|
||||
entry->zero_bits = false;
|
||||
}
|
||||
|
||||
if (!zero_bits) {
|
||||
if (!entry->zero_bits) {
|
||||
entry->type_ref = LLVMPointerType(child_type->type_ref, 0);
|
||||
|
||||
entry->size_in_bits = g->pointer_size_bytes * 8;
|
||||
entry->align_in_bits = g->pointer_size_bytes * 8;
|
||||
uint64_t debug_size_in_bits = LLVMSizeOfTypeInBits(g->target_data_ref, entry->type_ref);
|
||||
uint64_t debug_align_in_bits = 8*LLVMABISizeOfType(g->target_data_ref, entry->type_ref);
|
||||
assert(child_type->di_type);
|
||||
entry->di_type = LLVMZigCreateDebugPointerType(g->dbuilder, child_type->di_type,
|
||||
entry->size_in_bits, entry->align_in_bits, buf_ptr(&entry->name));
|
||||
debug_size_in_bits, debug_align_in_bits, buf_ptr(&entry->name));
|
||||
}
|
||||
|
||||
entry->data.pointer.child_type = child_type;
|
||||
|
@ -249,8 +243,6 @@ TypeTableEntry *get_maybe_type(CodeGen *g, TypeTableEntry *child_type) {
|
|||
// this is an optimization but also is necessary for calling C
|
||||
// functions where all pointers are maybe pointers
|
||||
// function types are technically pointers
|
||||
entry->size_in_bits = child_type->size_in_bits;
|
||||
entry->align_in_bits = child_type->align_in_bits;
|
||||
entry->type_ref = child_type->type_ref;
|
||||
entry->di_type = child_type->di_type;
|
||||
} else {
|
||||
|
@ -260,8 +252,6 @@ TypeTableEntry *get_maybe_type(CodeGen *g, TypeTableEntry *child_type) {
|
|||
LLVMInt1Type(),
|
||||
};
|
||||
entry->type_ref = LLVMStructType(elem_types, 2, false);
|
||||
entry->size_in_bits = child_type->size_in_bits + 8;
|
||||
entry->align_in_bits = child_type->align_in_bits;
|
||||
|
||||
|
||||
LLVMZigDIScope *compile_unit_scope = LLVMZigCompileUnitToScope(g->compile_unit);
|
||||
|
@ -271,18 +261,36 @@ TypeTableEntry *get_maybe_type(CodeGen *g, TypeTableEntry *child_type) {
|
|||
LLVMZigTag_DW_structure_type(), buf_ptr(&entry->name),
|
||||
compile_unit_scope, di_file, line);
|
||||
|
||||
uint64_t val_debug_size_in_bits = LLVMSizeOfTypeInBits(g->target_data_ref, child_type->type_ref);
|
||||
uint64_t val_debug_align_in_bits = 8*LLVMABISizeOfType(g->target_data_ref, child_type->type_ref);
|
||||
uint64_t val_offset_in_bits = 8*LLVMOffsetOfElement(g->target_data_ref, entry->type_ref, 0);
|
||||
|
||||
TypeTableEntry *bool_type = g->builtin_types.entry_bool;
|
||||
uint64_t maybe_debug_size_in_bits = LLVMSizeOfTypeInBits(g->target_data_ref, bool_type->type_ref);
|
||||
uint64_t maybe_debug_align_in_bits = 8*LLVMABISizeOfType(g->target_data_ref, bool_type->type_ref);
|
||||
uint64_t maybe_offset_in_bits = 8*LLVMOffsetOfElement(g->target_data_ref, entry->type_ref, 1);
|
||||
|
||||
uint64_t debug_size_in_bits = LLVMSizeOfTypeInBits(g->target_data_ref, entry->type_ref);
|
||||
uint64_t debug_align_in_bits = 8*LLVMABISizeOfType(g->target_data_ref, entry->type_ref);
|
||||
|
||||
LLVMZigDIType *di_element_types[] = {
|
||||
LLVMZigCreateDebugMemberType(g->dbuilder, LLVMZigTypeToScope(entry->di_type),
|
||||
"val", di_file, line, child_type->size_in_bits, child_type->align_in_bits, 0, 0,
|
||||
child_type->di_type),
|
||||
"val", di_file, line,
|
||||
val_debug_size_in_bits,
|
||||
val_debug_align_in_bits,
|
||||
val_offset_in_bits,
|
||||
0, child_type->di_type),
|
||||
LLVMZigCreateDebugMemberType(g->dbuilder, LLVMZigTypeToScope(entry->di_type),
|
||||
"maybe", di_file, line, 8, 8, child_type->size_in_bits, 0,
|
||||
child_type->di_type),
|
||||
"maybe", di_file, line,
|
||||
maybe_debug_size_in_bits,
|
||||
maybe_debug_align_in_bits,
|
||||
maybe_offset_in_bits,
|
||||
0, child_type->di_type),
|
||||
};
|
||||
LLVMZigDIType *replacement_di_type = LLVMZigCreateDebugStructType(g->dbuilder,
|
||||
compile_unit_scope,
|
||||
buf_ptr(&entry->name),
|
||||
di_file, line, entry->size_in_bits, entry->align_in_bits, 0,
|
||||
di_file, line, debug_size_in_bits, debug_align_in_bits, 0,
|
||||
nullptr, di_element_types, 2, 0, nullptr, "");
|
||||
|
||||
LLVMZigReplaceTemporary(g->dbuilder, entry->di_type, replacement_di_type);
|
||||
|
@ -309,10 +317,8 @@ static TypeTableEntry *get_error_type(CodeGen *g, TypeTableEntry *child_type) {
|
|||
|
||||
entry->data.error.child_type = child_type;
|
||||
|
||||
if (child_type->size_in_bits == 0) {
|
||||
if (!type_has_bits(child_type)) {
|
||||
entry->type_ref = g->err_tag_type->type_ref;
|
||||
entry->size_in_bits = g->err_tag_type->size_in_bits;
|
||||
entry->align_in_bits = g->err_tag_type->align_in_bits;
|
||||
entry->di_type = g->err_tag_type->di_type;
|
||||
|
||||
} else {
|
||||
|
@ -321,8 +327,6 @@ static TypeTableEntry *get_error_type(CodeGen *g, TypeTableEntry *child_type) {
|
|||
child_type->type_ref,
|
||||
};
|
||||
entry->type_ref = LLVMStructType(elem_types, 2, false);
|
||||
entry->size_in_bits = g->err_tag_type->size_in_bits + child_type->size_in_bits;
|
||||
entry->align_in_bits = g->err_tag_type->align_in_bits;
|
||||
|
||||
LLVMZigDIScope *compile_unit_scope = LLVMZigCompileUnitToScope(g->compile_unit);
|
||||
LLVMZigDIFile *di_file = nullptr;
|
||||
|
@ -331,19 +335,39 @@ static TypeTableEntry *get_error_type(CodeGen *g, TypeTableEntry *child_type) {
|
|||
LLVMZigTag_DW_structure_type(), buf_ptr(&entry->name),
|
||||
compile_unit_scope, di_file, line);
|
||||
|
||||
uint64_t tag_debug_size_in_bits = LLVMSizeOfTypeInBits(g->target_data_ref, g->err_tag_type->type_ref);
|
||||
uint64_t tag_debug_align_in_bits = 8*LLVMABISizeOfType(g->target_data_ref, g->err_tag_type->type_ref);
|
||||
uint64_t tag_offset_in_bits = 8*LLVMOffsetOfElement(g->target_data_ref, entry->type_ref, 0);
|
||||
|
||||
uint64_t value_debug_size_in_bits = LLVMSizeOfTypeInBits(g->target_data_ref, child_type->type_ref);
|
||||
uint64_t value_debug_align_in_bits = 8*LLVMABISizeOfType(g->target_data_ref, child_type->type_ref);
|
||||
uint64_t value_offset_in_bits = 8*LLVMOffsetOfElement(g->target_data_ref, entry->type_ref, 1);
|
||||
|
||||
uint64_t debug_size_in_bits = LLVMSizeOfTypeInBits(g->target_data_ref, entry->type_ref);
|
||||
uint64_t debug_align_in_bits = 8*LLVMABISizeOfType(g->target_data_ref, entry->type_ref);
|
||||
|
||||
LLVMZigDIType *di_element_types[] = {
|
||||
LLVMZigCreateDebugMemberType(g->dbuilder, LLVMZigTypeToScope(entry->di_type),
|
||||
"tag", di_file, line, g->err_tag_type->size_in_bits, g->err_tag_type->align_in_bits,
|
||||
0, 0, child_type->di_type),
|
||||
"tag", di_file, line,
|
||||
tag_debug_size_in_bits,
|
||||
tag_debug_align_in_bits,
|
||||
tag_offset_in_bits,
|
||||
0, child_type->di_type),
|
||||
LLVMZigCreateDebugMemberType(g->dbuilder, LLVMZigTypeToScope(entry->di_type),
|
||||
"value", di_file, line, child_type->size_in_bits, child_type->align_in_bits,
|
||||
g->err_tag_type->size_in_bits, 0, child_type->di_type),
|
||||
"value", di_file, line,
|
||||
value_debug_size_in_bits,
|
||||
value_debug_align_in_bits,
|
||||
value_offset_in_bits,
|
||||
0, child_type->di_type),
|
||||
};
|
||||
|
||||
LLVMZigDIType *replacement_di_type = LLVMZigCreateDebugStructType(g->dbuilder,
|
||||
compile_unit_scope,
|
||||
buf_ptr(&entry->name),
|
||||
di_file, line, entry->size_in_bits, entry->align_in_bits, 0,
|
||||
di_file, line,
|
||||
debug_size_in_bits,
|
||||
debug_align_in_bits,
|
||||
0,
|
||||
nullptr, di_element_types, 2, 0, nullptr, "");
|
||||
|
||||
LLVMZigReplaceTemporary(g->dbuilder, entry->di_type, replacement_di_type);
|
||||
|
@ -363,14 +387,16 @@ TypeTableEntry *get_array_type(CodeGen *g, TypeTableEntry *child_type, uint64_t
|
|||
} else {
|
||||
TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdArray);
|
||||
entry->type_ref = LLVMArrayType(child_type->type_ref, array_size);
|
||||
entry->zero_bits = (array_size == 0) || child_type->zero_bits;
|
||||
|
||||
buf_resize(&entry->name, 0);
|
||||
buf_appendf(&entry->name, "[%" PRIu64 "]%s", array_size, buf_ptr(&child_type->name));
|
||||
|
||||
entry->size_in_bits = child_type->size_in_bits * array_size;
|
||||
entry->align_in_bits = child_type->align_in_bits;
|
||||
uint64_t debug_size_in_bits = LLVMSizeOfTypeInBits(g->target_data_ref, entry->type_ref);
|
||||
uint64_t debug_align_in_bits = 8*LLVMABISizeOfType(g->target_data_ref, entry->type_ref);
|
||||
|
||||
entry->di_type = LLVMZigCreateDebugArrayType(g->dbuilder, entry->size_in_bits,
|
||||
entry->align_in_bits, child_type->di_type, array_size);
|
||||
entry->di_type = LLVMZigCreateDebugArrayType(g->dbuilder, debug_size_in_bits,
|
||||
debug_align_in_bits, child_type->di_type, array_size);
|
||||
entry->data.array.child_type = child_type;
|
||||
entry->data.array.len = array_size;
|
||||
|
||||
|
@ -379,14 +405,12 @@ TypeTableEntry *get_array_type(CodeGen *g, TypeTableEntry *child_type, uint64_t
|
|||
}
|
||||
}
|
||||
|
||||
static void unknown_size_array_type_common_init(CodeGen *g, TypeTableEntry *child_type,
|
||||
static void slice_type_common_init(CodeGen *g, TypeTableEntry *child_type,
|
||||
bool is_const, TypeTableEntry *entry)
|
||||
{
|
||||
TypeTableEntry *pointer_type = get_pointer_to_type(g, child_type, is_const);
|
||||
|
||||
unsigned element_count = 2;
|
||||
entry->size_in_bits = g->pointer_size_bytes * 2 * 8;
|
||||
entry->align_in_bits = g->pointer_size_bytes * 8;
|
||||
entry->data.structure.is_packed = false;
|
||||
entry->data.structure.is_unknown_size_array = true;
|
||||
entry->data.structure.src_field_count = element_count;
|
||||
|
@ -402,20 +426,20 @@ static void unknown_size_array_type_common_init(CodeGen *g, TypeTableEntry *chil
|
|||
entry->data.structure.fields[1].gen_index = 1;
|
||||
}
|
||||
|
||||
static TypeTableEntry *get_unknown_size_array_type(CodeGen *g, TypeTableEntry *child_type, bool is_const) {
|
||||
static TypeTableEntry *get_slice_type(CodeGen *g, TypeTableEntry *child_type, bool is_const) {
|
||||
assert(child_type->id != TypeTableEntryIdInvalid);
|
||||
TypeTableEntry **parent_pointer = &child_type->unknown_size_array_parent[(is_const ? 1 : 0)];
|
||||
|
||||
if (*parent_pointer) {
|
||||
return *parent_pointer;
|
||||
} else if (is_const) {
|
||||
TypeTableEntry *var_peer = get_unknown_size_array_type(g, child_type, false);
|
||||
TypeTableEntry *var_peer = get_slice_type(g, child_type, false);
|
||||
TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdStruct);
|
||||
|
||||
buf_resize(&entry->name, 0);
|
||||
buf_appendf(&entry->name, "[]const %s", buf_ptr(&child_type->name));
|
||||
|
||||
unknown_size_array_type_common_init(g, child_type, is_const, entry);
|
||||
slice_type_common_init(g, child_type, is_const, entry);
|
||||
|
||||
entry->type_ref = var_peer->type_ref;
|
||||
entry->di_type = var_peer->di_type;
|
||||
|
@ -439,15 +463,17 @@ static TypeTableEntry *get_unknown_size_array_type(CodeGen *g, TypeTableEntry *c
|
|||
};
|
||||
LLVMStructSetBody(entry->type_ref, element_types, element_count, false);
|
||||
|
||||
unknown_size_array_type_common_init(g, child_type, is_const, entry);
|
||||
slice_type_common_init(g, child_type, is_const, entry);
|
||||
|
||||
LLVMZigDIType *di_element_types[] = {
|
||||
pointer_type->di_type,
|
||||
g->builtin_types.entry_isize->di_type,
|
||||
};
|
||||
LLVMZigDIScope *compile_unit_scope = LLVMZigCompileUnitToScope(g->compile_unit);
|
||||
uint64_t debug_size_in_bits = LLVMSizeOfTypeInBits(g->target_data_ref, entry->type_ref);
|
||||
uint64_t debug_align_in_bits = 8*LLVMABISizeOfType(g->target_data_ref, entry->type_ref);
|
||||
entry->di_type = LLVMZigCreateDebugStructType(g->dbuilder, compile_unit_scope,
|
||||
buf_ptr(&entry->name), g->dummy_di_file, 0, entry->size_in_bits, entry->align_in_bits, 0,
|
||||
buf_ptr(&entry->name), g->dummy_di_file, 0, debug_size_in_bits, debug_align_in_bits, 0,
|
||||
nullptr, di_element_types, element_count, 0, nullptr, "");
|
||||
|
||||
entry->data.structure.complete = true;
|
||||
|
@ -462,11 +488,9 @@ TypeTableEntry *get_typedecl_type(CodeGen *g, const char *name, TypeTableEntry *
|
|||
|
||||
buf_init_from_str(&entry->name, name);
|
||||
|
||||
entry->type_ref = child_type->type_ref;
|
||||
entry->type_ref = child_type->type_ref;
|
||||
entry->di_type = child_type->di_type;
|
||||
entry->size_in_bits = child_type->size_in_bits;
|
||||
entry->align_in_bits = child_type->align_in_bits;
|
||||
entry->zero_bits = child_type->zero_bits;
|
||||
|
||||
entry->data.type_decl.child_type = child_type;
|
||||
|
||||
|
@ -497,9 +521,6 @@ TypeTableEntry *get_fn_type(CodeGen *g, FnTypeId fn_type_id) {
|
|||
fn_type->data.fn.calling_convention = LLVMFastCallConv;
|
||||
}
|
||||
|
||||
fn_type->size_in_bits = g->pointer_size_bytes * 8;
|
||||
fn_type->align_in_bits = g->pointer_size_bytes * 8;
|
||||
|
||||
// populate the name of the type
|
||||
buf_resize(&fn_type->name, 0);
|
||||
const char *extern_str = fn_type_id.is_extern ? "extern " : "";
|
||||
|
@ -542,7 +563,7 @@ TypeTableEntry *get_fn_type(CodeGen *g, FnTypeId fn_type_id) {
|
|||
// after the gen_param_index += 1 because 0 is the return type
|
||||
param_di_types[gen_param_index] = gen_type->di_type;
|
||||
gen_return_type = g->builtin_types.entry_void;
|
||||
} else if (fn_type_id.return_type->size_in_bits == 0) {
|
||||
} else if (!type_has_bits(fn_type_id.return_type)) {
|
||||
gen_return_type = g->builtin_types.entry_void;
|
||||
} else {
|
||||
gen_return_type = fn_type_id.return_type;
|
||||
|
@ -559,7 +580,7 @@ TypeTableEntry *get_fn_type(CodeGen *g, FnTypeId fn_type_id) {
|
|||
gen_param_info->gen_index = -1;
|
||||
|
||||
assert(type_is_complete(type_entry));
|
||||
if (type_entry->size_in_bits > 0) {
|
||||
if (type_has_bits(type_entry)) {
|
||||
TypeTableEntry *gen_type;
|
||||
if (handle_is_ptr(type_entry)) {
|
||||
gen_type = get_pointer_to_type(g, type_entry, true);
|
||||
|
@ -897,37 +918,43 @@ static void resolve_enum_type(CodeGen *g, ImportTableEntry *import, TypeTableEnt
|
|||
AstNode *field_node = decl_node->data.struct_decl.fields.at(i);
|
||||
TypeEnumField *type_enum_field = &enum_type->data.enumeration.fields[i];
|
||||
type_enum_field->name = &field_node->data.struct_field.name;
|
||||
type_enum_field->type_entry = analyze_type_expr(g, import, import->block_context,
|
||||
TypeTableEntry *field_type = analyze_type_expr(g, import, import->block_context,
|
||||
field_node->data.struct_field.type);
|
||||
type_enum_field->type_entry = field_type;
|
||||
type_enum_field->value = i;
|
||||
|
||||
|
||||
di_enumerators[i] = LLVMZigCreateDebugEnumerator(g->dbuilder, buf_ptr(type_enum_field->name), i);
|
||||
|
||||
if (type_enum_field->type_entry->id == TypeTableEntryIdStruct) {
|
||||
resolve_struct_type(g, import, type_enum_field->type_entry);
|
||||
} else if (type_enum_field->type_entry->id == TypeTableEntryIdEnum) {
|
||||
resolve_enum_type(g, import, type_enum_field->type_entry);
|
||||
} else if (type_enum_field->type_entry->id == TypeTableEntryIdInvalid) {
|
||||
if (field_type->id == TypeTableEntryIdStruct) {
|
||||
resolve_struct_type(g, import, field_type);
|
||||
} else if (field_type->id == TypeTableEntryIdEnum) {
|
||||
resolve_enum_type(g, import, field_type);
|
||||
} else if (field_type->id == TypeTableEntryIdInvalid) {
|
||||
enum_type->data.enumeration.is_invalid = true;
|
||||
continue;
|
||||
} else if (type_enum_field->type_entry->id == TypeTableEntryIdVoid) {
|
||||
} else if (!type_has_bits(field_type)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
uint64_t debug_size_in_bits = LLVMSizeOfTypeInBits(g->target_data_ref, field_type->type_ref);
|
||||
uint64_t debug_align_in_bits = 8*LLVMABISizeOfType(g->target_data_ref, field_type->type_ref);
|
||||
|
||||
union_inner_di_types[gen_field_index] = LLVMZigCreateDebugMemberType(g->dbuilder,
|
||||
LLVMZigTypeToScope(enum_type->di_type), buf_ptr(type_enum_field->name),
|
||||
import->di_file, field_node->line + 1,
|
||||
type_enum_field->type_entry->size_in_bits,
|
||||
type_enum_field->type_entry->align_in_bits,
|
||||
0, 0, type_enum_field->type_entry->di_type);
|
||||
debug_size_in_bits,
|
||||
debug_align_in_bits,
|
||||
0,
|
||||
0, field_type->di_type);
|
||||
|
||||
biggest_align_in_bits = max(biggest_align_in_bits, type_enum_field->type_entry->align_in_bits);
|
||||
biggest_align_in_bits = max(biggest_align_in_bits, debug_align_in_bits);
|
||||
|
||||
if (!biggest_union_member ||
|
||||
type_enum_field->type_entry->size_in_bits > biggest_union_member->size_in_bits)
|
||||
debug_size_in_bits > biggest_union_member_size_in_bits)
|
||||
{
|
||||
biggest_union_member = type_enum_field->type_entry;
|
||||
biggest_union_member_size_in_bits = biggest_union_member->size_in_bits;
|
||||
biggest_union_member = field_type;
|
||||
biggest_union_member_size_in_bits = debug_size_in_bits;
|
||||
}
|
||||
|
||||
gen_field_index += 1;
|
||||
|
@ -941,8 +968,6 @@ static void resolve_enum_type(CodeGen *g, ImportTableEntry *import, TypeTableEnt
|
|||
enum_type->data.enumeration.gen_field_count = gen_field_index;
|
||||
|
||||
TypeTableEntry *tag_type_entry = get_smallest_unsigned_int_type(g, field_count);
|
||||
enum_type->align_in_bits = tag_type_entry->size_in_bits;
|
||||
enum_type->size_in_bits = tag_type_entry->size_in_bits + biggest_union_member_size_in_bits;
|
||||
enum_type->data.enumeration.tag_type = tag_type_entry;
|
||||
|
||||
if (biggest_union_member) {
|
||||
|
@ -958,30 +983,37 @@ static void resolve_enum_type(CodeGen *g, ImportTableEntry *import, TypeTableEnt
|
|||
LLVMStructSetBody(enum_type->type_ref, root_struct_element_types, 2, false);
|
||||
|
||||
// create debug type for tag
|
||||
uint64_t tag_debug_size_in_bits = LLVMSizeOfTypeInBits(g->target_data_ref, tag_type_entry->type_ref);
|
||||
uint64_t tag_debug_align_in_bits = 8*LLVMABISizeOfType(g->target_data_ref, tag_type_entry->type_ref);
|
||||
LLVMZigDIType *tag_di_type = LLVMZigCreateDebugEnumerationType(g->dbuilder,
|
||||
LLVMZigTypeToScope(enum_type->di_type), "AnonEnum", import->di_file, decl_node->line + 1,
|
||||
tag_type_entry->size_in_bits, tag_type_entry->align_in_bits, di_enumerators, field_count,
|
||||
tag_debug_size_in_bits, tag_debug_align_in_bits, di_enumerators, field_count,
|
||||
tag_type_entry->di_type, "");
|
||||
|
||||
// create debug type for union
|
||||
LLVMZigDIType *union_di_type = LLVMZigCreateDebugUnionType(g->dbuilder,
|
||||
LLVMZigTypeToScope(enum_type->di_type), "AnonUnion", import->di_file, decl_node->line + 1,
|
||||
biggest_union_member->size_in_bits, biggest_align_in_bits, 0, union_inner_di_types,
|
||||
biggest_union_member_size_in_bits, biggest_align_in_bits, 0, union_inner_di_types,
|
||||
gen_field_index, 0, "");
|
||||
|
||||
// create debug types for members of root struct
|
||||
uint64_t tag_offset_in_bits = 8*LLVMOffsetOfElement(g->target_data_ref, enum_type->type_ref, 0);
|
||||
LLVMZigDIType *tag_member_di_type = LLVMZigCreateDebugMemberType(g->dbuilder,
|
||||
LLVMZigTypeToScope(enum_type->di_type), "tag_field",
|
||||
import->di_file, decl_node->line + 1,
|
||||
tag_type_entry->size_in_bits,
|
||||
tag_type_entry->align_in_bits,
|
||||
0, 0, tag_di_type);
|
||||
tag_debug_size_in_bits,
|
||||
tag_debug_align_in_bits,
|
||||
tag_offset_in_bits,
|
||||
0, tag_di_type);
|
||||
|
||||
uint64_t union_offset_in_bits = 8*LLVMOffsetOfElement(g->target_data_ref, enum_type->type_ref, 1);
|
||||
LLVMZigDIType *union_member_di_type = LLVMZigCreateDebugMemberType(g->dbuilder,
|
||||
LLVMZigTypeToScope(enum_type->di_type), "union_field",
|
||||
import->di_file, decl_node->line + 1,
|
||||
biggest_union_member->size_in_bits,
|
||||
biggest_union_member_size_in_bits,
|
||||
biggest_align_in_bits,
|
||||
tag_type_entry->size_in_bits, 0, union_di_type);
|
||||
union_offset_in_bits,
|
||||
0, union_di_type);
|
||||
|
||||
// create debug type for root struct
|
||||
LLVMZigDIType *di_root_members[] = {
|
||||
|
@ -990,11 +1022,15 @@ static void resolve_enum_type(CodeGen *g, ImportTableEntry *import, TypeTableEnt
|
|||
};
|
||||
|
||||
|
||||
uint64_t debug_size_in_bits = LLVMSizeOfTypeInBits(g->target_data_ref, enum_type->type_ref);
|
||||
uint64_t debug_align_in_bits = 8*LLVMABISizeOfType(g->target_data_ref, enum_type->type_ref);
|
||||
LLVMZigDIType *replacement_di_type = LLVMZigCreateDebugStructType(g->dbuilder,
|
||||
LLVMZigFileToScope(import->di_file),
|
||||
buf_ptr(&decl_node->data.struct_decl.name),
|
||||
import->di_file, decl_node->line + 1, enum_type->size_in_bits, enum_type->align_in_bits, 0,
|
||||
nullptr, di_root_members, 2, 0, nullptr, "");
|
||||
import->di_file, decl_node->line + 1,
|
||||
debug_size_in_bits,
|
||||
debug_align_in_bits,
|
||||
0, nullptr, di_root_members, 2, 0, nullptr, "");
|
||||
|
||||
LLVMZigReplaceTemporary(g->dbuilder, enum_type->di_type, replacement_di_type);
|
||||
enum_type->di_type = replacement_di_type;
|
||||
|
@ -1003,10 +1039,14 @@ static void resolve_enum_type(CodeGen *g, ImportTableEntry *import, TypeTableEnt
|
|||
enum_type->type_ref = tag_type_entry->type_ref;
|
||||
|
||||
// create debug type for tag
|
||||
uint64_t tag_debug_size_in_bits = LLVMSizeOfTypeInBits(g->target_data_ref, tag_type_entry->type_ref);
|
||||
uint64_t tag_debug_align_in_bits = 8*LLVMABISizeOfType(g->target_data_ref, tag_type_entry->type_ref);
|
||||
LLVMZigDIType *tag_di_type = LLVMZigCreateDebugEnumerationType(g->dbuilder,
|
||||
LLVMZigFileToScope(import->di_file), buf_ptr(&decl_node->data.struct_decl.name),
|
||||
import->di_file, decl_node->line + 1,
|
||||
tag_type_entry->size_in_bits, tag_type_entry->align_in_bits, di_enumerators, field_count,
|
||||
tag_debug_size_in_bits,
|
||||
tag_debug_align_in_bits,
|
||||
di_enumerators, field_count,
|
||||
tag_type_entry->di_type, "");
|
||||
|
||||
LLVMZigReplaceTemporary(g->dbuilder, enum_type->di_type, tag_di_type);
|
||||
|
@ -1025,6 +1065,7 @@ static void resolve_struct_type(CodeGen *g, ImportTableEntry *import, TypeTableE
|
|||
AstNode *decl_node = struct_type->data.structure.decl_node;
|
||||
|
||||
if (struct_type->data.structure.embedded_in_current) {
|
||||
struct_type->data.structure.is_invalid = true;
|
||||
if (!struct_type->data.structure.reported_infinite_err) {
|
||||
struct_type->data.structure.reported_infinite_err = true;
|
||||
add_node_error(g, decl_node,
|
||||
|
@ -1049,11 +1090,6 @@ static void resolve_struct_type(CodeGen *g, ImportTableEntry *import, TypeTableE
|
|||
// we possibly allocate too much here since gen_field_count can be lower than field_count.
|
||||
// the only problem is potential wasted space though.
|
||||
LLVMTypeRef *element_types = allocate<LLVMTypeRef>(field_count);
|
||||
LLVMZigDIType **di_element_types = allocate<LLVMZigDIType*>(field_count);
|
||||
|
||||
uint64_t total_size_in_bits = 0;
|
||||
uint64_t first_field_align_in_bits = 0;
|
||||
uint64_t offset_in_bits = 0;
|
||||
|
||||
// this field should be set to true only during the recursive calls to resolve_struct_type
|
||||
struct_type->data.structure.embedded_in_current = true;
|
||||
|
@ -1063,41 +1099,28 @@ static void resolve_struct_type(CodeGen *g, ImportTableEntry *import, TypeTableE
|
|||
AstNode *field_node = decl_node->data.struct_decl.fields.at(i);
|
||||
TypeStructField *type_struct_field = &struct_type->data.structure.fields[i];
|
||||
type_struct_field->name = &field_node->data.struct_field.name;
|
||||
type_struct_field->type_entry = analyze_type_expr(g, import, import->block_context,
|
||||
TypeTableEntry *field_type = analyze_type_expr(g, import, import->block_context,
|
||||
field_node->data.struct_field.type);
|
||||
type_struct_field->type_entry = field_type;
|
||||
type_struct_field->src_index = i;
|
||||
type_struct_field->gen_index = -1;
|
||||
|
||||
if (type_struct_field->type_entry->id == TypeTableEntryIdStruct) {
|
||||
resolve_struct_type(g, import, type_struct_field->type_entry);
|
||||
} else if (type_struct_field->type_entry->id == TypeTableEntryIdEnum) {
|
||||
resolve_enum_type(g, import, type_struct_field->type_entry);
|
||||
} else if (type_struct_field->type_entry->id == TypeTableEntryIdInvalid) {
|
||||
if (field_type->id == TypeTableEntryIdStruct) {
|
||||
resolve_struct_type(g, import, field_type);
|
||||
} else if (field_type->id == TypeTableEntryIdEnum) {
|
||||
resolve_enum_type(g, import, field_type);
|
||||
} else if (field_type->id == TypeTableEntryIdInvalid) {
|
||||
struct_type->data.structure.is_invalid = true;
|
||||
continue;
|
||||
} else if (type_struct_field->type_entry->id == TypeTableEntryIdVoid) {
|
||||
} else if (!type_has_bits(field_type)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
type_struct_field->gen_index = gen_field_index;
|
||||
|
||||
di_element_types[gen_field_index] = LLVMZigCreateDebugMemberType(g->dbuilder,
|
||||
LLVMZigTypeToScope(struct_type->di_type), buf_ptr(type_struct_field->name),
|
||||
import->di_file, field_node->line + 1,
|
||||
type_struct_field->type_entry->size_in_bits,
|
||||
type_struct_field->type_entry->align_in_bits,
|
||||
offset_in_bits, 0, type_struct_field->type_entry->di_type);
|
||||
|
||||
element_types[gen_field_index] = type_struct_field->type_entry->type_ref;
|
||||
assert(di_element_types[gen_field_index]);
|
||||
element_types[gen_field_index] = field_type->type_ref;
|
||||
assert(element_types[gen_field_index]);
|
||||
|
||||
total_size_in_bits += type_struct_field->type_entry->size_in_bits;
|
||||
if (first_field_align_in_bits == 0) {
|
||||
first_field_align_in_bits = type_struct_field->type_entry->align_in_bits;
|
||||
}
|
||||
offset_in_bits += type_struct_field->type_entry->size_in_bits;
|
||||
|
||||
gen_field_index += 1;
|
||||
}
|
||||
struct_type->data.structure.embedded_in_current = false;
|
||||
|
@ -1105,22 +1128,55 @@ static void resolve_struct_type(CodeGen *g, ImportTableEntry *import, TypeTableE
|
|||
struct_type->data.structure.gen_field_count = gen_field_index;
|
||||
struct_type->data.structure.complete = true;
|
||||
|
||||
if (!struct_type->data.structure.is_invalid) {
|
||||
if (struct_type->data.structure.is_invalid) {
|
||||
return;
|
||||
}
|
||||
|
||||
LLVMStructSetBody(struct_type->type_ref, element_types, gen_field_index, false);
|
||||
int gen_field_count = gen_field_index;
|
||||
LLVMStructSetBody(struct_type->type_ref, element_types, gen_field_count, false);
|
||||
|
||||
struct_type->align_in_bits = first_field_align_in_bits;
|
||||
struct_type->size_in_bits = total_size_in_bits;
|
||||
LLVMZigDIType **di_element_types = allocate<LLVMZigDIType*>(gen_field_count);
|
||||
|
||||
for (int i = 0; i < field_count; i += 1) {
|
||||
AstNode *field_node = decl_node->data.struct_decl.fields.at(i);
|
||||
TypeStructField *type_struct_field = &struct_type->data.structure.fields[i];
|
||||
gen_field_index = type_struct_field->gen_index;
|
||||
if (gen_field_index == -1) {
|
||||
continue;
|
||||
}
|
||||
|
||||
TypeTableEntry *field_type = type_struct_field->type_entry;
|
||||
|
||||
uint64_t debug_size_in_bits = LLVMSizeOfTypeInBits(g->target_data_ref, field_type->type_ref);
|
||||
uint64_t debug_align_in_bits = 8*LLVMABISizeOfType(g->target_data_ref, field_type->type_ref);
|
||||
uint64_t debug_offset_in_bits = 8*LLVMOffsetOfElement(g->target_data_ref, struct_type->type_ref,
|
||||
gen_field_index);
|
||||
di_element_types[gen_field_index] = LLVMZigCreateDebugMemberType(g->dbuilder,
|
||||
LLVMZigTypeToScope(struct_type->di_type), buf_ptr(type_struct_field->name),
|
||||
import->di_file, field_node->line + 1,
|
||||
debug_size_in_bits,
|
||||
debug_align_in_bits,
|
||||
debug_offset_in_bits,
|
||||
0, field_type->di_type);
|
||||
|
||||
assert(di_element_types[gen_field_index]);
|
||||
}
|
||||
|
||||
|
||||
uint64_t debug_size_in_bits = LLVMSizeOfTypeInBits(g->target_data_ref, struct_type->type_ref);
|
||||
uint64_t debug_align_in_bits = 8*LLVMABISizeOfType(g->target_data_ref, struct_type->type_ref);
|
||||
LLVMZigDIType *replacement_di_type = LLVMZigCreateDebugStructType(g->dbuilder,
|
||||
LLVMZigFileToScope(import->di_file),
|
||||
buf_ptr(&decl_node->data.struct_decl.name),
|
||||
import->di_file, decl_node->line + 1, struct_type->size_in_bits, struct_type->align_in_bits, 0,
|
||||
nullptr, di_element_types, gen_field_index, 0, nullptr, "");
|
||||
import->di_file, decl_node->line + 1,
|
||||
debug_size_in_bits,
|
||||
debug_align_in_bits,
|
||||
0, nullptr, di_element_types, gen_field_count, 0, nullptr, "");
|
||||
|
||||
LLVMZigReplaceTemporary(g->dbuilder, struct_type->di_type, replacement_di_type);
|
||||
struct_type->di_type = replacement_di_type;
|
||||
}
|
||||
|
||||
struct_type->zero_bits = (debug_size_in_bits == 0);
|
||||
}
|
||||
|
||||
static void preview_fn_proto(CodeGen *g, ImportTableEntry *import,
|
||||
|
@ -1498,7 +1554,7 @@ static void add_global_const_expr(CodeGen *g, Expr *expr) {
|
|||
if (expr->const_val.ok &&
|
||||
type_has_codegen_value(expr->type_entry) &&
|
||||
!expr->has_global_const &&
|
||||
expr->type_entry->size_in_bits > 0)
|
||||
type_has_bits(expr->type_entry))
|
||||
{
|
||||
g->global_const_list.append(expr);
|
||||
expr->has_global_const = true;
|
||||
|
@ -1517,7 +1573,7 @@ static bool num_lit_fits_in_other_type(CodeGen *g, AstNode *literal_node, TypeTa
|
|||
} else if (other_type->id == TypeTableEntryIdInt &&
|
||||
const_val->data.x_bignum.kind == BigNumKindInt)
|
||||
{
|
||||
if (bignum_fits_in_bits(&const_val->data.x_bignum, other_type->size_in_bits,
|
||||
if (bignum_fits_in_bits(&const_val->data.x_bignum, other_type->data.integral.bit_count,
|
||||
other_type->data.integral.is_signed))
|
||||
{
|
||||
return true;
|
||||
|
@ -1653,14 +1709,14 @@ static TypeTableEntry *determine_peer_type_compatibility(CodeGen *g, AstNode *pa
|
|||
cur_type->id == TypeTableEntryIdInt &&
|
||||
prev_type->data.integral.is_signed == cur_type->data.integral.is_signed)
|
||||
{
|
||||
if (cur_type->size_in_bits > prev_type->size_in_bits) {
|
||||
if (cur_type->data.integral.bit_count > prev_type->data.integral.bit_count) {
|
||||
prev_type = cur_type;
|
||||
prev_node = cur_node;
|
||||
}
|
||||
} else if (prev_type->id == TypeTableEntryIdFloat &&
|
||||
cur_type->id == TypeTableEntryIdFloat)
|
||||
{
|
||||
if (cur_type->size_in_bits > prev_type->size_in_bits) {
|
||||
if (cur_type->data.floating.bit_count > prev_type->data.floating.bit_count) {
|
||||
prev_type = cur_type;
|
||||
prev_node = cur_node;
|
||||
}
|
||||
|
@ -1737,7 +1793,7 @@ static bool types_match_with_implicit_cast(CodeGen *g, TypeTableEntry *expected_
|
|||
if (expected_type->id == TypeTableEntryIdInt &&
|
||||
actual_type->id == TypeTableEntryIdInt &&
|
||||
expected_type->data.integral.is_signed == actual_type->data.integral.is_signed &&
|
||||
expected_type->size_in_bits >= actual_type->size_in_bits)
|
||||
expected_type->data.integral.bit_count >= actual_type->data.integral.bit_count)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
@ -1745,7 +1801,7 @@ static bool types_match_with_implicit_cast(CodeGen *g, TypeTableEntry *expected_
|
|||
// implicit float widening conversion
|
||||
if (expected_type->id == TypeTableEntryIdFloat &&
|
||||
actual_type->id == TypeTableEntryIdFloat &&
|
||||
expected_type->size_in_bits >= actual_type->size_in_bits)
|
||||
expected_type->data.floating.bit_count >= actual_type->data.floating.bit_count)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
@ -2221,15 +2277,15 @@ static TypeTableEntry *analyze_slice_expr(CodeGen *g, ImportTableEntry *import,
|
|||
if (array_type->id == TypeTableEntryIdInvalid) {
|
||||
return_type = g->builtin_types.entry_invalid;
|
||||
} else if (array_type->id == TypeTableEntryIdArray) {
|
||||
return_type = get_unknown_size_array_type(g, array_type->data.array.child_type,
|
||||
return_type = get_slice_type(g, array_type->data.array.child_type,
|
||||
node->data.slice_expr.is_const);
|
||||
} else if (array_type->id == TypeTableEntryIdPointer) {
|
||||
return_type = get_unknown_size_array_type(g, array_type->data.pointer.child_type,
|
||||
return_type = get_slice_type(g, array_type->data.pointer.child_type,
|
||||
node->data.slice_expr.is_const);
|
||||
} else if (array_type->id == TypeTableEntryIdStruct &&
|
||||
array_type->data.structure.is_unknown_size_array)
|
||||
{
|
||||
return_type = get_unknown_size_array_type(g,
|
||||
return_type = get_slice_type(g,
|
||||
array_type->data.structure.fields[0].type_entry->data.pointer.child_type,
|
||||
node->data.slice_expr.is_const);
|
||||
} else {
|
||||
|
@ -2666,7 +2722,7 @@ static TypeTableEntry *analyze_bool_bin_op_expr(CodeGen *g, ImportTableEntry *im
|
|||
bool are_equal = false;
|
||||
if (enum1->tag == enum2->tag) {
|
||||
TypeEnumField *enum_field = &op1_type->data.enumeration.fields[enum1->tag];
|
||||
if (enum_field->type_entry->size_in_bits > 0) {
|
||||
if (type_has_bits(enum_field->type_entry)) {
|
||||
zig_panic("TODO const expr analyze enum special value for equality");
|
||||
} else {
|
||||
are_equal = true;
|
||||
|
@ -2839,7 +2895,7 @@ static TypeTableEntry *analyze_bin_op_expr(CodeGen *g, ImportTableEntry *import,
|
|||
AstNode **op1 = node->data.bin_op_expr.op1->parent_field;
|
||||
AstNode **op2 = node->data.bin_op_expr.op2->parent_field;
|
||||
|
||||
TypeTableEntry *str_type = get_unknown_size_array_type(g, g->builtin_types.entry_u8, true);
|
||||
TypeTableEntry *str_type = get_slice_type(g, g->builtin_types.entry_u8, true);
|
||||
|
||||
TypeTableEntry *op1_type = analyze_expression(g, import, context, str_type, *op1);
|
||||
TypeTableEntry *op2_type = analyze_expression(g, import, context, str_type, *op2);
|
||||
|
@ -3162,11 +3218,11 @@ static TypeTableEntry *analyze_array_type(CodeGen *g, ImportTableEntry *import,
|
|||
}
|
||||
} else {
|
||||
return resolve_expr_const_val_as_type(g, node,
|
||||
get_unknown_size_array_type(g, child_type, node->data.array_type.is_const));
|
||||
get_slice_type(g, child_type, node->data.array_type.is_const));
|
||||
}
|
||||
} else {
|
||||
return resolve_expr_const_val_as_type(g, node,
|
||||
get_unknown_size_array_type(g, child_type, node->data.array_type.is_const));
|
||||
get_slice_type(g, child_type, node->data.array_type.is_const));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3357,13 +3413,13 @@ static TypeTableEntry *analyze_min_max_value(CodeGen *g, ImportTableEntry *impor
|
|||
if (is_max) {
|
||||
if (type_entry->data.integral.is_signed) {
|
||||
int64_t val;
|
||||
if (type_entry->size_in_bits == 64) {
|
||||
if (type_entry->data.integral.bit_count == 64) {
|
||||
val = INT64_MAX;
|
||||
} else if (type_entry->size_in_bits == 32) {
|
||||
} else if (type_entry->data.integral.bit_count == 32) {
|
||||
val = INT32_MAX;
|
||||
} else if (type_entry->size_in_bits == 16) {
|
||||
} else if (type_entry->data.integral.bit_count == 16) {
|
||||
val = INT16_MAX;
|
||||
} else if (type_entry->size_in_bits == 8) {
|
||||
} else if (type_entry->data.integral.bit_count == 8) {
|
||||
val = INT8_MAX;
|
||||
} else {
|
||||
zig_unreachable();
|
||||
|
@ -3371,13 +3427,13 @@ static TypeTableEntry *analyze_min_max_value(CodeGen *g, ImportTableEntry *impor
|
|||
bignum_init_signed(&const_val->data.x_bignum, val);
|
||||
} else {
|
||||
uint64_t val;
|
||||
if (type_entry->size_in_bits == 64) {
|
||||
if (type_entry->data.integral.bit_count == 64) {
|
||||
val = UINT64_MAX;
|
||||
} else if (type_entry->size_in_bits == 32) {
|
||||
} else if (type_entry->data.integral.bit_count == 32) {
|
||||
val = UINT32_MAX;
|
||||
} else if (type_entry->size_in_bits == 16) {
|
||||
} else if (type_entry->data.integral.bit_count == 16) {
|
||||
val = UINT16_MAX;
|
||||
} else if (type_entry->size_in_bits == 8) {
|
||||
} else if (type_entry->data.integral.bit_count == 8) {
|
||||
val = UINT8_MAX;
|
||||
} else {
|
||||
zig_unreachable();
|
||||
|
@ -3387,13 +3443,13 @@ static TypeTableEntry *analyze_min_max_value(CodeGen *g, ImportTableEntry *impor
|
|||
} else {
|
||||
if (type_entry->data.integral.is_signed) {
|
||||
int64_t val;
|
||||
if (type_entry->size_in_bits == 64) {
|
||||
if (type_entry->data.integral.bit_count == 64) {
|
||||
val = INT64_MIN;
|
||||
} else if (type_entry->size_in_bits == 32) {
|
||||
} else if (type_entry->data.integral.bit_count == 32) {
|
||||
val = INT32_MIN;
|
||||
} else if (type_entry->size_in_bits == 16) {
|
||||
} else if (type_entry->data.integral.bit_count == 16) {
|
||||
val = INT16_MIN;
|
||||
} else if (type_entry->size_in_bits == 8) {
|
||||
} else if (type_entry->data.integral.bit_count == 8) {
|
||||
val = INT8_MIN;
|
||||
} else {
|
||||
zig_unreachable();
|
||||
|
@ -3657,14 +3713,16 @@ static TypeTableEntry *analyze_cast_expr(CodeGen *g, ImportTableEntry *import, B
|
|||
|
||||
// explicit cast from %void to integer type which can fit it
|
||||
bool actual_type_is_void_err = actual_type->id == TypeTableEntryIdErrorUnion &&
|
||||
actual_type->data.error.child_type->size_in_bits == 0;
|
||||
!type_has_bits(actual_type->data.error.child_type);
|
||||
bool actual_type_is_pure_err = actual_type->id == TypeTableEntryIdPureError;
|
||||
if ((actual_type_is_void_err || actual_type_is_pure_err) &&
|
||||
wanted_type->id == TypeTableEntryIdInt)
|
||||
{
|
||||
BigNum bn;
|
||||
bignum_init_unsigned(&bn, g->error_value_count);
|
||||
if (bignum_fits_in_bits(&bn, wanted_type->size_in_bits, wanted_type->data.integral.is_signed)) {
|
||||
if (bignum_fits_in_bits(&bn, wanted_type->data.integral.bit_count,
|
||||
wanted_type->data.integral.is_signed))
|
||||
{
|
||||
node->data.fn_call_expr.cast_op = CastOpErrToInt;
|
||||
eval_const_expr_implicit_cast(g, node, expr_node);
|
||||
return wanted_type;
|
||||
|
@ -3767,13 +3825,13 @@ static TypeTableEntry *analyze_builtin_fn_call_expr(CodeGen *g, ImportTableEntry
|
|||
if (dest_type->id == TypeTableEntryIdPointer &&
|
||||
src_type->id == TypeTableEntryIdPointer)
|
||||
{
|
||||
uint64_t dest_align_bits = dest_type->data.pointer.child_type->align_in_bits;
|
||||
uint64_t src_align_bits = src_type->data.pointer.child_type->align_in_bits;
|
||||
if (dest_align_bits != src_align_bits) {
|
||||
uint64_t dest_align = get_memcpy_align(g, dest_type->data.pointer.child_type);
|
||||
uint64_t src_align = get_memcpy_align(g, src_type->data.pointer.child_type);
|
||||
if (dest_align != src_align) {
|
||||
add_node_error(g, dest_node, buf_sprintf(
|
||||
"misaligned memcpy, '%s' has alignment '%" PRIu64 ", '%s' has alignment %" PRIu64,
|
||||
buf_ptr(&dest_type->name), dest_align_bits / 8,
|
||||
buf_ptr(&src_type->name), src_align_bits / 8));
|
||||
buf_ptr(&dest_type->name), dest_align,
|
||||
buf_ptr(&src_type->name), src_align));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3808,10 +3866,30 @@ static TypeTableEntry *analyze_builtin_fn_call_expr(CodeGen *g, ImportTableEntry
|
|||
buf_sprintf("no size available for type '%s'", buf_ptr(&type_entry->name)));
|
||||
return g->builtin_types.entry_invalid;
|
||||
} else {
|
||||
uint64_t size_in_bytes = type_entry->size_in_bits / 8;
|
||||
uint64_t size_in_bytes;
|
||||
if (type_has_bits(type_entry)) {
|
||||
size_in_bytes = LLVMStoreSizeOfType(g->target_data_ref, type_entry->type_ref);
|
||||
} else {
|
||||
size_in_bytes = 0;
|
||||
}
|
||||
return resolve_expr_const_val_as_unsigned_num_lit(g, node, expected_type, size_in_bytes);
|
||||
}
|
||||
}
|
||||
case BuiltinFnIdAlignof:
|
||||
{
|
||||
AstNode *type_node = node->data.fn_call_expr.params.at(0);
|
||||
TypeTableEntry *type_entry = analyze_type_expr(g, import, context, type_node);
|
||||
if (type_entry->id == TypeTableEntryIdInvalid) {
|
||||
return g->builtin_types.entry_invalid;
|
||||
} else if (type_entry->id == TypeTableEntryIdUnreachable) {
|
||||
add_node_error(g, first_executing_node(type_node),
|
||||
buf_sprintf("no align available for type '%s'", buf_ptr(&type_entry->name)));
|
||||
return g->builtin_types.entry_invalid;
|
||||
} else {
|
||||
uint64_t align_in_bytes = LLVMABISizeOfType(g->target_data_ref, type_entry->type_ref);
|
||||
return resolve_expr_const_val_as_unsigned_num_lit(g, node, expected_type, align_in_bytes);
|
||||
}
|
||||
}
|
||||
case BuiltinFnIdMaxValue:
|
||||
return analyze_min_max_value(g, import, context, node,
|
||||
"no max value available for type '%s'", true);
|
||||
|
@ -3874,7 +3952,7 @@ static TypeTableEntry *analyze_builtin_fn_call_expr(CodeGen *g, ImportTableEntry
|
|||
}
|
||||
|
||||
AstNode **str_node = node->data.fn_call_expr.params.at(0)->parent_field;
|
||||
TypeTableEntry *str_type = get_unknown_size_array_type(g, g->builtin_types.entry_u8, true);
|
||||
TypeTableEntry *str_type = get_slice_type(g, g->builtin_types.entry_u8, true);
|
||||
TypeTableEntry *resolved_type = analyze_expression(g, import, context, str_type, *str_node);
|
||||
|
||||
if (resolved_type->id == TypeTableEntryIdInvalid) {
|
||||
|
@ -3911,7 +3989,7 @@ static TypeTableEntry *analyze_builtin_fn_call_expr(CodeGen *g, ImportTableEntry
|
|||
{
|
||||
AstNode **str_node = node->data.fn_call_expr.params.at(0)->parent_field;
|
||||
|
||||
TypeTableEntry *str_type = get_unknown_size_array_type(g, g->builtin_types.entry_u8, true);
|
||||
TypeTableEntry *str_type = get_slice_type(g, g->builtin_types.entry_u8, true);
|
||||
TypeTableEntry *resolved_type = analyze_expression(g, import, context, str_type, *str_node);
|
||||
|
||||
if (resolved_type->id == TypeTableEntryIdInvalid) {
|
||||
|
@ -5317,8 +5395,6 @@ void semantic_analyze(CodeGen *g) {
|
|||
g->err_tag_type = get_smallest_unsigned_int_type(g, g->error_value_count);
|
||||
|
||||
g->builtin_types.entry_pure_error->type_ref = g->err_tag_type->type_ref;
|
||||
g->builtin_types.entry_pure_error->size_in_bits = g->err_tag_type->size_in_bits;
|
||||
g->builtin_types.entry_pure_error->align_in_bits = g->err_tag_type->align_in_bits;
|
||||
g->builtin_types.entry_pure_error->di_type = g->err_tag_type->di_type;
|
||||
}
|
||||
|
||||
|
@ -5571,7 +5647,7 @@ bool handle_is_ptr(TypeTableEntry *type_entry) {
|
|||
case TypeTableEntryIdStruct:
|
||||
return true;
|
||||
case TypeTableEntryIdErrorUnion:
|
||||
return type_entry->data.error.child_type->size_in_bits > 0;
|
||||
return type_has_bits(type_entry->data.error.child_type);
|
||||
case TypeTableEntryIdEnum:
|
||||
return type_entry->data.enumeration.gen_field_count != 0;
|
||||
case TypeTableEntryIdMaybe:
|
||||
|
@ -5640,3 +5716,59 @@ bool fn_type_id_eql(FnTypeId a, FnTypeId b) {
|
|||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool type_has_bits(TypeTableEntry *type_entry) {
|
||||
assert(type_entry);
|
||||
assert(type_entry->id != TypeTableEntryIdInvalid);
|
||||
return !type_entry->zero_bits;
|
||||
}
|
||||
|
||||
static TypeTableEntry *first_struct_field_type(TypeTableEntry *type_entry) {
|
||||
assert(type_entry->id == TypeTableEntryIdStruct);
|
||||
for (int i = 0; i < type_entry->data.structure.src_field_count; i += 1) {
|
||||
TypeStructField *tsf = &type_entry->data.structure.fields[i];
|
||||
if (tsf->gen_index == 0) {
|
||||
return tsf->type_entry;
|
||||
}
|
||||
}
|
||||
zig_unreachable();
|
||||
}
|
||||
|
||||
static TypeTableEntry *type_of_first_thing_in_memory(TypeTableEntry *type_entry) {
|
||||
assert(type_has_bits(type_entry));
|
||||
switch (type_entry->id) {
|
||||
case TypeTableEntryIdInvalid:
|
||||
case TypeTableEntryIdNumLitFloat:
|
||||
case TypeTableEntryIdNumLitInt:
|
||||
case TypeTableEntryIdUndefLit:
|
||||
case TypeTableEntryIdUnreachable:
|
||||
case TypeTableEntryIdMetaType:
|
||||
case TypeTableEntryIdVoid:
|
||||
zig_unreachable();
|
||||
case TypeTableEntryIdArray:
|
||||
return type_of_first_thing_in_memory(type_entry->data.array.child_type);
|
||||
case TypeTableEntryIdStruct:
|
||||
return type_of_first_thing_in_memory(first_struct_field_type(type_entry));
|
||||
case TypeTableEntryIdMaybe:
|
||||
return type_of_first_thing_in_memory(type_entry->data.maybe.child_type);
|
||||
case TypeTableEntryIdErrorUnion:
|
||||
return type_of_first_thing_in_memory(type_entry->data.error.child_type);
|
||||
case TypeTableEntryIdTypeDecl:
|
||||
return type_of_first_thing_in_memory(type_entry->data.type_decl.canonical_type);
|
||||
case TypeTableEntryIdEnum:
|
||||
return type_entry->data.enumeration.tag_type;
|
||||
case TypeTableEntryIdPureError:
|
||||
case TypeTableEntryIdFn:
|
||||
case TypeTableEntryIdBool:
|
||||
case TypeTableEntryIdInt:
|
||||
case TypeTableEntryIdFloat:
|
||||
case TypeTableEntryIdPointer:
|
||||
return type_entry;
|
||||
}
|
||||
}
|
||||
|
||||
uint64_t get_memcpy_align(CodeGen *g, TypeTableEntry *type_entry) {
|
||||
TypeTableEntry *first_type_in_mem = type_of_first_thing_in_memory(type_entry);
|
||||
return LLVMABISizeOfType(g->target_data_ref, first_type_in_mem->type_ref);
|
||||
}
|
||||
|
||||
|
|
|
@ -35,5 +35,7 @@ bool handle_is_ptr(TypeTableEntry *type_entry);
|
|||
void find_libc_path(CodeGen *g);
|
||||
|
||||
TypeTableEntry *get_underlying_type(TypeTableEntry *type_entry);
|
||||
bool type_has_bits(TypeTableEntry *type_entry);
|
||||
uint64_t get_memcpy_align(CodeGen *g, TypeTableEntry *type_entry);
|
||||
|
||||
#endif
|
||||
|
|
168
src/codegen.cpp
168
src/codegen.cpp
|
@ -145,8 +145,9 @@ static int bits_index(int size_in_bits) {
|
|||
static LLVMValueRef get_arithmetic_overflow_fn(CodeGen *g, TypeTableEntry *type_entry,
|
||||
const char *signed_name, const char *unsigned_name)
|
||||
{
|
||||
assert(type_entry->id == TypeTableEntryIdInt);
|
||||
const char *signed_str = type_entry->data.integral.is_signed ? signed_name : unsigned_name;
|
||||
Buf *llvm_name = buf_sprintf("llvm.%s.with.overflow.i%" PRIu64, signed_str, type_entry->size_in_bits);
|
||||
Buf *llvm_name = buf_sprintf("llvm.%s.with.overflow.i%d", signed_str, type_entry->data.integral.bit_count);
|
||||
|
||||
LLVMTypeRef return_elem_types[] = {
|
||||
type_entry->type_ref,
|
||||
|
@ -168,7 +169,7 @@ static LLVMValueRef get_int_overflow_fn(CodeGen *g, TypeTableEntry *type_entry,
|
|||
// [0-signed,1-unsigned][0-add,1-sub,2-mul][0-8,1-16,2-32,3-64]
|
||||
int index0 = type_entry->data.integral.is_signed ? 0 : 1;
|
||||
int index1 = add_sub_mul;
|
||||
int index2 = bits_index(type_entry->size_in_bits);
|
||||
int index2 = bits_index(type_entry->data.integral.bit_count);
|
||||
LLVMValueRef *fn = &g->int_overflow_fns[index0][index1][index2];
|
||||
if (*fn) {
|
||||
return *fn;
|
||||
|
@ -188,7 +189,6 @@ static LLVMValueRef get_int_overflow_fn(CodeGen *g, TypeTableEntry *type_entry,
|
|||
return *fn;
|
||||
}
|
||||
|
||||
|
||||
static LLVMValueRef gen_builtin_fn_call_expr(CodeGen *g, AstNode *node) {
|
||||
assert(node->type == NodeTypeFnCallExpr);
|
||||
AstNode *fn_ref_expr = node->data.fn_call_expr.fn_ref_expr;
|
||||
|
@ -257,7 +257,7 @@ static LLVMValueRef gen_builtin_fn_call_expr(CodeGen *g, AstNode *node) {
|
|||
LLVMValueRef dest_ptr_casted = LLVMBuildBitCast(g->builder, dest_ptr, ptr_u8, "");
|
||||
LLVMValueRef src_ptr_casted = LLVMBuildBitCast(g->builder, src_ptr, ptr_u8, "");
|
||||
|
||||
uint64_t align_in_bytes = dest_type->data.pointer.child_type->align_in_bits / 8;
|
||||
uint64_t align_in_bytes = get_memcpy_align(g, dest_type->data.pointer.child_type);
|
||||
|
||||
LLVMValueRef params[] = {
|
||||
dest_ptr_casted, // dest pointer
|
||||
|
@ -287,7 +287,7 @@ static LLVMValueRef gen_builtin_fn_call_expr(CodeGen *g, AstNode *node) {
|
|||
add_debug_source_node(g, node);
|
||||
LLVMValueRef dest_ptr_casted = LLVMBuildBitCast(g->builder, dest_ptr, ptr_u8, "");
|
||||
|
||||
uint64_t align_in_bytes = dest_type->data.pointer.child_type->align_in_bits / 8;
|
||||
uint64_t align_in_bytes = get_memcpy_align(g, dest_type->data.pointer.child_type);
|
||||
|
||||
LLVMValueRef params[] = {
|
||||
dest_ptr_casted, // dest pointer
|
||||
|
@ -301,6 +301,7 @@ static LLVMValueRef gen_builtin_fn_call_expr(CodeGen *g, AstNode *node) {
|
|||
return nullptr;
|
||||
}
|
||||
case BuiltinFnIdSizeof:
|
||||
case BuiltinFnIdAlignof:
|
||||
case BuiltinFnIdMinValue:
|
||||
case BuiltinFnIdMaxValue:
|
||||
case BuiltinFnIdMemberCount:
|
||||
|
@ -359,9 +360,21 @@ static LLVMValueRef gen_widen_or_shorten(CodeGen *g, AstNode *source_node, TypeT
|
|||
TypeTableEntry *wanted_type, LLVMValueRef expr_val)
|
||||
{
|
||||
assert(actual_type->id == wanted_type->id);
|
||||
if (actual_type->size_in_bits == wanted_type->size_in_bits) {
|
||||
uint64_t actual_bits;
|
||||
uint64_t wanted_bits;
|
||||
if (actual_type->id == TypeTableEntryIdFloat) {
|
||||
actual_bits = actual_type->data.floating.bit_count;
|
||||
wanted_bits = wanted_type->data.floating.bit_count;
|
||||
} else if (actual_type->id == TypeTableEntryIdInt) {
|
||||
actual_bits = actual_type->data.integral.bit_count;
|
||||
wanted_bits = wanted_type->data.integral.bit_count;
|
||||
} else {
|
||||
zig_unreachable();
|
||||
}
|
||||
|
||||
if (actual_bits == wanted_bits) {
|
||||
return expr_val;
|
||||
} else if (actual_type->size_in_bits < wanted_type->size_in_bits) {
|
||||
} else if (actual_bits < wanted_bits) {
|
||||
if (actual_type->id == TypeTableEntryIdFloat) {
|
||||
add_debug_source_node(g, source_node);
|
||||
return LLVMBuildFPExt(g->builder, expr_val, wanted_type->type_ref, "");
|
||||
|
@ -376,7 +389,7 @@ static LLVMValueRef gen_widen_or_shorten(CodeGen *g, AstNode *source_node, TypeT
|
|||
} else {
|
||||
zig_unreachable();
|
||||
}
|
||||
} else if (actual_type->size_in_bits > wanted_type->size_in_bits) {
|
||||
} else if (actual_bits > wanted_bits) {
|
||||
if (actual_type->id == TypeTableEntryIdFloat) {
|
||||
add_debug_source_node(g, source_node);
|
||||
return LLVMBuildFPTrunc(g->builder, expr_val, wanted_type->type_ref, "");
|
||||
|
@ -410,7 +423,7 @@ static LLVMValueRef gen_cast_expr(CodeGen *g, AstNode *node) {
|
|||
return expr_val;
|
||||
case CastOpErrToInt:
|
||||
assert(actual_type->id == TypeTableEntryIdErrorUnion);
|
||||
if (actual_type->data.error.child_type->size_in_bits == 0) {
|
||||
if (!type_has_bits(actual_type->data.error.child_type)) {
|
||||
return gen_widen_or_shorten(g, node, g->err_tag_type, wanted_type, expr_val);
|
||||
} else {
|
||||
zig_panic("TODO");
|
||||
|
@ -446,7 +459,7 @@ static LLVMValueRef gen_cast_expr(CodeGen *g, AstNode *node) {
|
|||
TypeTableEntry *child_type = wanted_type->data.error.child_type;
|
||||
LLVMValueRef ok_err_val = LLVMConstNull(g->err_tag_type->type_ref);
|
||||
|
||||
if (child_type->size_in_bits == 0) {
|
||||
if (!type_has_bits(child_type)) {
|
||||
return ok_err_val;
|
||||
} else {
|
||||
assert(cast_expr->tmp_ptr);
|
||||
|
@ -466,7 +479,7 @@ static LLVMValueRef gen_cast_expr(CodeGen *g, AstNode *node) {
|
|||
}
|
||||
case CastOpPureErrorWrap:
|
||||
assert(wanted_type->id == TypeTableEntryIdErrorUnion);
|
||||
if (wanted_type->data.error.child_type->size_in_bits == 0) {
|
||||
if (!type_has_bits(wanted_type->data.error.child_type)) {
|
||||
return expr_val;
|
||||
} else {
|
||||
zig_panic("TODO");
|
||||
|
@ -607,7 +620,7 @@ static LLVMValueRef gen_fn_call_expr(CodeGen *g, AstNode *node) {
|
|||
AstNode *expr_node = node->data.fn_call_expr.params.at(i);
|
||||
LLVMValueRef param_value = gen_expr(g, expr_node);
|
||||
TypeTableEntry *param_type = get_expr_type(expr_node);
|
||||
if (is_var_args || param_type->size_in_bits > 0) {
|
||||
if (is_var_args || type_has_bits(param_type)) {
|
||||
gen_param_values[gen_param_index] = param_value;
|
||||
gen_param_index += 1;
|
||||
}
|
||||
|
@ -621,7 +634,7 @@ static LLVMValueRef gen_fn_call_expr(CodeGen *g, AstNode *node) {
|
|||
return LLVMBuildUnreachable(g->builder);
|
||||
} else if (first_arg_ret) {
|
||||
return node->data.fn_call_expr.tmp_ptr;
|
||||
} else if (src_return_type->size_in_bits == 0) {
|
||||
} else if (!type_has_bits(src_return_type)) {
|
||||
return nullptr;
|
||||
} else {
|
||||
return result;
|
||||
|
@ -653,7 +666,7 @@ static LLVMValueRef gen_array_elem_ptr(CodeGen *g, AstNode *source_node, LLVMVal
|
|||
{
|
||||
assert(subscript_value);
|
||||
|
||||
if (array_type->size_in_bits == 0) {
|
||||
if (!type_has_bits(array_type)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
@ -978,7 +991,7 @@ static LLVMValueRef gen_prefix_op_expr(CodeGen *g, AstNode *node) {
|
|||
case PrefixOpDereference:
|
||||
{
|
||||
LLVMValueRef expr = gen_expr(g, expr_node);
|
||||
if (expr_type->size_in_bits == 0) {
|
||||
if (!type_has_bits(expr_type)) {
|
||||
return nullptr;
|
||||
} else {
|
||||
add_debug_source_node(g, node);
|
||||
|
@ -1002,7 +1015,7 @@ static LLVMValueRef gen_prefix_op_expr(CodeGen *g, AstNode *node) {
|
|||
|
||||
if (g->build_type != CodeGenBuildTypeRelease) {
|
||||
LLVMValueRef err_val;
|
||||
if (child_type->size_in_bits > 0) {
|
||||
if (type_has_bits(child_type)) {
|
||||
add_debug_source_node(g, node);
|
||||
LLVMValueRef err_val_ptr = LLVMBuildStructGEP(g->builder, expr_val, 0, "");
|
||||
err_val = LLVMBuildLoad(g->builder, err_val_ptr, "");
|
||||
|
@ -1022,7 +1035,7 @@ static LLVMValueRef gen_prefix_op_expr(CodeGen *g, AstNode *node) {
|
|||
LLVMPositionBuilderAtEnd(g->builder, ok_block);
|
||||
}
|
||||
|
||||
if (child_type->size_in_bits > 0) {
|
||||
if (type_has_bits(child_type)) {
|
||||
LLVMValueRef child_val_ptr = LLVMBuildStructGEP(g->builder, expr_val, 1, "");
|
||||
if (handle_is_ptr(child_type)) {
|
||||
return child_val_ptr;
|
||||
|
@ -1337,11 +1350,15 @@ static LLVMValueRef gen_struct_memcpy(CodeGen *g, AstNode *source_node, LLVMValu
|
|||
LLVMValueRef src_ptr = LLVMBuildBitCast(g->builder, src, ptr_u8, "");
|
||||
LLVMValueRef dest_ptr = LLVMBuildBitCast(g->builder, dest, ptr_u8, "");
|
||||
|
||||
TypeTableEntry *isize = g->builtin_types.entry_isize;
|
||||
uint64_t size_bytes = LLVMStoreSizeOfType(g->target_data_ref, type_entry->type_ref);
|
||||
uint64_t align_bytes = get_memcpy_align(g, type_entry);
|
||||
|
||||
LLVMValueRef params[] = {
|
||||
dest_ptr, // dest pointer
|
||||
src_ptr, // source pointer
|
||||
LLVMConstInt(LLVMIntType(g->pointer_size_bytes * 8), type_entry->size_in_bits / 8, false), // byte count
|
||||
LLVMConstInt(LLVMInt32Type(), type_entry->align_in_bits / 8, false), // align in bytes
|
||||
LLVMConstInt(isize->type_ref, size_bytes, false),
|
||||
LLVMConstInt(LLVMInt32Type(), align_bytes, false),
|
||||
LLVMConstNull(LLVMInt1Type()), // is volatile
|
||||
};
|
||||
|
||||
|
@ -1384,7 +1401,7 @@ static LLVMValueRef gen_assign_expr(CodeGen *g, AstNode *node) {
|
|||
|
||||
LLVMValueRef value = gen_expr(g, node->data.bin_op_expr.op2);
|
||||
|
||||
if (op1_type->size_in_bits == 0) {
|
||||
if (!type_has_bits(op1_type)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
@ -1546,7 +1563,7 @@ static LLVMValueRef gen_unwrap_err_expr(CodeGen *g, AstNode *node) {
|
|||
LLVMBasicBlockRef err_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "UnwrapErrError");
|
||||
LLVMBasicBlockRef end_block;
|
||||
bool err_reachable = op2_type->id != TypeTableEntryIdUnreachable;
|
||||
bool have_end_block = err_reachable && (child_type->size_in_bits > 0);
|
||||
bool have_end_block = err_reachable && type_has_bits(child_type);
|
||||
if (have_end_block) {
|
||||
end_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "UnwrapErrEnd");
|
||||
}
|
||||
|
@ -1566,7 +1583,7 @@ static LLVMValueRef gen_unwrap_err_expr(CodeGen *g, AstNode *node) {
|
|||
}
|
||||
|
||||
LLVMPositionBuilderAtEnd(g->builder, ok_block);
|
||||
if (child_type->size_in_bits == 0) {
|
||||
if (!type_has_bits(child_type)) {
|
||||
return nullptr;
|
||||
}
|
||||
LLVMValueRef child_val_ptr = LLVMBuildStructGEP(g->builder, expr_val, 1, "");
|
||||
|
@ -1624,7 +1641,7 @@ static LLVMValueRef gen_return_expr(CodeGen *g, AstNode *node) {
|
|||
|
||||
add_debug_source_node(g, node);
|
||||
LLVMValueRef err_val;
|
||||
if (child_type->size_in_bits > 0) {
|
||||
if (type_has_bits(child_type)) {
|
||||
LLVMValueRef err_val_ptr = LLVMBuildStructGEP(g->builder, value, 0, "");
|
||||
err_val = LLVMBuildLoad(g->builder, err_val_ptr, "");
|
||||
} else {
|
||||
|
@ -1639,7 +1656,7 @@ static LLVMValueRef gen_return_expr(CodeGen *g, AstNode *node) {
|
|||
if (return_type->id == TypeTableEntryIdPureError) {
|
||||
gen_return(g, node, err_val);
|
||||
} else if (return_type->id == TypeTableEntryIdErrorUnion) {
|
||||
if (return_type->data.error.child_type->size_in_bits > 0) {
|
||||
if (type_has_bits(return_type->data.error.child_type)) {
|
||||
assert(g->cur_ret_ptr);
|
||||
|
||||
add_debug_source_node(g, node);
|
||||
|
@ -1654,7 +1671,7 @@ static LLVMValueRef gen_return_expr(CodeGen *g, AstNode *node) {
|
|||
}
|
||||
|
||||
LLVMPositionBuilderAtEnd(g->builder, continue_block);
|
||||
if (child_type->size_in_bits > 0) {
|
||||
if (type_has_bits(child_type)) {
|
||||
add_debug_source_node(g, node);
|
||||
LLVMValueRef val_ptr = LLVMBuildStructGEP(g->builder, value, 1, "");
|
||||
if (handle_is_ptr(child_type)) {
|
||||
|
@ -2164,7 +2181,7 @@ static LLVMValueRef gen_var_decl_raw(CodeGen *g, AstNode *source_node, AstNodeVa
|
|||
*init_value = gen_expr(g, var_decl->expr);
|
||||
*expr_type = get_expr_type(var_decl->expr);
|
||||
}
|
||||
if (variable->type->size_in_bits == 0) {
|
||||
if (!type_has_bits(variable->type)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
@ -2225,15 +2242,17 @@ static LLVMValueRef gen_var_decl_raw(CodeGen *g, AstNode *source_node, AstNodeVa
|
|||
}
|
||||
}
|
||||
if (!ignore_uninit && g->build_type != CodeGenBuildTypeRelease) {
|
||||
TypeTableEntry *isize = g->builtin_types.entry_isize;
|
||||
uint64_t size_bytes = LLVMStoreSizeOfType(g->target_data_ref, variable->type->type_ref);
|
||||
uint64_t align_bytes = get_memcpy_align(g, variable->type);
|
||||
|
||||
// memset uninitialized memory to 0xa
|
||||
add_debug_source_node(g, source_node);
|
||||
LLVMTypeRef ptr_u8 = LLVMPointerType(LLVMInt8Type(), 0);
|
||||
LLVMValueRef fill_char = LLVMConstInt(LLVMInt8Type(), 0xaa, false);
|
||||
LLVMValueRef dest_ptr = LLVMBuildBitCast(g->builder, variable->value_ref, ptr_u8, "");
|
||||
LLVMValueRef byte_count = LLVMConstInt(LLVMIntType(g->pointer_size_bytes * 8),
|
||||
variable->type->size_in_bits / 8, false);
|
||||
LLVMValueRef align_in_bytes = LLVMConstInt(LLVMInt32Type(),
|
||||
variable->type->align_in_bits / 8, false);
|
||||
LLVMValueRef byte_count = LLVMConstInt(isize->type_ref, size_bytes, false);
|
||||
LLVMValueRef align_in_bytes = LLVMConstInt(LLVMInt32Type(), align_bytes, false);
|
||||
LLVMValueRef params[] = {
|
||||
dest_ptr,
|
||||
fill_char,
|
||||
|
@ -2273,7 +2292,7 @@ static LLVMValueRef gen_symbol(CodeGen *g, AstNode *node) {
|
|||
assert(node->type == NodeTypeSymbol);
|
||||
VariableTableEntry *variable = node->data.symbol_expr.variable;
|
||||
if (variable) {
|
||||
if (variable->type->size_in_bits == 0) {
|
||||
if (!type_has_bits(variable->type)) {
|
||||
return nullptr;
|
||||
} else if (variable->is_ptr) {
|
||||
assert(variable->value_ref);
|
||||
|
@ -2364,7 +2383,7 @@ static LLVMValueRef gen_switch_expr(CodeGen *g, AstNode *node) {
|
|||
static LLVMValueRef gen_expr(CodeGen *g, AstNode *node) {
|
||||
Expr *expr = get_resolved_expr(node);
|
||||
if (expr->const_val.ok) {
|
||||
if (expr->type_entry->size_in_bits == 0) {
|
||||
if (!type_has_bits(expr->type_entry)) {
|
||||
return nullptr;
|
||||
} else {
|
||||
assert(expr->const_llvm_val);
|
||||
|
@ -2600,7 +2619,7 @@ static LLVMValueRef gen_const_val(CodeGen *g, TypeTableEntry *type_entry, ConstE
|
|||
case TypeTableEntryIdErrorUnion:
|
||||
{
|
||||
TypeTableEntry *child_type = type_entry->data.error.child_type;
|
||||
if (child_type->size_in_bits == 0) {
|
||||
if (!type_has_bits(child_type)) {
|
||||
uint64_t value = const_val->data.x_err.err ? const_val->data.x_err.err->value : 0;
|
||||
return LLVMConstInt(g->err_tag_type->type_ref, value, false);
|
||||
} else {
|
||||
|
@ -2683,7 +2702,7 @@ static void do_code_gen(CodeGen *g) {
|
|||
|
||||
if (var->type->id == TypeTableEntryIdNumLitFloat ||
|
||||
var->type->id == TypeTableEntryIdNumLitInt ||
|
||||
var->type->size_in_bits == 0)
|
||||
!type_has_bits(var->type))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
@ -2820,7 +2839,7 @@ static void do_code_gen(CodeGen *g) {
|
|||
for (int var_i = 0; var_i < block_context->variable_list.length; var_i += 1) {
|
||||
VariableTableEntry *var = block_context->variable_list.at(var_i);
|
||||
|
||||
if (var->type->size_in_bits == 0) {
|
||||
if (!type_has_bits(var->type)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -2839,7 +2858,8 @@ static void do_code_gen(CodeGen *g) {
|
|||
|
||||
add_debug_source_node(g, var->decl_node);
|
||||
var->value_ref = LLVMBuildAlloca(g->builder, var->type->type_ref, buf_ptr(&var->name));
|
||||
LLVMSetAlignment(var->value_ref, var->type->align_in_bits / 8);
|
||||
uint64_t align_bytes = LLVMABISizeOfType(g->target_data_ref, var->type->type_ref);
|
||||
LLVMSetAlignment(var->value_ref, align_bytes);
|
||||
}
|
||||
|
||||
var->di_loc_var = LLVMZigCreateLocalVariable(g->dbuilder, tag,
|
||||
|
@ -2953,16 +2973,19 @@ static void define_builtin_types(CodeGen *g) {
|
|||
// if this type is anywhere in the AST, we should never hit codegen.
|
||||
TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdInvalid);
|
||||
buf_init_from_str(&entry->name, "(invalid)");
|
||||
entry->zero_bits = true;
|
||||
g->builtin_types.entry_invalid = entry;
|
||||
}
|
||||
{
|
||||
TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdNumLitFloat);
|
||||
buf_init_from_str(&entry->name, "(float literal)");
|
||||
entry->zero_bits = true;
|
||||
g->builtin_types.entry_num_lit_float = entry;
|
||||
}
|
||||
{
|
||||
TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdNumLitInt);
|
||||
buf_init_from_str(&entry->name, "(integer literal)");
|
||||
entry->zero_bits = true;
|
||||
g->builtin_types.entry_num_lit_int = entry;
|
||||
}
|
||||
{
|
||||
|
@ -2982,12 +3005,13 @@ static void define_builtin_types(CodeGen *g) {
|
|||
buf_resize(&entry->name, 0);
|
||||
buf_appendf(&entry->name, "%c%d", u_or_i, size_in_bits);
|
||||
|
||||
entry->size_in_bits = size_in_bits;
|
||||
entry->align_in_bits = size_in_bits;
|
||||
uint64_t debug_size_in_bits = LLVMSizeOfTypeInBits(g->target_data_ref, entry->type_ref);
|
||||
uint64_t debug_align_in_bits = 8*LLVMABISizeOfType(g->target_data_ref, entry->type_ref);
|
||||
entry->di_type = LLVMZigCreateDebugBasicType(g->dbuilder, buf_ptr(&entry->name),
|
||||
entry->size_in_bits, entry->align_in_bits,
|
||||
debug_size_in_bits, debug_align_in_bits,
|
||||
is_signed ? LLVMZigEncoding_DW_ATE_signed() : LLVMZigEncoding_DW_ATE_unsigned());
|
||||
entry->data.integral.is_signed = is_signed;
|
||||
entry->data.integral.bit_count = size_in_bits;
|
||||
g->primitive_type_table.put(&entry->name, entry);
|
||||
|
||||
get_int_type_ptr(g, is_signed, size_in_bits)[0] = entry;
|
||||
|
@ -3010,13 +3034,14 @@ static void define_builtin_types(CodeGen *g) {
|
|||
|
||||
buf_init_from_str(&entry->name, info->name);
|
||||
|
||||
entry->size_in_bits = size_in_bits;
|
||||
entry->align_in_bits = size_in_bits;
|
||||
|
||||
uint64_t debug_size_in_bits = LLVMSizeOfTypeInBits(g->target_data_ref, entry->type_ref);
|
||||
uint64_t debug_align_in_bits = 8*LLVMABISizeOfType(g->target_data_ref, entry->type_ref);
|
||||
entry->di_type = LLVMZigCreateDebugBasicType(g->dbuilder, buf_ptr(&entry->name),
|
||||
entry->size_in_bits, entry->align_in_bits,
|
||||
debug_size_in_bits,
|
||||
debug_align_in_bits,
|
||||
is_signed ? LLVMZigEncoding_DW_ATE_signed() : LLVMZigEncoding_DW_ATE_unsigned());
|
||||
entry->data.integral.is_signed = is_signed;
|
||||
entry->data.integral.bit_count = size_in_bits;
|
||||
g->primitive_type_table.put(&entry->name, entry);
|
||||
|
||||
get_c_int_type_ptr(g, info->id)[0] = entry;
|
||||
|
@ -3026,10 +3051,11 @@ static void define_builtin_types(CodeGen *g) {
|
|||
TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdBool);
|
||||
entry->type_ref = LLVMInt1Type();
|
||||
buf_init_from_str(&entry->name, "bool");
|
||||
entry->size_in_bits = 8;
|
||||
entry->align_in_bits = 8;
|
||||
uint64_t debug_size_in_bits = LLVMSizeOfTypeInBits(g->target_data_ref, entry->type_ref);
|
||||
uint64_t debug_align_in_bits = 8*LLVMABISizeOfType(g->target_data_ref, entry->type_ref);
|
||||
entry->di_type = LLVMZigCreateDebugBasicType(g->dbuilder, buf_ptr(&entry->name),
|
||||
entry->size_in_bits, entry->align_in_bits,
|
||||
debug_size_in_bits,
|
||||
debug_align_in_bits,
|
||||
LLVMZigEncoding_DW_ATE_unsigned());
|
||||
g->builtin_types.entry_bool = entry;
|
||||
g->primitive_type_table.put(&entry->name, entry);
|
||||
|
@ -3038,12 +3064,14 @@ static void define_builtin_types(CodeGen *g) {
|
|||
TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdInt);
|
||||
entry->type_ref = LLVMIntType(g->pointer_size_bytes * 8);
|
||||
buf_init_from_str(&entry->name, "isize");
|
||||
entry->size_in_bits = g->pointer_size_bytes * 8;
|
||||
entry->align_in_bits = g->pointer_size_bytes * 8;
|
||||
entry->data.integral.is_signed = true;
|
||||
entry->data.integral.bit_count = g->pointer_size_bytes * 8;
|
||||
|
||||
uint64_t debug_size_in_bits = LLVMSizeOfTypeInBits(g->target_data_ref, entry->type_ref);
|
||||
uint64_t debug_align_in_bits = 8*LLVMABISizeOfType(g->target_data_ref, entry->type_ref);
|
||||
entry->di_type = LLVMZigCreateDebugBasicType(g->dbuilder, buf_ptr(&entry->name),
|
||||
entry->size_in_bits, entry->align_in_bits,
|
||||
debug_size_in_bits,
|
||||
debug_align_in_bits,
|
||||
LLVMZigEncoding_DW_ATE_signed());
|
||||
g->builtin_types.entry_isize = entry;
|
||||
g->primitive_type_table.put(&entry->name, entry);
|
||||
|
@ -3052,12 +3080,14 @@ static void define_builtin_types(CodeGen *g) {
|
|||
TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdInt);
|
||||
entry->type_ref = LLVMIntType(g->pointer_size_bytes * 8);
|
||||
buf_init_from_str(&entry->name, "usize");
|
||||
entry->size_in_bits = g->pointer_size_bytes * 8;
|
||||
entry->align_in_bits = g->pointer_size_bytes * 8;
|
||||
entry->data.integral.is_signed = false;
|
||||
entry->data.integral.bit_count = g->pointer_size_bytes * 8;
|
||||
|
||||
uint64_t debug_size_in_bits = LLVMSizeOfTypeInBits(g->target_data_ref, entry->type_ref);
|
||||
uint64_t debug_align_in_bits = 8*LLVMABISizeOfType(g->target_data_ref, entry->type_ref);
|
||||
entry->di_type = LLVMZigCreateDebugBasicType(g->dbuilder, buf_ptr(&entry->name),
|
||||
entry->size_in_bits, entry->align_in_bits,
|
||||
debug_size_in_bits,
|
||||
debug_align_in_bits,
|
||||
LLVMZigEncoding_DW_ATE_unsigned());
|
||||
g->builtin_types.entry_usize = entry;
|
||||
g->primitive_type_table.put(&entry->name, entry);
|
||||
|
@ -3066,10 +3096,13 @@ static void define_builtin_types(CodeGen *g) {
|
|||
TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdFloat);
|
||||
entry->type_ref = LLVMFloatType();
|
||||
buf_init_from_str(&entry->name, "f32");
|
||||
entry->size_in_bits = 32;
|
||||
entry->align_in_bits = 32;
|
||||
entry->data.floating.bit_count = 32;
|
||||
|
||||
uint64_t debug_size_in_bits = LLVMSizeOfTypeInBits(g->target_data_ref, entry->type_ref);
|
||||
uint64_t debug_align_in_bits = 8*LLVMABISizeOfType(g->target_data_ref, entry->type_ref);
|
||||
entry->di_type = LLVMZigCreateDebugBasicType(g->dbuilder, buf_ptr(&entry->name),
|
||||
entry->size_in_bits, entry->align_in_bits,
|
||||
debug_size_in_bits,
|
||||
debug_align_in_bits,
|
||||
LLVMZigEncoding_DW_ATE_float());
|
||||
g->builtin_types.entry_f32 = entry;
|
||||
g->primitive_type_table.put(&entry->name, entry);
|
||||
|
@ -3078,10 +3111,13 @@ static void define_builtin_types(CodeGen *g) {
|
|||
TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdFloat);
|
||||
entry->type_ref = LLVMDoubleType();
|
||||
buf_init_from_str(&entry->name, "f64");
|
||||
entry->size_in_bits = 64;
|
||||
entry->align_in_bits = 64;
|
||||
entry->data.floating.bit_count = 64;
|
||||
|
||||
uint64_t debug_size_in_bits = LLVMSizeOfTypeInBits(g->target_data_ref, entry->type_ref);
|
||||
uint64_t debug_align_in_bits = 8*LLVMABISizeOfType(g->target_data_ref, entry->type_ref);
|
||||
entry->di_type = LLVMZigCreateDebugBasicType(g->dbuilder, buf_ptr(&entry->name),
|
||||
entry->size_in_bits, entry->align_in_bits,
|
||||
debug_size_in_bits,
|
||||
debug_align_in_bits,
|
||||
LLVMZigEncoding_DW_ATE_float());
|
||||
g->builtin_types.entry_f64 = entry;
|
||||
g->primitive_type_table.put(&entry->name, entry);
|
||||
|
@ -3090,10 +3126,13 @@ static void define_builtin_types(CodeGen *g) {
|
|||
TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdFloat);
|
||||
entry->type_ref = LLVMX86FP80Type();
|
||||
buf_init_from_str(&entry->name, "c_long_double");
|
||||
entry->size_in_bits = 128;
|
||||
entry->align_in_bits = 128;
|
||||
entry->data.floating.bit_count = 80;
|
||||
|
||||
uint64_t debug_size_in_bits = LLVMSizeOfTypeInBits(g->target_data_ref, entry->type_ref);
|
||||
uint64_t debug_align_in_bits = 8*LLVMABISizeOfType(g->target_data_ref, entry->type_ref);
|
||||
entry->di_type = LLVMZigCreateDebugBasicType(g->dbuilder, buf_ptr(&entry->name),
|
||||
80, entry->align_in_bits,
|
||||
debug_size_in_bits,
|
||||
debug_align_in_bits,
|
||||
LLVMZigEncoding_DW_ATE_float());
|
||||
g->builtin_types.entry_c_long_double = entry;
|
||||
g->primitive_type_table.put(&entry->name, entry);
|
||||
|
@ -3101,9 +3140,11 @@ static void define_builtin_types(CodeGen *g) {
|
|||
{
|
||||
TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdVoid);
|
||||
entry->type_ref = LLVMVoidType();
|
||||
entry->zero_bits = true;
|
||||
buf_init_from_str(&entry->name, "void");
|
||||
entry->di_type = LLVMZigCreateDebugBasicType(g->dbuilder, buf_ptr(&entry->name),
|
||||
entry->size_in_bits, entry->align_in_bits,
|
||||
0,
|
||||
0,
|
||||
LLVMZigEncoding_DW_ATE_unsigned());
|
||||
g->builtin_types.entry_void = entry;
|
||||
g->primitive_type_table.put(&entry->name, entry);
|
||||
|
@ -3111,6 +3152,7 @@ static void define_builtin_types(CodeGen *g) {
|
|||
{
|
||||
TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdUnreachable);
|
||||
entry->type_ref = LLVMVoidType();
|
||||
entry->zero_bits = true;
|
||||
buf_init_from_str(&entry->name, "unreachable");
|
||||
entry->di_type = g->builtin_types.entry_void->di_type;
|
||||
g->builtin_types.entry_unreachable = entry;
|
||||
|
@ -3119,6 +3161,7 @@ static void define_builtin_types(CodeGen *g) {
|
|||
{
|
||||
TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdMetaType);
|
||||
buf_init_from_str(&entry->name, "type");
|
||||
entry->zero_bits = true;
|
||||
g->builtin_types.entry_type = entry;
|
||||
g->primitive_type_table.put(&entry->name, entry);
|
||||
}
|
||||
|
@ -3212,6 +3255,7 @@ static void define_builtin_fns(CodeGen *g) {
|
|||
g->memset_fn_val = builtin_fn->fn_val;
|
||||
}
|
||||
create_builtin_fn_with_arg_count(g, BuiltinFnIdSizeof, "sizeof", 1);
|
||||
create_builtin_fn_with_arg_count(g, BuiltinFnIdAlignof, "alignof", 1);
|
||||
create_builtin_fn_with_arg_count(g, BuiltinFnIdMaxValue, "max_value", 1);
|
||||
create_builtin_fn_with_arg_count(g, BuiltinFnIdMinValue, "min_value", 1);
|
||||
create_builtin_fn_with_arg_count(g, BuiltinFnIdMemberCount, "member_count", 1);
|
||||
|
|
|
@ -740,8 +740,6 @@ static void visit_enum_decl(Context *c, const EnumDecl *enum_decl) {
|
|||
enum_type->data.enumeration.complete = true;
|
||||
|
||||
TypeTableEntry *tag_type_entry = get_smallest_unsigned_int_type(c->codegen, field_count);
|
||||
enum_type->align_in_bits = tag_type_entry->size_in_bits;
|
||||
enum_type->size_in_bits = tag_type_entry->size_in_bits;
|
||||
enum_type->data.enumeration.tag_type = tag_type_entry;
|
||||
|
||||
c->enum_type_table.put(bare_name, enum_type);
|
||||
|
@ -795,11 +793,14 @@ static void visit_enum_decl(Context *c, const EnumDecl *enum_decl) {
|
|||
|
||||
// create debug type for tag
|
||||
unsigned line = c->source_node ? (c->source_node->line + 1) : 0;
|
||||
uint64_t debug_size_in_bits = LLVMSizeOfTypeInBits(c->codegen->target_data_ref, enum_type->type_ref);
|
||||
uint64_t debug_align_in_bits = 8*LLVMABISizeOfType(c->codegen->target_data_ref, enum_type->type_ref);
|
||||
LLVMZigDIType *tag_di_type = LLVMZigCreateDebugEnumerationType(c->codegen->dbuilder,
|
||||
LLVMZigFileToScope(c->import->di_file), buf_ptr(bare_name),
|
||||
c->import->di_file, line,
|
||||
tag_type_entry->size_in_bits, tag_type_entry->align_in_bits, di_enumerators, field_count,
|
||||
tag_type_entry->di_type, "");
|
||||
debug_size_in_bits,
|
||||
debug_align_in_bits,
|
||||
di_enumerators, field_count, tag_type_entry->di_type, "");
|
||||
|
||||
LLVMZigReplaceTemporary(c->codegen->dbuilder, enum_type->di_type, tag_di_type);
|
||||
enum_type->di_type = tag_di_type;
|
||||
|
@ -894,10 +895,6 @@ static TypeTableEntry *resolve_record_decl(Context *c, const RecordDecl *record_
|
|||
LLVMTypeRef *element_types = allocate<LLVMTypeRef>(field_count);
|
||||
LLVMZigDIType **di_element_types = allocate<LLVMZigDIType*>(field_count);
|
||||
|
||||
uint64_t total_size_in_bits = 0;
|
||||
uint64_t first_field_align_in_bits = 0;
|
||||
uint64_t offset_in_bits = 0;
|
||||
|
||||
uint32_t i = 0;
|
||||
for (auto it = record_def->field_begin(),
|
||||
it_end = record_def->field_end();
|
||||
|
@ -909,30 +906,29 @@ static TypeTableEntry *resolve_record_decl(Context *c, const RecordDecl *record_
|
|||
type_struct_field->name = buf_create_from_str(decl_name(field_decl));
|
||||
type_struct_field->src_index = i;
|
||||
type_struct_field->gen_index = i;
|
||||
type_struct_field->type_entry = resolve_qual_type(c, field_decl->getType(), field_decl);
|
||||
TypeTableEntry *field_type = resolve_qual_type(c, field_decl->getType(), field_decl);
|
||||
type_struct_field->type_entry = field_type;
|
||||
|
||||
if (type_struct_field->type_entry->id == TypeTableEntryIdInvalid) {
|
||||
if (field_type->id == TypeTableEntryIdInvalid) {
|
||||
emit_warning(c, field_decl, "struct %s demoted to typedef - unresolved type\n", buf_ptr(bare_name));
|
||||
return struct_type;
|
||||
}
|
||||
|
||||
uint64_t debug_size_in_bits = LLVMSizeOfTypeInBits(c->codegen->target_data_ref, field_type->type_ref);
|
||||
uint64_t debug_align_in_bits = 8*LLVMABISizeOfType(c->codegen->target_data_ref, field_type->type_ref);
|
||||
uint64_t debug_offset_in_bits = 8*LLVMOffsetOfElement(c->codegen->target_data_ref, struct_type->type_ref, i);
|
||||
di_element_types[i] = LLVMZigCreateDebugMemberType(c->codegen->dbuilder,
|
||||
LLVMZigTypeToScope(struct_type->di_type), buf_ptr(type_struct_field->name),
|
||||
c->import->di_file, line + 1,
|
||||
type_struct_field->type_entry->size_in_bits,
|
||||
type_struct_field->type_entry->align_in_bits,
|
||||
offset_in_bits, 0, type_struct_field->type_entry->di_type);
|
||||
debug_size_in_bits,
|
||||
debug_align_in_bits,
|
||||
debug_offset_in_bits,
|
||||
0, field_type->di_type);
|
||||
|
||||
element_types[i] = type_struct_field->type_entry->type_ref;
|
||||
element_types[i] = field_type->type_ref;
|
||||
assert(di_element_types[i]);
|
||||
assert(element_types[i]);
|
||||
|
||||
total_size_in_bits += type_struct_field->type_entry->size_in_bits;
|
||||
if (first_field_align_in_bits == 0) {
|
||||
first_field_align_in_bits = type_struct_field->type_entry->align_in_bits;
|
||||
}
|
||||
offset_in_bits += type_struct_field->type_entry->size_in_bits;
|
||||
|
||||
}
|
||||
struct_type->data.structure.embedded_in_current = false;
|
||||
|
||||
|
@ -941,13 +937,14 @@ static TypeTableEntry *resolve_record_decl(Context *c, const RecordDecl *record_
|
|||
|
||||
LLVMStructSetBody(struct_type->type_ref, element_types, field_count, false);
|
||||
|
||||
struct_type->align_in_bits = first_field_align_in_bits;
|
||||
struct_type->size_in_bits = total_size_in_bits;
|
||||
|
||||
uint64_t debug_size_in_bits = LLVMSizeOfTypeInBits(c->codegen->target_data_ref, struct_type->type_ref);
|
||||
uint64_t debug_align_in_bits = 8*LLVMABISizeOfType(c->codegen->target_data_ref, struct_type->type_ref);
|
||||
LLVMZigDIType *replacement_di_type = LLVMZigCreateDebugStructType(c->codegen->dbuilder,
|
||||
LLVMZigFileToScope(c->import->di_file),
|
||||
buf_ptr(full_type_name),
|
||||
c->import->di_file, line + 1, struct_type->size_in_bits, struct_type->align_in_bits, 0,
|
||||
buf_ptr(full_type_name), c->import->di_file, line + 1,
|
||||
debug_size_in_bits,
|
||||
debug_align_in_bits,
|
||||
0,
|
||||
nullptr, di_element_types, field_count, 0, nullptr, "");
|
||||
|
||||
LLVMZigReplaceTemporary(c->codegen->dbuilder, struct_type->di_type, replacement_di_type);
|
||||
|
|
|
@ -379,10 +379,10 @@ pub fn main(args: [][]u8) -> %void {
|
|||
array[0] = void{};
|
||||
array[1] = array[2];
|
||||
if (@sizeof(@typeof(array)) != 0) {
|
||||
%%stdout.printf("BAD\n");
|
||||
%%stdout.printf("BAD sizeof\n");
|
||||
}
|
||||
if (array.len != 4) {
|
||||
%%stdout.printf("BAD\n");
|
||||
%%stdout.printf("BAD len\n");
|
||||
}
|
||||
%%stdout.printf("OK\n");
|
||||
}
|
||||
|
@ -1075,22 +1075,22 @@ pub fn main(args: [][]u8) -> %void {
|
|||
const bar = Bar.B;
|
||||
|
||||
if (bar != Bar.B) {
|
||||
%%stdout.printf("BAD\n");
|
||||
%%stdout.printf("BAD 1\n");
|
||||
}
|
||||
|
||||
if (@member_count(Foo) != 3) {
|
||||
%%stdout.printf("BAD\n");
|
||||
%%stdout.printf("BAD 2\n");
|
||||
}
|
||||
|
||||
if (@member_count(Bar) != 4) {
|
||||
%%stdout.printf("BAD\n");
|
||||
%%stdout.printf("BAD 3\n");
|
||||
}
|
||||
|
||||
if (@sizeof(Foo) != 17) {
|
||||
%%stdout.printf("BAD\n");
|
||||
if (@sizeof(Foo) != 24) {
|
||||
%%stdout.printf("BAD 4\n");
|
||||
}
|
||||
if (@sizeof(Bar) != 1) {
|
||||
%%stdout.printf("BAD\n");
|
||||
%%stdout.printf("BAD 5\n");
|
||||
}
|
||||
|
||||
%%stdout.printf("OK\n");
|
||||
|
|
Loading…
Reference in New Issue