mirror of
https://github.com/ziglang/zig.git
synced 2026-02-13 21:08:36 +00:00
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.
This commit is contained in:
parent
914ad1ec2e
commit
0e3ca4c63e
@ -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) {
|
||||
|
||||
@ -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,
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -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",
|
||||
|
||||
@ -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();
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user