| ... | ... | @@ -1410,17 +1410,45 @@ static LLVMValueRef ir_render_store_ptr(CodeGen *g, IrExecutable *executable, Ir |
| 1410 | 1410 | TypeTableEntry *ptr_type = get_underlying_type(instruction->ptr->value.type); |
| 1411 | 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 | 1414 | return nullptr; |
| 1415 | | } |
| 1416 | | if (handle_is_ptr(child_type)) { |
| 1415 | |
| 1416 | if (handle_is_ptr(child_type)) |
| 1417 | 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 | 1452 | return nullptr; |
| 1425 | 1453 | } |
| 1426 | 1454 | |