diff options
| author | Jacob Young <jacobly0@users.noreply.github.com> | 2024-02-15 10:37:52 +0100 |
|---|---|---|
| committer | Jacob Young <jacobly0@users.noreply.github.com> | 2024-02-25 11:22:10 +0100 |
| commit | 2fcb2f597549edd0b1241cebf98c11efe2f25884 (patch) | |
| tree | ebf6aca8e0c1d5c77874c2c05b0cccd0967d080f /src/Sema.zig | |
| parent | 2fdc9e6ae8b6f1ec86050011e1170d639d8c9c2c (diff) | |
| download | zig-2fcb2f597549edd0b1241cebf98c11efe2f25884.tar.gz zig-2fcb2f597549edd0b1241cebf98c11efe2f25884.zip | |
Sema: implement vector coercions
These used to be lowered elementwise in air, and now are a single air
instruction that can be lowered elementwise in the backend if necessary.
Diffstat (limited to 'src/Sema.zig')
| -rw-r--r-- | src/Sema.zig | 33 |
1 files changed, 31 insertions, 2 deletions
diff --git a/src/Sema.zig b/src/Sema.zig index 0a38cf93dc..e1a9f7ee65 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -23328,7 +23328,8 @@ fn checkVectorElemType( const mod = sema.mod; switch (ty.zigTypeTag(mod)) { .Int, .Float, .Bool => return, - else => if (ty.isPtrAtRuntime(mod)) return, + .Optional, .Pointer => if (ty.isPtrAtRuntime(mod)) return, + else => {}, } return sema.fail(block, ty_src, "expected integer, float, bool, or pointer for the vector element type; found '{}'", .{ty.fmt(mod)}); } @@ -28455,7 +28456,7 @@ const CoerceOpts = struct { report_err: bool = true, /// Ignored if `report_err == false`. is_ret: bool = false, - /// Should coercion to comptime_int ermit an error message. + /// Should coercion to comptime_int emit an error message. no_cast_to_comptime_int: bool = false, param_src: struct { @@ -31858,6 +31859,34 @@ fn coerceArrayLike( } const dest_elem_ty = dest_ty.childType(mod); + if (dest_ty.isVector(mod) and inst_ty.isVector(mod) and (try sema.resolveValue(inst)) == null) { + const inst_elem_ty = inst_ty.childType(mod); + switch (dest_elem_ty.zigTypeTag(mod)) { + .Int => if (inst_elem_ty.isInt(mod)) { + // integer widening + const dst_info = dest_elem_ty.intInfo(mod); + const src_info = inst_elem_ty.intInfo(mod); + if ((src_info.signedness == dst_info.signedness and dst_info.bits >= src_info.bits) or + // small enough unsigned ints can get casted to large enough signed ints + (dst_info.signedness == .signed and dst_info.bits > src_info.bits)) + { + try sema.requireRuntimeBlock(block, inst_src, null); + return block.addTyOp(.intcast, dest_ty, inst); + } + }, + .Float => if (inst_elem_ty.isRuntimeFloat()) { + // float widening + const src_bits = inst_elem_ty.floatBits(target); + const dst_bits = dest_elem_ty.floatBits(target); + if (dst_bits >= src_bits) { + try sema.requireRuntimeBlock(block, inst_src, null); + return block.addTyOp(.fpext, dest_ty, inst); + } + }, + else => {}, + } + } + const element_vals = try sema.arena.alloc(InternPool.Index, dest_len); const element_refs = try sema.arena.alloc(Air.Inst.Ref, dest_len); var runtime_src: ?LazySrcLoc = null; |
