stage2: check address space cast validity

This commit is contained in:
Robin Voetter 2022-08-27 12:55:28 +02:00
parent 5d429b03e3
commit 9f14681473
No known key found for this signature in database
GPG Key ID: E755662F227CB468
3 changed files with 41 additions and 3 deletions

View File

@ -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,

View File

@ -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, .{

View File

@ -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",