aboutsummaryrefslogtreecommitdiff
path: root/src/codegen/llvm.zig
diff options
context:
space:
mode:
authorRobin Voetter <robin@voetter.nl>2021-10-16 17:23:30 +0200
committerRobin Voetter <robin@voetter.nl>2021-10-17 20:33:04 +0200
commitd193ba9843324dcaf239220df8db63ebe3adf67e (patch)
treed90845ee6808df06d314325e9e85b4395bd8b454 /src/codegen/llvm.zig
parent9336a87452eda87c19cb707484d0b6dfb4140b57 (diff)
downloadzig-d193ba9843324dcaf239220df8db63ebe3adf67e.tar.gz
zig-d193ba9843324dcaf239220df8db63ebe3adf67e.zip
stage2: array->vector coercion
Diffstat (limited to 'src/codegen/llvm.zig')
-rw-r--r--src/codegen/llvm.zig37
1 files changed, 37 insertions, 0 deletions
diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig
index 4349fce4d9..70442729ba 100644
--- a/src/codegen/llvm.zig
+++ b/src/codegen/llvm.zig
@@ -2889,6 +2889,43 @@ pub const FuncGen = struct {
}
}
return array_ptr;
+ } else if (operand_ty.zigTypeTag() == .Array and inst_ty.zigTypeTag() == .Vector) {
+ const target = self.dg.module.getTarget();
+ const elem_ty = operand_ty.childType();
+ const llvm_vector_ty = try self.dg.llvmType(inst_ty);
+ if (!isByRef(operand_ty)) {
+ return self.dg.todo("implement bitcast non-ref array to vector", .{});
+ }
+
+ const bitcast_ok = elem_ty.bitSize(target) == elem_ty.abiSize(target) * 8;
+ if (bitcast_ok) {
+ const llvm_vector_ptr_ty = llvm_vector_ty.pointerType(0);
+ const casted_ptr = self.builder.buildBitCast(operand, llvm_vector_ptr_ty, "");
+ const vector = self.builder.buildLoad(casted_ptr, "");
+ // The array is aligned to the element's alignment, while the vector might have a completely
+ // different alignment. This means we need to enforce the alignment of this load.
+ vector.setAlignment(elem_ty.abiAlignment(target));
+ return vector;
+ } else {
+ // If the ABI size of the element type is not evenly divisible by size in bits;
+ // a simple bitcast will not work, and we fall back to extractelement.
+ const llvm_usize = try self.dg.llvmType(Type.usize);
+ const llvm_u32 = self.context.intType(32);
+ const zero = llvm_usize.constNull();
+ const vector_len = operand_ty.arrayLen();
+ var vector = llvm_vector_ty.getUndef();
+ var i: u64 = 0;
+ while (i < vector_len) : (i += 1) {
+ const index_usize = llvm_usize.constInt(i, .False);
+ const index_u32 = llvm_u32.constInt(i, .False);
+ const indexes: [2]*const llvm.Value = .{ zero, index_usize };
+ const elem_ptr = self.builder.buildInBoundsGEP(operand, &indexes, indexes.len, "");
+ const elem = self.builder.buildLoad(elem_ptr, "");
+ vector = self.builder.buildInsertElement(vector, elem, index_u32, "");
+ }
+
+ return vector;
+ }
}
return self.builder.buildBitCast(operand, llvm_dest_ty, "");