From 9f14681473140cd79e6d38cb2bb46a90c1be1259 Mon Sep 17 00:00:00 2001 From: Robin Voetter Date: Sat, 27 Aug 2022 12:55:28 +0200 Subject: [PATCH] stage2: check address space cast validity --- lib/std/target.zig | 11 +++++++++++ src/Sema.zig | 12 ++++++++++-- src/target.zig | 21 ++++++++++++++++++++- 3 files changed, 41 insertions(+), 3 deletions(-) diff --git a/lib/std/target.zig b/lib/std/target.zig index b6a8a8b9c0..139df629c5 100644 --- a/lib/std/target.zig +++ b/lib/std/target.zig @@ -1157,6 +1157,17 @@ pub const Target = struct { }; } + /// Returns whether this architecture supporst the address space + pub fn supportsAddressSpace(arch: Arch, address_space: std.builtin.AddressSpace) bool { + const is_nvptx = arch == .nvptx or arch == .nvptx64; + return switch (address_space) { + .generic => true, + .fs, .gs, .ss => arch == .x86_64 or arch == .i386, + .global, .constant, .local, .shared => arch == .amdgcn or is_nvptx, + .param => is_nvptx, + }; + } + pub fn ptrBitWidth(arch: Arch) u16 { switch (arch) { .avr, diff --git a/src/Sema.zig b/src/Sema.zig index 9a6c2acb14..9d05d53536 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -18181,13 +18181,21 @@ fn zirAddrSpaceCast(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.Inst const ptr = try sema.resolveInst(extra.rhs); const ptr_ty = sema.typeOf(ptr); + // TODO in addition to pointers, this instruction is supposed to work for // pointer-like optionals and slices. try sema.checkPtrOperand(block, ptr_src, ptr_ty); - // TODO check address space cast validity. const src_addrspace = ptr_ty.ptrAddressSpace(); - _ = src_addrspace; + if (!target_util.addrSpaceCastIsValid(sema.mod.getTarget(), src_addrspace, dest_addrspace)) { + const msg = msg: { + const msg = try sema.errMsg(block, src, "invalid address space cast", .{}); + errdefer msg.destroy(sema.gpa); + try sema.errNote(block, src, msg, "address space '{s}' is not compatible with address space '{s}'", .{ @tagName(src_addrspace), @tagName(dest_addrspace) }); + break :msg msg; + }; + return sema.failWithOwnedErrorMsg(msg); + } const ptr_info = ptr_ty.ptrInfo().data; const dest_ty = try Type.ptr(sema.arena, sema.mod, .{ diff --git a/src/target.zig b/src/target.zig index b7da04e548..3fbaf6abc4 100644 --- a/src/target.zig +++ b/src/target.zig @@ -1,5 +1,6 @@ const std = @import("std"); const Type = @import("type.zig").Type; +const AddressSpace = std.builtin.AddressSpace; pub const ArchOsAbi = struct { arch: std.Target.Cpu.Arch, @@ -635,12 +636,30 @@ pub fn defaultAddressSpace( /// Query the default address space for functions themselves. function, }, -) std.builtin.AddressSpace { +) AddressSpace { _ = target; _ = context; return .generic; } +/// Returns true if pointers in `from` can be converted to a pointer in `to`. +pub fn addrSpaceCastIsValid( + target: std.Target, + from: AddressSpace, + to: AddressSpace, +) bool { + const arch = target.cpu.arch; + switch (arch) { + .x86_64, .i386 => return arch.supportsAddressSpace(from) and arch.supportsAddressSpace(to), + .amdgcn => { + const to_generic = arch.supportsAddressSpace(from) and to == .generic; + const from_generic = arch.supportsAddressSpace(to) and from == .generic; + return to_generic or from_generic; + }, + else => return from == .generic and to == .generic, + } +} + pub fn llvmMachineAbi(target: std.Target) ?[:0]const u8 { const have_float = switch (target.abi) { .gnuilp32 => return "ilp32",