Commit b28f7d0808
Changed files (6)
src/all_types.hpp
@@ -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,
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;
- } else {
- zero_bits = true;
- }
+
+ if (type_is_complete(canon_child_type)) {
+ entry->zero_bits = !type_has_bits(canon_child_type);
} 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);
- 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, "");
+ 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);
- LLVMZigReplaceTemporary(g->dbuilder, struct_type->di_type, replacement_di_type);
- struct_type->di_type = replacement_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,
+ 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);
+}
+
src/analyze.hpp
@@ -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
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);
src/parseh.cpp
@@ -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);
test/run_tests.cpp
@@ -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");