aboutsummaryrefslogtreecommitdiff
path: root/src/codegen.cpp
diff options
context:
space:
mode:
authorAndrew Kelley <superjoe30@gmail.com>2017-02-22 00:49:10 -0500
committerAndrew Kelley <superjoe30@gmail.com>2017-02-22 00:49:10 -0500
commitd794549985fc9a3fd6d6b1620be15d290f6a759f (patch)
tree82e39db15fd95ecb7041ec7fea74857689d07982 /src/codegen.cpp
parentcf5108f222107ed242d2dc2c37d76758157da542 (diff)
downloadzig-d794549985fc9a3fd6d6b1620be15d290f6a759f.tar.gz
zig-d794549985fc9a3fd6d6b1620be15d290f6a759f.zip
bitfields support for array of non-store-aligned packed structs
Diffstat (limited to 'src/codegen.cpp')
-rw-r--r--src/codegen.cpp29
1 files changed, 29 insertions, 0 deletions
diff --git a/src/codegen.cpp b/src/codegen.cpp
index 90c910adf3..5d98b22ab8 100644
--- a/src/codegen.cpp
+++ b/src/codegen.cpp
@@ -1466,6 +1466,27 @@ static LLVMValueRef ir_render_elem_ptr(CodeGen *g, IrExecutable *executable, IrI
array_type->data.array.len, false);
add_bounds_check(g, subscript_value, LLVMIntEQ, nullptr, LLVMIntULT, end);
}
+ if (array_ptr_type->data.pointer.unaligned_bit_count != 0) {
+ return array_ptr_ptr;
+ }
+ TypeTableEntry *canon_child_type = get_underlying_type(array_type->data.array.child_type);
+ if (canon_child_type->id == TypeTableEntryIdStruct &&
+ canon_child_type->data.structure.layout == ContainerLayoutPacked)
+ {
+ LLVMTypeRef ptr_u8_type_ref = LLVMPointerType(LLVMInt8Type(), 0);
+ LLVMValueRef u8_array_ptr = LLVMBuildBitCast(g->builder, array_ptr, ptr_u8_type_ref, "");
+ size_t unaligned_bit_count = instruction->base.value.type->data.pointer.unaligned_bit_count;
+ assert(unaligned_bit_count != 0);
+ assert(unaligned_bit_count % 8 == 0);
+ LLVMValueRef elem_size_bytes = LLVMConstInt(g->builtin_types.entry_usize->type_ref,
+ unaligned_bit_count / 8, false);
+ LLVMValueRef byte_offset = LLVMBuildNUWMul(g->builder, subscript_value, elem_size_bytes, "");
+ LLVMValueRef indices[] = {
+ byte_offset
+ };
+ LLVMValueRef elem_byte_ptr = LLVMBuildInBoundsGEP(g->builder, u8_array_ptr, indices, 1, "");
+ return LLVMBuildBitCast(g->builder, elem_byte_ptr, LLVMPointerType(canon_child_type->type_ref, 0), "");
+ }
LLVMValueRef indices[] = {
LLVMConstNull(g->builtin_types.entry_usize->type_ref),
subscript_value
@@ -1552,11 +1573,19 @@ static LLVMValueRef ir_render_struct_field_ptr(CodeGen *g, IrExecutable *executa
IrInstructionStructFieldPtr *instruction)
{
LLVMValueRef struct_ptr = ir_llvm_value(g, instruction->struct_ptr);
+ // not necessarily a pointer. could be TypeTableEntryIdStruct
+ TypeTableEntry *struct_ptr_type = instruction->struct_ptr->value.type;
TypeStructField *field = instruction->field;
if (!type_has_bits(field->type_entry))
return nullptr;
+ if (struct_ptr_type->id == TypeTableEntryIdPointer &&
+ struct_ptr_type->data.pointer.unaligned_bit_count != 0)
+ {
+ return struct_ptr;
+ }
+
assert(field->gen_index != SIZE_MAX);
return LLVMBuildStructGEP(g->builder, struct_ptr, field->gen_index, "");
}