Commit 9f14681473
Changed files (3)
lib
std
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,
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, .{
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",