Commit 0e3ca4c63e
Changed files (5)
test
stage1
behavior
src/analyze.cpp
@@ -4708,6 +4708,7 @@ ZigType *get_int_type(CodeGen *g, bool is_signed, uint32_t size_in_bits) {
bool is_valid_vector_elem_type(ZigType *elem_type) {
return elem_type->id == ZigTypeIdInt ||
elem_type->id == ZigTypeIdFloat ||
+ elem_type->id == ZigTypeIdBool ||
get_codegen_ptr_type(elem_type) != nullptr;
}
@@ -4727,7 +4728,7 @@ ZigType *get_vector_type(CodeGen *g, uint32_t len, ZigType *elem_type) {
ZigType *entry = new_type_table_entry(ZigTypeIdVector);
if ((len != 0) && type_has_bits(elem_type)) {
- // Vectors can only be ints, floats, or pointers. ints and floats have trivially resolvable
+ // Vectors can only be ints, floats, bools, or pointers. ints (inc. bools) and floats have trivially resolvable
// llvm type refs. pointers we will use usize instead.
LLVMTypeRef example_vector_llvm_type;
if (elem_type->id == ZigTypeIdPointer) {
src/codegen.cpp
@@ -5549,10 +5549,14 @@ static LLVMValueRef ir_render_vector_to_array(CodeGen *g, IrExecutable *executab
assert(handle_is_ptr(array_type));
LLVMValueRef result_loc = ir_llvm_value(g, instruction->result_loc);
LLVMValueRef vector = ir_llvm_value(g, instruction->vector);
- LLVMValueRef casted_ptr = LLVMBuildBitCast(g->builder, result_loc,
- LLVMPointerType(get_llvm_type(g, instruction->vector->value.type), 0), "");
- uint32_t alignment = get_ptr_align(g, instruction->result_loc->value.type);
- gen_store_untyped(g, vector, casted_ptr, alignment, false);
+ LLVMValueRef array = LLVMGetUndef(get_llvm_type(g, array_type));
+ for (uintptr_t i = 0; i < instruction->vector->value.type->data.vector.len; i++) {
+ LLVMValueRef index = LLVMConstInt(g->builtin_types.entry_u32->llvm_type, i, false);
+ LLVMValueRef elem = LLVMBuildExtractElement(g->builder, vector,
+ index, "vector_to_array");
+ array = LLVMBuildInsertValue(g->builder, array, elem, i, "");
+ }
+ LLVMBuildStore(g->builder, array, result_loc);
return result_loc;
}
@@ -5563,12 +5567,16 @@ static LLVMValueRef ir_render_array_to_vector(CodeGen *g, IrExecutable *executab
assert(vector_type->id == ZigTypeIdVector);
assert(!handle_is_ptr(vector_type));
LLVMValueRef array_ptr = ir_llvm_value(g, instruction->array);
- LLVMValueRef casted_ptr = LLVMBuildBitCast(g->builder, array_ptr,
- LLVMPointerType(get_llvm_type(g, vector_type), 0), "");
- ZigType *array_type = instruction->array->value.type;
- assert(array_type->id == ZigTypeIdArray);
- uint32_t alignment = get_abi_alignment(g, array_type->data.array.child_type);
- return gen_load_untyped(g, casted_ptr, alignment, false, "");
+ LLVMValueRef array = LLVMBuildLoad2(g->builder, get_llvm_type(g, instruction->array->value.type),
+ array_ptr, "");
+ LLVMValueRef vector = LLVMGetUndef(get_llvm_type(g, vector_type));
+ for (uintptr_t i = 0; i < instruction->base.value.type->data.vector.len; i++) {
+ LLVMValueRef index = LLVMConstInt(g->builtin_types.entry_u32->llvm_type, i, false);
+ LLVMValueRef elem = LLVMBuildExtractValue(g->builder, array,
+ i, "vector_to_array");
+ vector = LLVMBuildInsertElement(g->builder, vector, elem, index, "");
+ }
+ return vector;
}
static LLVMValueRef ir_render_assert_zero(CodeGen *g, IrExecutable *executable,
src/ir.cpp
@@ -22024,7 +22024,7 @@ static IrInstruction *ir_analyze_instruction_vector_type(IrAnalyze *ira, IrInstr
if (!is_valid_vector_elem_type(elem_type)) {
ir_add_error(ira, instruction->elem_type,
- buf_sprintf("vector element type must be integer, float, or pointer; '%s' is invalid",
+ buf_sprintf("vector element type must be integer, float, bool, or pointer; '%s' is invalid",
buf_ptr(&elem_type->name)));
return ira->codegen->invalid_instruction;
}
test/stage1/behavior/vector.zig
@@ -2,6 +2,18 @@ const std = @import("std");
const mem = std.mem;
const expect = std.testing.expect;
+test "implicit cast vector to array - bool" {
+ const S = struct {
+ fn doTheTest() void {
+ const a: @Vector(4, bool) = [_]bool{ true, false, true, false };
+ const result_array: [4]bool = a;
+ expect(mem.eql(bool, result_array, [4]bool{ true, false, true, false }));
+ }
+ };
+ S.doTheTest();
+ comptime S.doTheTest();
+}
+
test "vector wrap operators" {
const S = struct {
fn doTheTest() void {
@@ -80,3 +92,32 @@ test "array to vector" {
var arr = [4]f32{ foo, 1.5, 0.0, 0.0 };
var vec: @Vector(4, f32) = arr;
}
+
+test "vector casts of sizes not divisable by 8" {
+ const S = struct {
+ fn doTheTest() void {
+ {
+ var v: @Vector(4, u3) = [4]u3{ 5, 2, 3, 0};
+ var x: [4]u3 = v;
+ expect(mem.eql(u3, x, ([4]u3)(v)));
+ }
+ {
+ var v: @Vector(4, u2) = [4]u2{ 1, 2, 3, 0};
+ var x: [4]u2 = v;
+ expect(mem.eql(u2, x, ([4]u2)(v)));
+ }
+ {
+ var v: @Vector(4, u1) = [4]u1{ 1, 0, 1, 0};
+ var x: [4]u1 = v;
+ expect(mem.eql(u1, x, ([4]u1)(v)));
+ }
+ {
+ var v: @Vector(4, bool) = [4]bool{ false, false, true, false};
+ var x: [4]bool = v;
+ expect(mem.eql(bool, x, ([4]bool)(v)));
+ }
+ }
+ };
+ S.doTheTest();
+ comptime S.doTheTest();
+}
test/compile_errors.zig
@@ -6491,7 +6491,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
\\ var v: V = undefined;
\\}
,
- "tmp.zig:2:26: error: vector element type must be integer, float, or pointer; '@Vector(4, u8)' is invalid",
+ "tmp.zig:2:26: error: vector element type must be integer, float, bool, or pointer; '@Vector(4, u8)' is invalid",
);
cases.add("compileLog of tagged enum doesn't crash the compiler",