types sized and aligned with LLVM target data layout API

master
Andrew Kelley 2016-02-03 00:42:24 -07:00
parent b04e64d300
commit b28f7d0808
6 changed files with 438 additions and 257 deletions

View File

@ -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,

View File

@ -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);
}

View File

@ -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

View File

@ -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);

View File

@ -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);

View File

@ -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");