| ... | @@ -1410,17 +1410,45 @@ static LLVMValueRef ir_render_store_ptr(CodeGen *g, IrExecutable *executable, Ir | ... | @@ -1410,17 +1410,45 @@ static LLVMValueRef ir_render_store_ptr(CodeGen *g, IrExecutable *executable, Ir |
| 1410 | TypeTableEntry *ptr_type = get_underlying_type(instruction->ptr->value.type); | 1410 | TypeTableEntry *ptr_type = get_underlying_type(instruction->ptr->value.type); |
| 1411 | TypeTableEntry *child_type = get_underlying_type(ptr_type->data.pointer.child_type); | 1411 | TypeTableEntry *child_type = get_underlying_type(ptr_type->data.pointer.child_type); |
| 1412 | | 1412 | |
| 1413 | if (!type_has_bits(child_type)) { | 1413 | if (!type_has_bits(child_type)) |
| 1414 | return nullptr; | 1414 | return nullptr; |
| 1415 | } | 1415 | |
| 1416 | if (handle_is_ptr(child_type)) { | 1416 | if (handle_is_ptr(child_type)) |
| 1417 | return gen_struct_memcpy(g, value, ptr, child_type); | 1417 | return gen_struct_memcpy(g, value, ptr, child_type); |
| | 1418 | |
| | 1419 | uint32_t bit_offset = ptr_type->data.pointer.bit_offset; |
| | 1420 | if (bit_offset == 0) { |
| | 1421 | LLVMTypeRef ptr_child_ref = LLVMGetElementType(LLVMTypeOf(ptr)); |
| | 1422 | bool need_to_do_some_bit_stuff = |
| | 1423 | LLVMGetTypeKind(ptr_child_ref) == LLVMIntegerTypeKind && |
| | 1424 | LLVMGetTypeKind(child_type->type_ref) == LLVMIntegerTypeKind && |
| | 1425 | LLVMGetIntTypeWidth(child_type->type_ref) < LLVMGetIntTypeWidth(ptr_child_ref); |
| | 1426 | if (!need_to_do_some_bit_stuff) { |
| | 1427 | LLVMValueRef llvm_instruction = LLVMBuildStore(g->builder, value, ptr); |
| | 1428 | LLVMSetVolatile(llvm_instruction, ptr_type->data.pointer.is_volatile); |
| | 1429 | return nullptr; |
| | 1430 | } |
| 1418 | } | 1431 | } |
| 1419 | | 1432 | |
| 1420 | LLVMValueRef llvm_instruction = LLVMBuildStore(g->builder, value, ptr); | 1433 | LLVMValueRef containing_int = LLVMBuildLoad(g->builder, ptr, ""); |
| 1421 | | 1434 | |
| 1422 | LLVMSetVolatile(llvm_instruction, ptr_type->data.pointer.is_volatile); | 1435 | uint32_t child_bit_count = type_size_bits(g, child_type); |
| | 1436 | uint32_t host_bit_count = LLVMGetIntTypeWidth(LLVMTypeOf(containing_int)); |
| | 1437 | uint32_t shift_amt = host_bit_count - bit_offset - child_bit_count; |
| | 1438 | LLVMValueRef shift_amt_val = LLVMConstInt(LLVMTypeOf(containing_int), shift_amt, false); |
| | 1439 | |
| | 1440 | LLVMValueRef mask_val = LLVMConstAllOnes(child_type->type_ref); |
| | 1441 | mask_val = LLVMConstZExt(mask_val, LLVMTypeOf(containing_int)); |
| | 1442 | mask_val = LLVMConstShl(mask_val, shift_amt_val); |
| | 1443 | mask_val = LLVMConstNot(mask_val); |
| 1423 | | 1444 | |
| | 1445 | LLVMValueRef anded_containing_int = LLVMBuildAnd(g->builder, containing_int, mask_val, ""); |
| | 1446 | LLVMValueRef extended_value = LLVMBuildZExt(g->builder, value, LLVMTypeOf(containing_int), ""); |
| | 1447 | LLVMValueRef shifted_value = LLVMBuildShl(g->builder, extended_value, shift_amt_val, ""); |
| | 1448 | LLVMValueRef ored_value = LLVMBuildOr(g->builder, shifted_value, anded_containing_int, ""); |
| | 1449 | |
| | 1450 | LLVMValueRef llvm_instruction = LLVMBuildStore(g->builder, ored_value, ptr); |
| | 1451 | LLVMSetVolatile(llvm_instruction, ptr_type->data.pointer.is_volatile); |
| 1424 | return nullptr; | 1452 | return nullptr; |
| 1425 | } | 1453 | } |
| 1426 | | 1454 | |