diff options
| author | Andrew Kelley <superjoe30@gmail.com> | 2017-02-16 15:45:41 -0500 |
|---|---|---|
| committer | Andrew Kelley <superjoe30@gmail.com> | 2017-02-16 15:45:41 -0500 |
| commit | fc5d47b9b960aa08d65bf0dfe3d6395c811f793b (patch) | |
| tree | 2ccc51b0a0f2429793c4be5075bfda53b1b01b65 /src/codegen.cpp | |
| parent | 4b5cc80f665314067e0e5b96c859acca1b2e1cb0 (diff) | |
| download | zig-fc5d47b9b960aa08d65bf0dfe3d6395c811f793b.tar.gz zig-fc5d47b9b960aa08d65bf0dfe3d6395c811f793b.zip | |
reading from a bit field partially works
See #261
Still need to do:
* reading a field that has bit offset 0 but still needs to
shift and truncate
* writing a field
Diffstat (limited to 'src/codegen.cpp')
| -rw-r--r-- | src/codegen.cpp | 23 |
1 files changed, 20 insertions, 3 deletions
diff --git a/src/codegen.cpp b/src/codegen.cpp index 8180034956..0d8ef0b03a 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -1379,14 +1379,31 @@ static LLVMValueRef ir_render_decl_var(CodeGen *g, IrExecutable *executable, static LLVMValueRef ir_render_load_ptr(CodeGen *g, IrExecutable *executable, IrInstructionLoadPtr *instruction) { TypeTableEntry *child_type = instruction->base.value.type; - if (!type_has_bits(child_type)) { + if (!type_has_bits(child_type)) return nullptr; - } + LLVMValueRef ptr = ir_llvm_value(g, instruction->ptr); TypeTableEntry *ptr_type = instruction->ptr->value.type; assert(ptr_type->id == TypeTableEntryIdPointer); bool is_volatile = ptr_type->data.pointer.is_volatile; - return get_handle_value(g, ptr, child_type, is_volatile); + + uint32_t bit_offset = ptr_type->data.pointer.bit_offset; + if (bit_offset == 0) + return get_handle_value(g, ptr, child_type, is_volatile); + + assert(!handle_is_ptr(child_type)); + + LLVMValueRef containing_int = LLVMBuildLoad(g->builder, ptr, ""); + LLVMSetVolatile(containing_int, is_volatile); + + uint32_t child_bit_count = type_size_bits(g, child_type); + uint32_t host_bit_count = LLVMGetIntTypeWidth(LLVMTypeOf(containing_int)); + uint32_t shift_amt = host_bit_count - bit_offset - child_bit_count; + + LLVMValueRef shift_amt_val = LLVMConstInt(LLVMTypeOf(containing_int), shift_amt, false); + LLVMValueRef shifted_value = LLVMBuildLShr(g->builder, containing_int, shift_amt_val, ""); + + return LLVMBuildTrunc(g->builder, shifted_value, child_type->type_ref, ""); } static LLVMValueRef ir_render_store_ptr(CodeGen *g, IrExecutable *executable, IrInstructionStorePtr *instruction) { |
