diff options
| author | Andrew Kelley <superjoe30@gmail.com> | 2017-02-22 00:49:10 -0500 |
|---|---|---|
| committer | Andrew Kelley <superjoe30@gmail.com> | 2017-02-22 00:49:10 -0500 |
| commit | d794549985fc9a3fd6d6b1620be15d290f6a759f (patch) | |
| tree | 82e39db15fd95ecb7041ec7fea74857689d07982 /src/codegen.cpp | |
| parent | cf5108f222107ed242d2dc2c37d76758157da542 (diff) | |
| download | zig-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.cpp | 29 |
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, ""); } |
