diff options
| author | Veikka Tuominen <git@vexu.eu> | 2023-01-27 20:25:48 +0200 |
|---|---|---|
| committer | Veikka Tuominen <git@vexu.eu> | 2023-01-30 18:55:57 +0200 |
| commit | f16c10a86b7183e99e54a70344f4681211cd52bb (patch) | |
| tree | aa6c1f3510696eb5ee63dd4ddb17c96cc6dce45b /src | |
| parent | fe4ea31f7e9e1c8caea6a1df107b91e8ea1a7b8a (diff) | |
| download | zig-f16c10a86b7183e99e54a70344f4681211cd52bb.tar.gz zig-f16c10a86b7183e99e54a70344f4681211cd52bb.zip | |
implement `@qualCast`
Diffstat (limited to 'src')
| -rw-r--r-- | src/AstGen.zig | 2 | ||||
| -rw-r--r-- | src/BuiltinFn.zig | 8 | ||||
| -rw-r--r-- | src/Sema.zig | 62 | ||||
| -rw-r--r-- | src/Zir.zig | 6 | ||||
| -rw-r--r-- | src/print_zir.zig | 1 |
5 files changed, 77 insertions, 2 deletions
diff --git a/src/AstGen.zig b/src/AstGen.zig index df111906e6..a5667ce9e8 100644 --- a/src/AstGen.zig +++ b/src/AstGen.zig @@ -2530,6 +2530,7 @@ fn addEnsureResult(gz: *GenZir, maybe_unused_result: Zir.Inst.Ref, statement: As .bit_size_of, .typeof_log2_int_type, .ptr_to_int, + .qual_cast, .align_of, .bool_to_int, .embed_file, @@ -8037,6 +8038,7 @@ fn builtinCall( .float_cast => return typeCast(gz, scope, ri, node, params[0], params[1], .float_cast), .int_cast => return typeCast(gz, scope, ri, node, params[0], params[1], .int_cast), .ptr_cast => return typeCast(gz, scope, ri, node, params[0], params[1], .ptr_cast), + .qual_cast => return typeCast(gz, scope, ri, node, params[0], params[1], .qual_cast), .truncate => return typeCast(gz, scope, ri, node, params[0], params[1], .truncate), // zig fmt: on diff --git a/src/BuiltinFn.zig b/src/BuiltinFn.zig index b71d96c3dd..80eb739185 100644 --- a/src/BuiltinFn.zig +++ b/src/BuiltinFn.zig @@ -75,6 +75,7 @@ pub const Tag = enum { prefetch, ptr_cast, ptr_to_int, + qual_cast, rem, return_address, select, @@ -675,6 +676,13 @@ pub const list = list: { }, }, .{ + "@qualCast", + .{ + .tag = .qual_cast, + .param_count = 2, + }, + }, + .{ "@rem", .{ .tag = .rem, diff --git a/src/Sema.zig b/src/Sema.zig index b4731d9509..d306c68e08 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -1015,6 +1015,7 @@ fn analyzeBodyInner( .float_cast => try sema.zirFloatCast(block, inst), .int_cast => try sema.zirIntCast(block, inst), .ptr_cast => try sema.zirPtrCast(block, inst), + .qual_cast => try sema.zirQualCast(block, inst), .truncate => try sema.zirTruncate(block, inst), .align_cast => try sema.zirAlignCast(block, inst), .has_decl => try sema.zirHasDecl(block, inst), @@ -19529,10 +19530,24 @@ fn zirPtrCast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air const operand_info = operand_ty.ptrInfo().data; const dest_info = dest_ty.ptrInfo().data; if (!operand_info.mutable and dest_info.mutable) { - return sema.fail(block, src, "cast discards const qualifier", .{}); + const msg = msg: { + const msg = try sema.errMsg(block, src, "cast discards const qualifier", .{}); + errdefer msg.destroy(sema.gpa); + + try sema.errNote(block, src, msg, "consider using '@qualCast'", .{}); + break :msg msg; + }; + return sema.failWithOwnedErrorMsg(msg); } if (operand_info.@"volatile" and !dest_info.@"volatile") { - return sema.fail(block, src, "cast discards volatile qualifier", .{}); + const msg = msg: { + const msg = try sema.errMsg(block, src, "cast discards volatile qualifier", .{}); + errdefer msg.destroy(sema.gpa); + + try sema.errNote(block, src, msg, "consider using '@qualCast'", .{}); + break :msg msg; + }; + return sema.failWithOwnedErrorMsg(msg); } if (operand_info.@"addrspace" != dest_info.@"addrspace") { const msg = msg: { @@ -19634,6 +19649,49 @@ fn zirPtrCast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air return block.addBitCast(aligned_dest_ty, ptr); } +fn zirQualCast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { + const inst_data = sema.code.instructions.items(.data)[inst].pl_node; + const src = inst_data.src(); + const dest_ty_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node }; + const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg1 = inst_data.src_node }; + const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data; + const dest_ty = try sema.resolveType(block, dest_ty_src, extra.lhs); + const operand = try sema.resolveInst(extra.rhs); + const operand_ty = sema.typeOf(operand); + + try sema.checkPtrType(block, dest_ty_src, dest_ty); + try sema.checkPtrOperand(block, operand_src, operand_ty); + + var operand_payload = operand_ty.ptrInfo(); + var dest_info = dest_ty.ptrInfo(); + + operand_payload.data.mutable = dest_info.data.mutable; + operand_payload.data.@"volatile" = dest_info.data.@"volatile"; + + const altered_operand_ty = Type.initPayload(&operand_payload.base); + if (!altered_operand_ty.eql(dest_ty, sema.mod)) { + const msg = msg: { + const msg = try sema.errMsg(block, src, "'@qualCast' can only modify 'const' and 'volatile' qualifiers", .{}); + errdefer msg.destroy(sema.gpa); + + dest_info.data.mutable = !operand_ty.isConstPtr(); + dest_info.data.@"volatile" = operand_ty.isVolatilePtr(); + const altered_dest_ty = Type.initPayload(&dest_info.base); + try sema.errNote(block, src, msg, "expected type '{}'", .{altered_dest_ty.fmt(sema.mod)}); + try sema.errNote(block, src, msg, "got type '{}'", .{operand_ty.fmt(sema.mod)}); + break :msg msg; + }; + return sema.failWithOwnedErrorMsg(msg); + } + + if (try sema.resolveMaybeUndefVal(operand)) |operand_val| { + return sema.addConstant(dest_ty, operand_val); + } + + try sema.requireRuntimeBlock(block, src, null); + return block.addBitCast(dest_ty, operand); +} + fn zirTruncate(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { const inst_data = sema.code.instructions.items(.data)[inst].pl_node; const src = inst_data.src(); diff --git a/src/Zir.zig b/src/Zir.zig index 94e6a9a11a..b93422177e 100644 --- a/src/Zir.zig +++ b/src/Zir.zig @@ -857,6 +857,9 @@ pub const Inst = struct { /// Implements the `@ptrCast` builtin. /// Uses `pl_node` with payload `Bin`. `lhs` is dest type, `rhs` is operand. ptr_cast, + /// Implements the `@qualCast` builtin. + /// Uses `pl_node` with payload `Bin`. `lhs` is dest type, `rhs` is operand. + qual_cast, /// Implements the `@truncate` builtin. /// Uses `pl_node` with payload `Bin`. `lhs` is dest type, `rhs` is operand. truncate, @@ -1195,6 +1198,7 @@ pub const Inst = struct { .float_cast, .int_cast, .ptr_cast, + .qual_cast, .truncate, .align_cast, .has_field, @@ -1484,6 +1488,7 @@ pub const Inst = struct { .float_cast, .int_cast, .ptr_cast, + .qual_cast, .truncate, .align_cast, .has_field, @@ -1755,6 +1760,7 @@ pub const Inst = struct { .float_cast = .pl_node, .int_cast = .pl_node, .ptr_cast = .pl_node, + .qual_cast = .pl_node, .truncate = .pl_node, .align_cast = .pl_node, .typeof_builtin = .pl_node, diff --git a/src/print_zir.zig b/src/print_zir.zig index 6e8923bed9..e5fc8815ed 100644 --- a/src/print_zir.zig +++ b/src/print_zir.zig @@ -332,6 +332,7 @@ const Writer = struct { .float_cast, .int_cast, .ptr_cast, + .qual_cast, .truncate, .align_cast, .div_exact, |
