diff options
| author | Andrew Kelley <andrew@ziglang.org> | 2021-10-17 21:59:10 -0400 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2021-10-17 21:59:10 -0400 |
| commit | ad17108bddc3bc198190407ab5b00820b2c17cd5 (patch) | |
| tree | b59e6657f6350aefe8a67631d8398ba584a9717e /src/Sema.zig | |
| parent | e9d1e5e533d12abe14582736d90e4cb173addc56 (diff) | |
| parent | 15a0b30d8e905a7b46fa97175d9bdba2bd5a8403 (diff) | |
| download | zig-ad17108bddc3bc198190407ab5b00820b2c17cd5.tar.gz zig-ad17108bddc3bc198190407ab5b00820b2c17cd5.zip | |
Merge pull request #9960 from Snektron/bit-not
Some not and vector stuff
Diffstat (limited to 'src/Sema.zig')
| -rw-r--r-- | src/Sema.zig | 102 |
1 files changed, 72 insertions, 30 deletions
diff --git a/src/Sema.zig b/src/Sema.zig index cfc541453a..2211e69fb0 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -6629,8 +6629,42 @@ fn zirBitNot(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air. const tracy = trace(@src()); defer tracy.end(); - _ = inst; - return sema.fail(block, sema.src, "TODO implement zirBitNot", .{}); + const inst_data = sema.code.instructions.items(.data)[inst].un_node; + const src = inst_data.src(); + const operand_src = src; // TODO put this on the operand, not the '~' + + const operand = sema.resolveInst(inst_data.operand); + const operand_type = sema.typeOf(operand); + const scalar_type = operand_type.scalarType(); + + if (scalar_type.zigTypeTag() != .Int) { + return sema.fail(block, src, "unable to perform binary not operation on type '{}'", .{operand_type}); + } + + if (try sema.resolveMaybeUndefVal(block, operand_src, operand)) |val| { + const target = sema.mod.getTarget(); + if (val.isUndef()) { + return sema.addConstUndef(scalar_type); + } else if (operand_type.zigTypeTag() == .Vector) { + const vec_len = operand_type.arrayLen(); + var elem_val_buf: Value.ElemValueBuffer = undefined; + const elems = try sema.arena.alloc(Value, vec_len); + for (elems) |*elem, i| { + const elem_val = val.elemValueBuffer(i, &elem_val_buf); + elem.* = try elem_val.bitwiseNot(scalar_type, sema.arena, target); + } + return sema.addConstant( + operand_type, + try Value.Tag.array.create(sema.arena, elems), + ); + } else { + const result_val = try val.bitwiseNot(scalar_type, sema.arena, target); + return sema.addConstant(scalar_type, result_val); + } + } + + try sema.requireRuntimeBlock(block, src); + return block.addTyOp(.not, operand_type, operand); } fn zirArrayCat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { @@ -8239,12 +8273,13 @@ fn zirBoolNot(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air const bool_type = Type.initTag(.bool); const operand = try sema.coerce(block, bool_type, uncasted_operand, operand_src); - if (try sema.resolveDefinedValue(block, operand_src, operand)) |val| { - if (val.toBool()) { - return Air.Inst.Ref.bool_false; - } else { - return Air.Inst.Ref.bool_true; - } + if (try sema.resolveMaybeUndefVal(block, operand_src, operand)) |val| { + return if (val.isUndef()) + sema.addConstUndef(bool_type) + else if (val.toBool()) + Air.Inst.Ref.bool_false + else + Air.Inst.Ref.bool_true; } try sema.requireRuntimeBlock(block, src); return block.addTyOp(.not, bool_type, operand); @@ -11640,7 +11675,11 @@ fn coerce( else => {}, }, .Array => switch (inst_ty.zigTypeTag()) { - .Vector => return sema.coerceVectorToArray(block, dest_ty, dest_ty_src, inst, inst_src), + .Vector => return sema.coerceVectorInMemory(block, dest_ty, dest_ty_src, inst, inst_src), + else => {}, + }, + .Vector => switch (inst_ty.zigTypeTag()) { + .Array => return sema.coerceVectorInMemory(block, dest_ty, dest_ty_src, inst, inst_src), else => {}, }, else => {}, @@ -12224,46 +12263,49 @@ fn coerceEnumToUnion( return sema.failWithOwnedErrorMsg(msg); } -fn coerceVectorToArray( +// Coerces vectors/arrays which have the same in-memory layout. This can be used for +// both coercing from and to vectors. +fn coerceVectorInMemory( sema: *Sema, block: *Block, - array_ty: Type, - array_ty_src: LazySrcLoc, - vector: Air.Inst.Ref, - vector_src: LazySrcLoc, + dest_ty: Type, + dest_ty_src: LazySrcLoc, + inst: Air.Inst.Ref, + inst_src: LazySrcLoc, ) !Air.Inst.Ref { - const vector_ty = sema.typeOf(vector); - const array_len = array_ty.arrayLen(); - const vector_len = vector_ty.arrayLen(); - if (array_len != vector_len) { + const inst_ty = sema.typeOf(inst); + const inst_len = inst_ty.arrayLen(); + const dest_len = dest_ty.arrayLen(); + + if (dest_len != inst_len) { const msg = msg: { - const msg = try sema.errMsg(block, vector_src, "expected {}, found {}", .{ - array_ty, vector_ty, + const msg = try sema.errMsg(block, inst_src, "expected {}, found {}", .{ + dest_ty, inst_ty, }); errdefer msg.destroy(sema.gpa); - try sema.errNote(block, array_ty_src, msg, "array has length {d}", .{array_len}); - try sema.errNote(block, vector_src, msg, "vector has length {d}", .{vector_len}); + try sema.errNote(block, dest_ty_src, msg, "destination has length {d}", .{dest_len}); + try sema.errNote(block, inst_src, msg, "source has length {d}", .{inst_len}); break :msg msg; }; return sema.failWithOwnedErrorMsg(msg); } const target = sema.mod.getTarget(); - const array_elem_ty = array_ty.childType(); - const vector_elem_ty = vector_ty.childType(); - const in_memory_result = coerceInMemoryAllowed(array_elem_ty, vector_elem_ty, false, target); + const dest_elem_ty = dest_ty.childType(); + const inst_elem_ty = inst_ty.childType(); + const in_memory_result = coerceInMemoryAllowed(dest_elem_ty, inst_elem_ty, false, target); if (in_memory_result != .ok) { // TODO recursive error notes for coerceInMemoryAllowed failure - return sema.fail(block, vector_src, "expected {}, found {}", .{ array_ty, vector_ty }); + return sema.fail(block, inst_src, "expected {}, found {}", .{ dest_ty, inst_ty }); } - if (try sema.resolveMaybeUndefVal(block, vector_src, vector)) |vector_val| { + if (try sema.resolveMaybeUndefVal(block, inst_src, inst)) |inst_val| { // These types share the same comptime value representation. - return sema.addConstant(array_ty, vector_val); + return sema.addConstant(dest_ty, inst_val); } - try sema.requireRuntimeBlock(block, vector_src); - return block.addTyOp(.bitcast, array_ty, vector); + try sema.requireRuntimeBlock(block, inst_src); + return block.addTyOp(.bitcast, dest_ty, inst); } fn coerceCompatibleErrorSets( |
