mirror of
https://codeberg.org/ziglang/zig.git
synced 2025-12-06 13:54:21 +00:00
stage2: add @addrSpaceCast builtin
This commit is contained in:
parent
5f3b91437f
commit
5d429b03e3
17 changed files with 99 additions and 4 deletions
|
|
@ -729,6 +729,10 @@ pub const Inst = struct {
|
||||||
/// Sets the operand as the current error return trace,
|
/// Sets the operand as the current error return trace,
|
||||||
set_err_return_trace,
|
set_err_return_trace,
|
||||||
|
|
||||||
|
/// Convert the address space of a pointer.
|
||||||
|
/// Uses the `ty_op` field.
|
||||||
|
addrspace_cast,
|
||||||
|
|
||||||
pub fn fromCmpOp(op: std.math.CompareOperator, optimized: bool) Tag {
|
pub fn fromCmpOp(op: std.math.CompareOperator, optimized: bool) Tag {
|
||||||
switch (op) {
|
switch (op) {
|
||||||
.lt => return if (optimized) .cmp_lt_optimized else .cmp_lt,
|
.lt => return if (optimized) .cmp_lt_optimized else .cmp_lt,
|
||||||
|
|
@ -1138,6 +1142,7 @@ pub fn typeOfIndex(air: Air, inst: Air.Inst.Index) Type {
|
||||||
.popcount,
|
.popcount,
|
||||||
.byte_swap,
|
.byte_swap,
|
||||||
.bit_reverse,
|
.bit_reverse,
|
||||||
|
.addrspace_cast,
|
||||||
=> return air.getRefType(datas[inst].ty_op.ty),
|
=> return air.getRefType(datas[inst].ty_op.ty),
|
||||||
|
|
||||||
.loop,
|
.loop,
|
||||||
|
|
|
||||||
|
|
@ -7789,6 +7789,14 @@ fn builtinCall(
|
||||||
});
|
});
|
||||||
return rvalue(gz, rl, result, node);
|
return rvalue(gz, rl, result, node);
|
||||||
},
|
},
|
||||||
|
.addrspace_cast => {
|
||||||
|
const result = try gz.addExtendedPayload(.addrspace_cast, Zir.Inst.BinNode{
|
||||||
|
.lhs = try comptimeExpr(gz, scope, .{ .ty = .address_space_type }, params[0]),
|
||||||
|
.rhs = try expr(gz, scope, .none, params[1]),
|
||||||
|
.node = gz.nodeIndexToRelative(node),
|
||||||
|
});
|
||||||
|
return rvalue(gz, rl, result, node);
|
||||||
|
},
|
||||||
|
|
||||||
// zig fmt: off
|
// zig fmt: off
|
||||||
.has_decl => return hasDeclOrField(gz, scope, rl, node, params[0], params[1], .has_decl),
|
.has_decl => return hasDeclOrField(gz, scope, rl, node, params[0], params[1], .has_decl),
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@ const std = @import("std");
|
||||||
|
|
||||||
pub const Tag = enum {
|
pub const Tag = enum {
|
||||||
add_with_overflow,
|
add_with_overflow,
|
||||||
|
addrspace_cast,
|
||||||
align_cast,
|
align_cast,
|
||||||
align_of,
|
align_of,
|
||||||
as,
|
as,
|
||||||
|
|
@ -152,6 +153,13 @@ pub const list = list: {
|
||||||
.param_count = 4,
|
.param_count = 4,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
.{
|
||||||
|
"@addrSpaceCast",
|
||||||
|
.{
|
||||||
|
.tag = .addrspace_cast,
|
||||||
|
.param_count = 2,
|
||||||
|
},
|
||||||
|
},
|
||||||
.{
|
.{
|
||||||
"@alignCast",
|
"@alignCast",
|
||||||
.{
|
.{
|
||||||
|
|
|
||||||
|
|
@ -268,6 +268,7 @@ pub fn categorizeOperand(
|
||||||
.bit_reverse,
|
.bit_reverse,
|
||||||
.splat,
|
.splat,
|
||||||
.error_set_has_value,
|
.error_set_has_value,
|
||||||
|
.addrspace_cast,
|
||||||
=> {
|
=> {
|
||||||
const o = air_datas[inst].ty_op;
|
const o = air_datas[inst].ty_op;
|
||||||
if (o.operand == operand_ref) return matchOperandSmallIndex(l, inst, 0, .none);
|
if (o.operand == operand_ref) return matchOperandSmallIndex(l, inst, 0, .none);
|
||||||
|
|
@ -844,6 +845,7 @@ fn analyzeInst(
|
||||||
.bit_reverse,
|
.bit_reverse,
|
||||||
.splat,
|
.splat,
|
||||||
.error_set_has_value,
|
.error_set_has_value,
|
||||||
|
.addrspace_cast,
|
||||||
=> {
|
=> {
|
||||||
const o = inst_datas[inst].ty_op;
|
const o = inst_datas[inst].ty_op;
|
||||||
return trackOperands(a, new_set, inst, main_tomb, .{ o.operand, .none, .none });
|
return trackOperands(a, new_set, inst, main_tomb, .{ o.operand, .none, .none });
|
||||||
|
|
|
||||||
|
|
@ -4617,7 +4617,7 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !bool {
|
||||||
.constant => target_util.defaultAddressSpace(target, .global_constant),
|
.constant => target_util.defaultAddressSpace(target, .global_constant),
|
||||||
else => unreachable,
|
else => unreachable,
|
||||||
},
|
},
|
||||||
else => |addrspace_ref| try sema.analyzeAddrspace(&block_scope, address_space_src, addrspace_ref, addrspace_ctx),
|
else => |addrspace_ref| try sema.analyzeAddressSpace(&block_scope, address_space_src, addrspace_ref, addrspace_ctx),
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
54
src/Sema.zig
54
src/Sema.zig
|
|
@ -975,8 +975,9 @@ fn analyzeBodyInner(
|
||||||
.reify => try sema.zirReify( block, extended, inst),
|
.reify => try sema.zirReify( block, extended, inst),
|
||||||
.builtin_async_call => try sema.zirBuiltinAsyncCall( block, extended),
|
.builtin_async_call => try sema.zirBuiltinAsyncCall( block, extended),
|
||||||
.cmpxchg => try sema.zirCmpxchg( block, extended),
|
.cmpxchg => try sema.zirCmpxchg( block, extended),
|
||||||
|
.addrspace_cast => try sema.zirAddrSpaceCast( block, extended),
|
||||||
// zig fmt: on
|
// zig fmt: on
|
||||||
|
|
||||||
.fence => {
|
.fence => {
|
||||||
try sema.zirFence(block, extended);
|
try sema.zirFence(block, extended);
|
||||||
i += 1;
|
i += 1;
|
||||||
|
|
@ -16250,7 +16251,7 @@ fn zirPtrType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
|
||||||
const address_space = if (inst_data.flags.has_addrspace) blk: {
|
const address_space = if (inst_data.flags.has_addrspace) blk: {
|
||||||
const ref = @intToEnum(Zir.Inst.Ref, sema.code.extra[extra_i]);
|
const ref = @intToEnum(Zir.Inst.Ref, sema.code.extra[extra_i]);
|
||||||
extra_i += 1;
|
extra_i += 1;
|
||||||
break :blk try sema.analyzeAddrspace(block, addrspace_src, ref, .pointer);
|
break :blk try sema.analyzeAddressSpace(block, addrspace_src, ref, .pointer);
|
||||||
} else .generic;
|
} else .generic;
|
||||||
|
|
||||||
const bit_offset = if (inst_data.flags.has_bit_range) blk: {
|
const bit_offset = if (inst_data.flags.has_bit_range) blk: {
|
||||||
|
|
@ -18170,6 +18171,53 @@ fn reifyStruct(
|
||||||
return sema.analyzeDeclVal(block, src, new_decl_index);
|
return sema.analyzeDeclVal(block, src, new_decl_index);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn zirAddrSpaceCast(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData) CompileError!Air.Inst.Ref {
|
||||||
|
const extra = sema.code.extraData(Zir.Inst.BinNode, extended.operand).data;
|
||||||
|
const src = LazySrcLoc.nodeOffset(extra.node);
|
||||||
|
const addrspace_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = extra.node };
|
||||||
|
const ptr_src: LazySrcLoc = .{ .node_offset_builtin_call_arg1 = extra.node };
|
||||||
|
|
||||||
|
const dest_addrspace = try sema.analyzeAddressSpace(block, addrspace_src, extra.lhs, .pointer);
|
||||||
|
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;
|
||||||
|
|
||||||
|
const ptr_info = ptr_ty.ptrInfo().data;
|
||||||
|
const dest_ty = try Type.ptr(sema.arena, sema.mod, .{
|
||||||
|
.pointee_type = ptr_info.pointee_type,
|
||||||
|
.@"align" = ptr_info.@"align",
|
||||||
|
.@"addrspace" = dest_addrspace,
|
||||||
|
.mutable = ptr_info.mutable,
|
||||||
|
.@"allowzero" = ptr_info.@"allowzero",
|
||||||
|
.@"volatile" = ptr_info.@"volatile",
|
||||||
|
.size = ptr_info.size,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (try sema.resolveMaybeUndefVal(block, ptr_src, ptr)) |val| {
|
||||||
|
// Pointer value should compatible with both address spaces.
|
||||||
|
// TODO: Figure out why this generates an invalid bitcast.
|
||||||
|
return sema.addConstant(dest_ty, val);
|
||||||
|
}
|
||||||
|
|
||||||
|
try sema.requireRuntimeBlock(block, src, ptr_src);
|
||||||
|
// TODO: Address space cast safety?
|
||||||
|
|
||||||
|
return block.addInst(.{
|
||||||
|
.tag = .addrspace_cast,
|
||||||
|
.data = .{ .ty_op = .{
|
||||||
|
.ty = try sema.addType(dest_ty),
|
||||||
|
.operand = ptr,
|
||||||
|
} },
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
fn zirTypeName(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
|
fn zirTypeName(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
|
||||||
const inst_data = sema.code.instructions.items(.data)[inst].un_node;
|
const inst_data = sema.code.instructions.items(.data)[inst].un_node;
|
||||||
const ty_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node };
|
const ty_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node };
|
||||||
|
|
@ -30292,7 +30340,7 @@ pub const AddressSpaceContext = enum {
|
||||||
pointer,
|
pointer,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub fn analyzeAddrspace(
|
pub fn analyzeAddressSpace(
|
||||||
sema: *Sema,
|
sema: *Sema,
|
||||||
block: *Block,
|
block: *Block,
|
||||||
src: LazySrcLoc,
|
src: LazySrcLoc,
|
||||||
|
|
|
||||||
|
|
@ -1969,6 +1969,9 @@ pub const Inst = struct {
|
||||||
/// `small` 0=>weak 1=>strong
|
/// `small` 0=>weak 1=>strong
|
||||||
/// `operand` is payload index to `Cmpxchg`.
|
/// `operand` is payload index to `Cmpxchg`.
|
||||||
cmpxchg,
|
cmpxchg,
|
||||||
|
/// Implement the builtin `@addrSpaceCast`
|
||||||
|
/// `Operand` is payload index to `BinNode`. `lhs` is dest type, `rhs` is operand.
|
||||||
|
addrspace_cast,
|
||||||
|
|
||||||
pub const InstData = struct {
|
pub const InstData = struct {
|
||||||
opcode: Extended,
|
opcode: Extended,
|
||||||
|
|
|
||||||
|
|
@ -677,6 +677,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
|
||||||
.union_init => try self.airUnionInit(inst),
|
.union_init => try self.airUnionInit(inst),
|
||||||
.prefetch => try self.airPrefetch(inst),
|
.prefetch => try self.airPrefetch(inst),
|
||||||
.mul_add => try self.airMulAdd(inst),
|
.mul_add => try self.airMulAdd(inst),
|
||||||
|
.addrspace_cast => return self.fail("TODO implement addrspace_cast", .{}),
|
||||||
|
|
||||||
.@"try" => try self.airTry(inst),
|
.@"try" => try self.airTry(inst),
|
||||||
.try_ptr => try self.airTryPtr(inst),
|
.try_ptr => try self.airTryPtr(inst),
|
||||||
|
|
|
||||||
|
|
@ -690,6 +690,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
|
||||||
.union_init => try self.airUnionInit(inst),
|
.union_init => try self.airUnionInit(inst),
|
||||||
.prefetch => try self.airPrefetch(inst),
|
.prefetch => try self.airPrefetch(inst),
|
||||||
.mul_add => try self.airMulAdd(inst),
|
.mul_add => try self.airMulAdd(inst),
|
||||||
|
.addrspace_cast => return self.fail("TODO implement addrspace_cast", .{}),
|
||||||
|
|
||||||
.@"try" => try self.airTry(inst),
|
.@"try" => try self.airTry(inst),
|
||||||
.try_ptr => try self.airTryPtr(inst),
|
.try_ptr => try self.airTryPtr(inst),
|
||||||
|
|
|
||||||
|
|
@ -604,6 +604,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
|
||||||
.union_init => try self.airUnionInit(inst),
|
.union_init => try self.airUnionInit(inst),
|
||||||
.prefetch => try self.airPrefetch(inst),
|
.prefetch => try self.airPrefetch(inst),
|
||||||
.mul_add => try self.airMulAdd(inst),
|
.mul_add => try self.airMulAdd(inst),
|
||||||
|
.addrspace_cast => @panic("TODO"),
|
||||||
|
|
||||||
.@"try" => @panic("TODO"),
|
.@"try" => @panic("TODO"),
|
||||||
.try_ptr => @panic("TODO"),
|
.try_ptr => @panic("TODO"),
|
||||||
|
|
|
||||||
|
|
@ -618,6 +618,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
|
||||||
.union_init => @panic("TODO try self.airUnionInit(inst)"),
|
.union_init => @panic("TODO try self.airUnionInit(inst)"),
|
||||||
.prefetch => try self.airPrefetch(inst),
|
.prefetch => try self.airPrefetch(inst),
|
||||||
.mul_add => @panic("TODO try self.airMulAdd(inst)"),
|
.mul_add => @panic("TODO try self.airMulAdd(inst)"),
|
||||||
|
.addrspace_cast => @panic("TODO try self.airAddrSpaceCast(int)"),
|
||||||
|
|
||||||
.@"try" => try self.airTry(inst),
|
.@"try" => try self.airTry(inst),
|
||||||
.try_ptr => @panic("TODO try self.airTryPtr(inst)"),
|
.try_ptr => @panic("TODO try self.airTryPtr(inst)"),
|
||||||
|
|
|
||||||
|
|
@ -1699,6 +1699,7 @@ fn genInst(self: *Self, inst: Air.Inst.Index) !WValue {
|
||||||
.set_err_return_trace,
|
.set_err_return_trace,
|
||||||
.is_named_enum_value,
|
.is_named_enum_value,
|
||||||
.error_set_has_value,
|
.error_set_has_value,
|
||||||
|
.addrspace_cast,
|
||||||
=> |tag| return self.fail("TODO: Implement wasm inst: {s}", .{@tagName(tag)}),
|
=> |tag| return self.fail("TODO: Implement wasm inst: {s}", .{@tagName(tag)}),
|
||||||
|
|
||||||
.add_optimized,
|
.add_optimized,
|
||||||
|
|
|
||||||
|
|
@ -695,6 +695,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
|
||||||
.union_init => try self.airUnionInit(inst),
|
.union_init => try self.airUnionInit(inst),
|
||||||
.prefetch => try self.airPrefetch(inst),
|
.prefetch => try self.airPrefetch(inst),
|
||||||
.mul_add => try self.airMulAdd(inst),
|
.mul_add => try self.airMulAdd(inst),
|
||||||
|
.addrspace_cast => return self.fail("TODO implement addrspace_cast", .{}),
|
||||||
|
|
||||||
.@"try" => try self.airTry(inst),
|
.@"try" => try self.airTry(inst),
|
||||||
.try_ptr => try self.airTryPtr(inst),
|
.try_ptr => try self.airTryPtr(inst),
|
||||||
|
|
|
||||||
|
|
@ -1871,6 +1871,7 @@ fn genBody(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail, OutO
|
||||||
.aggregate_init => try airAggregateInit(f, inst),
|
.aggregate_init => try airAggregateInit(f, inst),
|
||||||
.union_init => try airUnionInit(f, inst),
|
.union_init => try airUnionInit(f, inst),
|
||||||
.prefetch => try airPrefetch(f, inst),
|
.prefetch => try airPrefetch(f, inst),
|
||||||
|
.addrspace_cast => return f.fail("TODO: C backend: implement addrspace_cast", .{}),
|
||||||
|
|
||||||
.@"try" => try airTry(f, inst),
|
.@"try" => try airTry(f, inst),
|
||||||
.try_ptr => try airTryPtr(f, inst),
|
.try_ptr => try airTryPtr(f, inst),
|
||||||
|
|
|
||||||
|
|
@ -4512,6 +4512,7 @@ pub const FuncGen = struct {
|
||||||
.aggregate_init => try self.airAggregateInit(inst),
|
.aggregate_init => try self.airAggregateInit(inst),
|
||||||
.union_init => try self.airUnionInit(inst),
|
.union_init => try self.airUnionInit(inst),
|
||||||
.prefetch => try self.airPrefetch(inst),
|
.prefetch => try self.airPrefetch(inst),
|
||||||
|
.addrspace_cast => try self.airAddrSpaceCast(inst),
|
||||||
|
|
||||||
.is_named_enum_value => try self.airIsNamedEnumValue(inst),
|
.is_named_enum_value => try self.airIsNamedEnumValue(inst),
|
||||||
.error_set_has_value => try self.airErrorSetHasValue(inst),
|
.error_set_has_value => try self.airErrorSetHasValue(inst),
|
||||||
|
|
@ -9045,6 +9046,17 @@ pub const FuncGen = struct {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn airAddrSpaceCast(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {
|
||||||
|
if (self.liveness.isUnused(inst)) return null;
|
||||||
|
|
||||||
|
const ty_op = self.air.instructions.items(.data)[inst].ty_op;
|
||||||
|
const inst_ty = self.air.typeOfIndex(inst);
|
||||||
|
const operand = try self.resolveInst(ty_op.operand);
|
||||||
|
|
||||||
|
const llvm_dest_ty = try self.dg.lowerType(inst_ty);
|
||||||
|
return self.builder.buildAddrSpaceCast(operand, llvm_dest_ty, "");
|
||||||
|
}
|
||||||
|
|
||||||
fn softF80TruncOrExt(
|
fn softF80TruncOrExt(
|
||||||
self: *FuncGen,
|
self: *FuncGen,
|
||||||
operand: *llvm.Value,
|
operand: *llvm.Value,
|
||||||
|
|
|
||||||
|
|
@ -244,6 +244,7 @@ const Writer = struct {
|
||||||
.byte_swap,
|
.byte_swap,
|
||||||
.bit_reverse,
|
.bit_reverse,
|
||||||
.error_set_has_value,
|
.error_set_has_value,
|
||||||
|
.addrspace_cast,
|
||||||
=> try w.writeTyOp(s, inst),
|
=> try w.writeTyOp(s, inst),
|
||||||
|
|
||||||
.block,
|
.block,
|
||||||
|
|
|
||||||
|
|
@ -512,6 +512,7 @@ const Writer = struct {
|
||||||
.err_set_cast,
|
.err_set_cast,
|
||||||
.wasm_memory_grow,
|
.wasm_memory_grow,
|
||||||
.prefetch,
|
.prefetch,
|
||||||
|
.addrspace_cast,
|
||||||
=> {
|
=> {
|
||||||
const inst_data = self.code.extraData(Zir.Inst.BinNode, extended.operand).data;
|
const inst_data = self.code.extraData(Zir.Inst.BinNode, extended.operand).data;
|
||||||
const src = LazySrcLoc.nodeOffset(inst_data.node);
|
const src = LazySrcLoc.nodeOffset(inst_data.node);
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue