authorgravatar for shawn@git.icuShawn Landden <shawn@git.icu> 2019-07-25 11:11:37-05:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-09-18 09:52:58-04:00
log0e3ca4c63ecb8e43af8261020d21bc6888d18fc0
tree7df095fa7a25c68d3648a3d87eaa937ce3ead5a4
parent914ad1ec2eff4ea9061804ad0da9cde7dd6543b6
signature Commit is signed but in an unrecognized format.

Fix array->vector and vector->array for many types. Allow vector of bool.

Vectors do not have the same packing as arrays, and just bitcasting is not the correct way to convert them.

5 files changed, 63 insertions(+), 13 deletions(-)

src/analyze.cpp+2-1
...@@ -4708,6 +4708,7 @@ ZigType *get_int_type(CodeGen *g, bool is_signed, uint32_t size_in_bits) {...@@ -4708,6 +4708,7 @@ ZigType *get_int_type(CodeGen *g, bool is_signed, uint32_t size_in_bits) {
4708bool is_valid_vector_elem_type(ZigType *elem_type) {4708bool is_valid_vector_elem_type(ZigType *elem_type) {
4709 return elem_type->id == ZigTypeIdInt ||4709 return elem_type->id == ZigTypeIdInt ||
4710 elem_type->id == ZigTypeIdFloat ||4710 elem_type->id == ZigTypeIdFloat ||
4711 elem_type->id == ZigTypeIdBool ||
4711 get_codegen_ptr_type(elem_type) != nullptr;4712 get_codegen_ptr_type(elem_type) != nullptr;
4712}4713}
47134714
...@@ -4727,7 +4728,7 @@ ZigType *get_vector_type(CodeGen *g, uint32_t len, ZigType *elem_type) {...@@ -4727,7 +4728,7 @@ ZigType *get_vector_type(CodeGen *g, uint32_t len, ZigType *elem_type) {
47274728
4728 ZigType *entry = new_type_table_entry(ZigTypeIdVector);4729 ZigType *entry = new_type_table_entry(ZigTypeIdVector);
4729 if ((len != 0) && type_has_bits(elem_type)) {4730 if ((len != 0) && type_has_bits(elem_type)) {
4730 // Vectors can only be ints, floats, or pointers. ints and floats have trivially resolvable4731 // Vectors can only be ints, floats, bools, or pointers. ints (inc. bools) and floats have trivially resolvable
4731 // llvm type refs. pointers we will use usize instead.4732 // llvm type refs. pointers we will use usize instead.
4732 LLVMTypeRef example_vector_llvm_type;4733 LLVMTypeRef example_vector_llvm_type;
4733 if (elem_type->id == ZigTypeIdPointer) {4734 if (elem_type->id == ZigTypeIdPointer) {
src/codegen.cpp+18-10
...@@ -5549,10 +5549,14 @@ static LLVMValueRef ir_render_vector_to_array(CodeGen *g, IrExecutable *executab...@@ -5549,10 +5549,14 @@ 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 casted_ptr = LLVMBuildBitCast(g->builder, result_loc,5552 LLVMValueRef array = LLVMGetUndef(get_llvm_type(g, array_type));
5553 LLVMPointerType(get_llvm_type(g, instruction->vector->value.type), 0), "");5553 for (uintptr_t i = 0; i < instruction->vector->value.type->data.vector.len; i++) {
5554 uint32_t alignment = get_ptr_align(g, instruction->result_loc->value.type);5554 LLVMValueRef index = LLVMConstInt(g->builtin_types.entry_u32->llvm_type, i, false);
5555 gen_store_untyped(g, vector, casted_ptr, alignment, false);5555 LLVMValueRef elem = LLVMBuildExtractElement(g->builder, vector,
5556 index, "vector_to_array");
5557 array = LLVMBuildInsertValue(g->builder, array, elem, i, "");
5558 }
5559 LLVMBuildStore(g->builder, array, result_loc);
5556 return result_loc;5560 return result_loc;
5557}5561}
55585562
...@@ -5563,12 +5567,16 @@ static LLVMValueRef ir_render_array_to_vector(CodeGen *g, IrExecutable *executab...@@ -5563,12 +5567,16 @@ static LLVMValueRef ir_render_array_to_vector(CodeGen *g, IrExecutable *executab
5563 assert(vector_type->id == ZigTypeIdVector);5567 assert(vector_type->id == ZigTypeIdVector);
5564 assert(!handle_is_ptr(vector_type));5568 assert(!handle_is_ptr(vector_type));
5565 LLVMValueRef array_ptr = ir_llvm_value(g, instruction->array);5569 LLVMValueRef array_ptr = ir_llvm_value(g, instruction->array);
5566 LLVMValueRef casted_ptr = LLVMBuildBitCast(g->builder, array_ptr,5570 LLVMValueRef array = LLVMBuildLoad2(g->builder, get_llvm_type(g, instruction->array->value.type),
5567 LLVMPointerType(get_llvm_type(g, vector_type), 0), "");5571 array_ptr, "");
5568 ZigType *array_type = instruction->array->value.type;5572 LLVMValueRef vector = LLVMGetUndef(get_llvm_type(g, vector_type));
5569 assert(array_type->id == ZigTypeIdArray);5573 for (uintptr_t i = 0; i < instruction->base.value.type->data.vector.len; i++) {
5570 uint32_t alignment = get_abi_alignment(g, array_type->data.array.child_type);5574 LLVMValueRef index = LLVMConstInt(g->builtin_types.entry_u32->llvm_type, i, false);
5571 return gen_load_untyped(g, casted_ptr, alignment, false, "");5575 LLVMValueRef elem = LLVMBuildExtractValue(g->builder, array,
5576 i, "vector_to_array");
5577 vector = LLVMBuildInsertElement(g->builder, vector, elem, index, "");
5578 }
5579 return vector;
5572}5580}
55735581
5574static LLVMValueRef ir_render_assert_zero(CodeGen *g, IrExecutable *executable,5582static LLVMValueRef ir_render_assert_zero(CodeGen *g, IrExecutable *executable,
src/ir.cpp+1-1
...@@ -22024,7 +22024,7 @@ static IrInstruction *ir_analyze_instruction_vector_type(IrAnalyze *ira, IrInstr...@@ -22024,7 +22024,7 @@ static IrInstruction *ir_analyze_instruction_vector_type(IrAnalyze *ira, IrInstr
2202422024
22025 if (!is_valid_vector_elem_type(elem_type)) {22025 if (!is_valid_vector_elem_type(elem_type)) {
22026 ir_add_error(ira, instruction->elem_type,22026 ir_add_error(ira, instruction->elem_type,
22027 buf_sprintf("vector element type must be integer, float, or pointer; '%s' is invalid",22027 buf_sprintf("vector element type must be integer, float, bool, or pointer; '%s' is invalid",
22028 buf_ptr(&elem_type->name)));22028 buf_ptr(&elem_type->name)));
22029 return ira->codegen->invalid_instruction;22029 return ira->codegen->invalid_instruction;
22030 }22030 }
test/compile_errors.zig+1-1
...@@ -6491,7 +6491,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -6491,7 +6491,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
6491 \\ var v: V = undefined;6491 \\ var v: V = undefined;
6492 \\}6492 \\}
6493 ,6493 ,
6494 "tmp.zig:2:26: error: vector element type must be integer, float, or pointer; '@Vector(4, u8)' is invalid",6494 "tmp.zig:2:26: error: vector element type must be integer, float, bool, or pointer; '@Vector(4, u8)' is invalid",
6495 );6495 );
64966496
6497 cases.add("compileLog of tagged enum doesn't crash the compiler",6497 cases.add("compileLog of tagged enum doesn't crash the compiler",
test/stage1/behavior/vector.zig+41
...@@ -2,6 +2,18 @@ const std = @import("std");...@@ -2,6 +2,18 @@ const std = @import("std");
2const mem = std.mem;2const mem = std.mem;
3const expect = std.testing.expect;3const expect = std.testing.expect;
44
5test "implicit cast vector to array - bool" {
6 const S = struct {
7 fn doTheTest() void {
8 const a: @Vector(4, bool) = [_]bool{ true, false, true, false };
9 const result_array: [4]bool = a;
10 expect(mem.eql(bool, result_array, [4]bool{ true, false, true, false }));
11 }
12 };
13 S.doTheTest();
14 comptime S.doTheTest();
15}
16
5test "vector wrap operators" {17test "vector wrap operators" {
6 const S = struct {18 const S = struct {
7 fn doTheTest() void {19 fn doTheTest() void {
...@@ -80,3 +92,32 @@ test "array to vector" {...@@ -80,3 +92,32 @@ test "array to vector" {
80 var arr = [4]f32{ foo, 1.5, 0.0, 0.0 };92 var arr = [4]f32{ foo, 1.5, 0.0, 0.0 };
81 var vec: @Vector(4, f32) = arr;93 var vec: @Vector(4, f32) = arr;
82}94}
95
96test "vector casts of sizes not divisable by 8" {
97 const S = struct {
98 fn doTheTest() void {
99 {
100 var v: @Vector(4, u3) = [4]u3{ 5, 2, 3, 0};
101 var x: [4]u3 = v;
102 expect(mem.eql(u3, x, ([4]u3)(v)));
103 }
104 {
105 var v: @Vector(4, u2) = [4]u2{ 1, 2, 3, 0};
106 var x: [4]u2 = v;
107 expect(mem.eql(u2, x, ([4]u2)(v)));
108 }
109 {
110 var v: @Vector(4, u1) = [4]u1{ 1, 0, 1, 0};
111 var x: [4]u1 = v;
112 expect(mem.eql(u1, x, ([4]u1)(v)));
113 }
114 {
115 var v: @Vector(4, bool) = [4]bool{ false, false, true, false};
116 var x: [4]bool = v;
117 expect(mem.eql(bool, x, ([4]bool)(v)));
118 }
119 }
120 };
121 S.doTheTest();
122 comptime S.doTheTest();
123}