| ... | @@ -5549,14 +5549,29 @@ static LLVMValueRef ir_render_vector_to_array(CodeGen *g, IrExecutable *executab | ... | @@ -5549,14 +5549,29 @@ static LLVMValueRef ir_render_vector_to_array(CodeGen *g, IrExecutable *executab |
| 5549 | assert(handle_is_ptr(array_type)); | 5549 | assert(handle_is_ptr(array_type)); |
| 5550 | LLVMValueRef result_loc = ir_llvm_value(g, instruction->result_loc); | 5550 | LLVMValueRef result_loc = ir_llvm_value(g, instruction->result_loc); |
| 5551 | LLVMValueRef vector = ir_llvm_value(g, instruction->vector); | 5551 | LLVMValueRef vector = ir_llvm_value(g, instruction->vector); |
| 5552 | LLVMValueRef array = LLVMGetUndef(get_llvm_type(g, array_type)); | 5552 | |
| 5553 | for (uintptr_t i = 0; i < instruction->vector->value.type->data.vector.len; i++) { | 5553 | ZigType *elem_type = array_type->data.array.child_type; |
| 5554 | LLVMValueRef index = LLVMConstInt(g->builtin_types.entry_u32->llvm_type, i, false); | 5554 | bool bitcast_ok = (elem_type->size_in_bits * 8) == elem_type->abi_size; |
| 5555 | LLVMValueRef elem = LLVMBuildExtractElement(g->builder, vector, | 5555 | if (bitcast_ok) { |
| 5556 | index, "vector_to_array"); | 5556 | LLVMValueRef casted_ptr = LLVMBuildBitCast(g->builder, result_loc, |
| 5557 | array = LLVMBuildInsertValue(g->builder, array, elem, i, ""); | 5557 | LLVMPointerType(get_llvm_type(g, instruction->vector->value.type), 0), ""); |
| 5558 | } | 5558 | uint32_t alignment = get_ptr_align(g, instruction->result_loc->value.type); |
| 5559 | LLVMBuildStore(g->builder, array, result_loc); | 5559 | gen_store_untyped(g, vector, casted_ptr, alignment, false); |
| | 5560 | } else { |
| | 5561 | // If the ABI size of the element type is not evenly divisible by size_in_bits, a simple bitcast |
| | 5562 | // will not work, and we fall back to extractelement. |
| | 5563 | LLVMTypeRef usize_type_ref = g->builtin_types.entry_usize->llvm_type; |
| | 5564 | LLVMTypeRef u32_type_ref = LLVMInt32Type(); |
| | 5565 | LLVMValueRef zero = LLVMConstInt(usize_type_ref, 0, false); |
| | 5566 | for (uintptr_t i = 0; i < instruction->vector->value.type->data.vector.len; i++) { |
| | 5567 | LLVMValueRef index_usize = LLVMConstInt(usize_type_ref, i, false); |
| | 5568 | LLVMValueRef index_u32 = LLVMConstInt(u32_type_ref, i, false); |
| | 5569 | LLVMValueRef indexes[] = { zero, index_usize }; |
| | 5570 | LLVMValueRef elem_ptr = LLVMBuildInBoundsGEP(g->builder, result_loc, indexes, 2, ""); |
| | 5571 | LLVMValueRef elem = LLVMBuildExtractElement(g->builder, vector, index_u32, ""); |
| | 5572 | LLVMBuildStore(g->builder, elem, elem_ptr); |
| | 5573 | } |
| | 5574 | } |
| 5560 | return result_loc; | 5575 | return result_loc; |
| 5561 | } | 5576 | } |
| 5562 | | 5577 | |
| ... | @@ -5567,16 +5582,34 @@ static LLVMValueRef ir_render_array_to_vector(CodeGen *g, IrExecutable *executab | ... | @@ -5567,16 +5582,34 @@ static LLVMValueRef ir_render_array_to_vector(CodeGen *g, IrExecutable *executab |
| 5567 | assert(vector_type->id == ZigTypeIdVector); | 5582 | assert(vector_type->id == ZigTypeIdVector); |
| 5568 | assert(!handle_is_ptr(vector_type)); | 5583 | assert(!handle_is_ptr(vector_type)); |
| 5569 | LLVMValueRef array_ptr = ir_llvm_value(g, instruction->array); | 5584 | LLVMValueRef array_ptr = ir_llvm_value(g, instruction->array); |
| 5570 | LLVMValueRef array = LLVMBuildLoad2(g->builder, get_llvm_type(g, instruction->array->value.type), | 5585 | LLVMTypeRef vector_type_ref = get_llvm_type(g, vector_type); |
| 5571 | array_ptr, ""); | 5586 | |
| 5572 | LLVMValueRef vector = LLVMGetUndef(get_llvm_type(g, vector_type)); | 5587 | ZigType *elem_type = vector_type->data.vector.elem_type; |
| 5573 | for (uintptr_t i = 0; i < instruction->base.value.type->data.vector.len; i++) { | 5588 | bool bitcast_ok = (elem_type->size_in_bits * 8) == elem_type->abi_size; |
| 5574 | LLVMValueRef index = LLVMConstInt(g->builtin_types.entry_u32->llvm_type, i, false); | 5589 | if (bitcast_ok) { |
| 5575 | LLVMValueRef elem = LLVMBuildExtractValue(g->builder, array, | 5590 | LLVMValueRef casted_ptr = LLVMBuildBitCast(g->builder, array_ptr, |
| 5576 | i, "vector_to_array"); | 5591 | LLVMPointerType(vector_type_ref, 0), ""); |
| 5577 | vector = LLVMBuildInsertElement(g->builder, vector, elem, index, ""); | 5592 | ZigType *array_type = instruction->array->value.type; |
| 5578 | } | 5593 | assert(array_type->id == ZigTypeIdArray); |
| 5579 | return vector; | 5594 | uint32_t alignment = get_abi_alignment(g, array_type->data.array.child_type); |
| | 5595 | return gen_load_untyped(g, casted_ptr, alignment, false, ""); |
| | 5596 | } else { |
| | 5597 | // If the ABI size of the element type is not evenly divisible by size_in_bits, a simple bitcast |
| | 5598 | // will not work, and we fall back to insertelement. |
| | 5599 | LLVMTypeRef usize_type_ref = g->builtin_types.entry_usize->llvm_type; |
| | 5600 | LLVMTypeRef u32_type_ref = LLVMInt32Type(); |
| | 5601 | LLVMValueRef zero = LLVMConstInt(usize_type_ref, 0, false); |
| | 5602 | LLVMValueRef vector = LLVMGetUndef(vector_type_ref); |
| | 5603 | for (uintptr_t i = 0; i < instruction->base.value.type->data.vector.len; i++) { |
| | 5604 | LLVMValueRef index_usize = LLVMConstInt(usize_type_ref, i, false); |
| | 5605 | LLVMValueRef index_u32 = LLVMConstInt(u32_type_ref, i, false); |
| | 5606 | LLVMValueRef indexes[] = { zero, index_usize }; |
| | 5607 | LLVMValueRef elem_ptr = LLVMBuildInBoundsGEP(g->builder, array_ptr, indexes, 2, ""); |
| | 5608 | LLVMValueRef elem = LLVMBuildLoad(g->builder, elem_ptr, ""); |
| | 5609 | vector = LLVMBuildInsertElement(g->builder, vector, elem, index_u32, ""); |
| | 5610 | } |
| | 5611 | return vector; |
| | 5612 | } |
| 5580 | } | 5613 | } |
| 5581 | | 5614 | |
| 5582 | static LLVMValueRef ir_render_assert_zero(CodeGen *g, IrExecutable *executable, | 5615 | static LLVMValueRef ir_render_assert_zero(CodeGen *g, IrExecutable *executable, |