aboutsummaryrefslogtreecommitdiff
path: root/src/codegen.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/codegen.cpp')
-rw-r--r--src/codegen.cpp84
1 files changed, 58 insertions, 26 deletions
diff --git a/src/codegen.cpp b/src/codegen.cpp
index 1a091584b4..ea4d698cde 100644
--- a/src/codegen.cpp
+++ b/src/codegen.cpp
@@ -7140,12 +7140,12 @@ static LLVMValueRef gen_const_val(CodeGen *g, ZigValue *const_val, const char *n
ZigType *type_entry = const_val->type;
assert(type_has_bits(g, type_entry));
-check: switch (const_val->special) {
+ if (const_val->special == ConstValSpecialLazy &&
+ (err = ir_resolve_lazy(g, nullptr, const_val)))
+ codegen_report_errors_and_exit(g);
+
+ switch (const_val->special) {
case ConstValSpecialLazy:
- if ((err = ir_resolve_lazy(g, nullptr, const_val))) {
- codegen_report_errors_and_exit(g);
- }
- goto check;
case ConstValSpecialRuntime:
zig_unreachable();
case ConstValSpecialUndef:
@@ -7222,12 +7222,26 @@ check: switch (const_val->special) {
make_unnamed_struct = false;
}
+
LLVMValueRef fields[] = {
child_val,
maybe_val,
+ nullptr,
};
if (make_unnamed_struct) {
- return LLVMConstStruct(fields, 2, false);
+ LLVMValueRef result = LLVMConstStruct(fields, 2, false);
+ uint64_t last_field_offset = LLVMOffsetOfElement(g->target_data_ref, LLVMTypeOf(result), 1);
+ uint64_t end_offset = last_field_offset +
+ LLVMStoreSizeOfType(g->target_data_ref, LLVMTypeOf(fields[1]));
+ uint64_t expected_sz = LLVMABISizeOfType(g->target_data_ref, get_llvm_type(g, type_entry));
+ unsigned pad_sz = expected_sz - end_offset;
+ if (pad_sz != 0) {
+ fields[2] = LLVMGetUndef(LLVMArrayType(LLVMInt8Type(), pad_sz));
+ result = LLVMConstStruct(fields, 3, false);
+ }
+ uint64_t actual_sz = LLVMStoreSizeOfType(g->target_data_ref, LLVMTypeOf(result));
+ assert(actual_sz == expected_sz);
+ return result;
} else {
return LLVMConstNamedStruct(get_llvm_type(g, type_entry), fields, 2);
}
@@ -7316,32 +7330,50 @@ check: switch (const_val->special) {
continue;
}
ZigValue *field_val = const_val->data.x_struct.fields[i];
- assert(field_val->type != nullptr);
- if ((err = ensure_const_val_repr(nullptr, g, nullptr, field_val,
- type_struct_field->type_entry)))
- {
+ ZigType *field_type = field_val->type;
+ assert(field_type != nullptr);
+ if ((err = ensure_const_val_repr(nullptr, g, nullptr, field_val, field_type))) {
zig_unreachable();
}
LLVMValueRef val = gen_const_val(g, field_val, "");
- fields[type_struct_field->gen_index] = val;
- make_unnamed_struct = make_unnamed_struct || is_llvm_value_unnamed_type(g, field_val->type, val);
-
- size_t end_pad_gen_index = (i + 1 < src_field_count) ?
- type_entry->data.structure.fields[i + 1]->gen_index :
- type_entry->data.structure.gen_field_count;
- size_t next_offset = (i + 1 < src_field_count) ?
- type_entry->data.structure.fields[i + 1]->offset : type_entry->abi_size;
- if (end_pad_gen_index != SIZE_MAX) {
- for (size_t gen_i = type_struct_field->gen_index + 1; gen_i < end_pad_gen_index;
- gen_i += 1)
- {
- size_t pad_bytes = next_offset -
- (type_struct_field->offset + type_struct_field->type_entry->abi_size);
- LLVMTypeRef llvm_array_type = LLVMArrayType(LLVMInt8Type(), pad_bytes);
- fields[gen_i] = LLVMGetUndef(llvm_array_type);
+ make_unnamed_struct = make_unnamed_struct || is_llvm_value_unnamed_type(g, field_type, val);
+
+ // Find the next runtime field
+ size_t next_rt_gen_index = type_entry->data.structure.gen_field_count;
+ size_t next_offset = type_entry->abi_size;
+ for (size_t j = i + 1; j < src_field_count; j++) {
+ const size_t index = type_entry->data.structure.fields[j]->gen_index;
+ const size_t offset = type_entry->data.structure.fields[j]->offset;
+
+ if (index != SIZE_MAX) {
+ next_rt_gen_index = index;
+ next_offset = offset;
+ break;
}
}
+
+ // How much padding is needed to reach the next field
+ const size_t pad_bytes = next_offset -
+ (type_struct_field->offset + LLVMABISizeOfType(g->target_data_ref, LLVMTypeOf(val)));
+ // Catch underflow
+ assert((ssize_t)pad_bytes >= 0);
+
+ if (type_struct_field->gen_index + 1 != next_rt_gen_index) {
+ // If there's a hole between this field and the next
+ // we have an alignment gap to fill
+ fields[type_struct_field->gen_index] = val;
+ fields[type_struct_field->gen_index + 1] = LLVMGetUndef(LLVMArrayType(LLVMInt8Type(), pad_bytes));
+ } else if (pad_bytes != 0) {
+ LLVMValueRef padded_val[] = {
+ val,
+ LLVMGetUndef(LLVMArrayType(LLVMInt8Type(), pad_bytes)),
+ };
+ fields[type_struct_field->gen_index] = LLVMConstStruct(padded_val, 2, true);
+ make_unnamed_struct = true;
+ } else {
+ fields[type_struct_field->gen_index] = val;
+ }
}
}
if (make_unnamed_struct) {