mirror of
https://github.com/ziglang/zig.git
synced 2026-02-12 20:37:54 +00:00
AstGen: implement @Vector
This commit is contained in:
parent
e018e64a53
commit
ff2ec0dc5a
@ -1808,6 +1808,7 @@ fn unusedResultExpr(gz: *GenZir, scope: *Scope, statement: ast.Node.Index) Inner
|
||||
.array_mul,
|
||||
.array_type,
|
||||
.array_type_sentinel,
|
||||
.vector_type,
|
||||
.elem_type,
|
||||
.indexable_ptr_len,
|
||||
.anyframe_type,
|
||||
@ -6510,6 +6511,14 @@ fn builtinCall(
|
||||
});
|
||||
return rvalue(gz, scope, rl, result, node);
|
||||
},
|
||||
.Vector => {
|
||||
const result = try gz.addPlNode(.vector_type, node, Zir.Inst.Bin{
|
||||
.lhs = try comptimeExpr(gz, scope, .{.ty = .u32_type}, params[0]),
|
||||
.rhs = try typeExpr(gz, scope, params[1]),
|
||||
});
|
||||
return rvalue(gz, scope, rl, result, node);
|
||||
},
|
||||
|
||||
}
|
||||
// zig fmt: on
|
||||
}
|
||||
|
||||
@ -104,6 +104,7 @@ pub const Tag = enum {
|
||||
type_name,
|
||||
TypeOf,
|
||||
union_init,
|
||||
Vector,
|
||||
};
|
||||
|
||||
tag: Tag,
|
||||
@ -848,5 +849,12 @@ pub const list = list: {
|
||||
.param_count = 3,
|
||||
},
|
||||
},
|
||||
.{
|
||||
"@Vector",
|
||||
.{
|
||||
.tag = .Vector,
|
||||
.param_count = 2,
|
||||
},
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
16
src/Sema.zig
16
src/Sema.zig
@ -143,6 +143,7 @@ pub fn analyzeBody(
|
||||
.array_mul => try sema.zirArrayMul(block, inst),
|
||||
.array_type => try sema.zirArrayType(block, inst),
|
||||
.array_type_sentinel => try sema.zirArrayTypeSentinel(block, inst),
|
||||
.vector_type => try sema.zirVectorType(block, inst),
|
||||
.as => try sema.zirAs(block, inst),
|
||||
.as_node => try sema.zirAsNode(block, inst),
|
||||
.bit_and => try sema.zirBitwise(block, inst, .bit_and),
|
||||
@ -2143,6 +2144,21 @@ fn zirElemType(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerErro
|
||||
return sema.mod.constType(sema.arena, src, elem_type);
|
||||
}
|
||||
|
||||
fn zirVectorType(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst {
|
||||
const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
|
||||
const src = inst_data.src();
|
||||
const elem_type_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node };
|
||||
const len_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 len = try sema.resolveAlreadyCoercedInt(block, len_src, extra.lhs, u32);
|
||||
const elem_type = try sema.resolveType(block, elem_type_src, extra.rhs);
|
||||
const vector_type = try Type.Tag.vector.create(sema.arena, .{
|
||||
.len = len,
|
||||
.elem_type = elem_type,
|
||||
});
|
||||
return sema.mod.constType(sema.arena, src, vector_type);
|
||||
}
|
||||
|
||||
fn zirArrayType(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst {
|
||||
const tracy = trace(@src());
|
||||
defer tracy.end();
|
||||
|
||||
@ -158,6 +158,10 @@ pub const Inst = struct {
|
||||
/// `[N:S]T` syntax. No source location provided.
|
||||
/// Uses the `array_type_sentinel` field.
|
||||
array_type_sentinel,
|
||||
/// `@Vector` builtin.
|
||||
/// Uses the `pl_node` union field with `Bin` payload.
|
||||
/// lhs is length, rhs is element type.
|
||||
vector_type,
|
||||
/// Given an array type, returns the element type.
|
||||
/// Uses the `un_node` union field.
|
||||
elem_type,
|
||||
@ -952,6 +956,7 @@ pub const Inst = struct {
|
||||
.array_mul,
|
||||
.array_type,
|
||||
.array_type_sentinel,
|
||||
.vector_type,
|
||||
.elem_type,
|
||||
.indexable_ptr_len,
|
||||
.anyframe_type,
|
||||
@ -2542,6 +2547,7 @@ const Writer = struct {
|
||||
.atomic_load,
|
||||
.bitcast,
|
||||
.bitcast_result_ptr,
|
||||
.vector_type,
|
||||
=> try self.writePlNodeBin(stream, inst),
|
||||
|
||||
.@"export" => try self.writePlNodeExport(stream, inst),
|
||||
|
||||
58
src/type.zig
58
src/type.zig
@ -69,7 +69,14 @@ pub const Type = extern union {
|
||||
.fn_ccc_void_no_args => return .Fn,
|
||||
.function => return .Fn,
|
||||
|
||||
.array, .array_u8_sentinel_0, .array_u8, .array_sentinel => return .Array,
|
||||
.array,
|
||||
.array_u8_sentinel_0,
|
||||
.array_u8,
|
||||
.array_sentinel,
|
||||
=> return .Array,
|
||||
|
||||
.vector => return .Vector,
|
||||
|
||||
.single_const_pointer_to_comptime_int,
|
||||
.const_slice_u8,
|
||||
.single_const_pointer,
|
||||
@ -438,7 +445,7 @@ pub const Type = extern union {
|
||||
const info_b = b.intInfo(@as(Target, undefined));
|
||||
return info_a.signedness == info_b.signedness and info_a.bits == info_b.bits;
|
||||
},
|
||||
.Array => {
|
||||
.Array, .Vector => {
|
||||
if (a.arrayLen() != b.arrayLen())
|
||||
return false;
|
||||
if (!a.elemType().eql(b.elemType()))
|
||||
@ -487,7 +494,6 @@ pub const Type = extern union {
|
||||
.BoundFn,
|
||||
.Opaque,
|
||||
.Frame,
|
||||
.Vector,
|
||||
=> std.debug.panic("TODO implement Type equality comparison of {} and {}", .{ a, b }),
|
||||
}
|
||||
}
|
||||
@ -522,7 +528,7 @@ pub const Type = extern union {
|
||||
std.hash.autoHash(&hasher, info.bits);
|
||||
}
|
||||
},
|
||||
.Array => {
|
||||
.Array, .Vector => {
|
||||
std.hash.autoHash(&hasher, self.arrayLen());
|
||||
std.hash.autoHash(&hasher, self.elemType().hash());
|
||||
// TODO hash array sentinel
|
||||
@ -552,7 +558,6 @@ pub const Type = extern union {
|
||||
.Opaque,
|
||||
.Frame,
|
||||
.AnyFrame,
|
||||
.Vector,
|
||||
.EnumLiteral,
|
||||
=> {
|
||||
// TODO implement more type hashing
|
||||
@ -647,6 +652,13 @@ pub const Type = extern union {
|
||||
.int_unsigned,
|
||||
=> return self.copyPayloadShallow(allocator, Payload.Bits),
|
||||
|
||||
.vector => {
|
||||
const payload = self.castTag(.vector).?.data;
|
||||
return Tag.vector.create(allocator, .{
|
||||
.len = payload.len,
|
||||
.elem_type = try payload.elem_type.copy(allocator),
|
||||
});
|
||||
},
|
||||
.array => {
|
||||
const payload = self.castTag(.array).?.data;
|
||||
return Tag.array.create(allocator, .{
|
||||
@ -839,6 +851,12 @@ pub const Type = extern union {
|
||||
const len = ty.castTag(.array_u8_sentinel_0).?.data;
|
||||
return writer.print("[{d}:0]u8", .{len});
|
||||
},
|
||||
.vector => {
|
||||
const payload = ty.castTag(.vector).?.data;
|
||||
try writer.print("@Vector({d}, ", .{payload.len});
|
||||
try payload.elem_type.format("", .{}, writer);
|
||||
return writer.writeAll(")");
|
||||
},
|
||||
.array => {
|
||||
const payload = ty.castTag(.array).?.data;
|
||||
try writer.print("[{d}]", .{payload.len});
|
||||
@ -1116,7 +1134,7 @@ pub const Type = extern union {
|
||||
},
|
||||
|
||||
// TODO lazy types
|
||||
.array => self.elemType().hasCodeGenBits() and self.arrayLen() != 0,
|
||||
.array, .vector => self.elemType().hasCodeGenBits() and self.arrayLen() != 0,
|
||||
.array_u8 => self.arrayLen() != 0,
|
||||
.array_sentinel, .single_const_pointer, .single_mut_pointer, .many_const_pointer, .many_mut_pointer, .c_const_pointer, .c_mut_pointer, .const_slice, .mut_slice, .pointer => self.elemType().hasCodeGenBits(),
|
||||
.int_signed, .int_unsigned => self.cast(Payload.Bits).?.data != 0,
|
||||
@ -1264,6 +1282,10 @@ pub const Type = extern union {
|
||||
|
||||
.array, .array_sentinel => return self.elemType().abiAlignment(target),
|
||||
|
||||
// TODO audit this - is there any more complicated logic to determine
|
||||
// ABI alignment of vectors?
|
||||
.vector => return 16,
|
||||
|
||||
.int_signed, .int_unsigned => {
|
||||
const bits: u16 = self.cast(Payload.Bits).?.data;
|
||||
return std.math.ceilPowerOfTwoPromote(u16, (bits + 7) / 8);
|
||||
@ -1386,8 +1408,8 @@ pub const Type = extern union {
|
||||
|
||||
.array_u8 => self.castTag(.array_u8).?.data,
|
||||
.array_u8_sentinel_0 => self.castTag(.array_u8_sentinel_0).?.data + 1,
|
||||
.array => {
|
||||
const payload = self.castTag(.array).?.data;
|
||||
.array, .vector => {
|
||||
const payload = self.cast(Payload.Array).?.data;
|
||||
const elem_size = std.math.max(payload.elem_type.abiAlignment(target), payload.elem_type.abiSize(target));
|
||||
return payload.len * elem_size;
|
||||
},
|
||||
@ -1534,6 +1556,11 @@ pub const Type = extern union {
|
||||
|
||||
.bool => 1,
|
||||
|
||||
.vector => {
|
||||
const payload = self.castTag(.vector).?.data;
|
||||
const elem_bit_size = payload.elem_type.bitSize(target);
|
||||
return elem_bit_size * payload.len;
|
||||
},
|
||||
.array_u8 => 8 * self.castTag(.array_u8).?.data,
|
||||
.array_u8_sentinel_0 => 8 * (self.castTag(.array_u8_sentinel_0).?.data + 1),
|
||||
.array => {
|
||||
@ -1811,7 +1838,6 @@ pub const Type = extern union {
|
||||
.Enum,
|
||||
.Frame,
|
||||
.AnyFrame,
|
||||
.Vector,
|
||||
=> return true,
|
||||
|
||||
.Opaque => return is_extern,
|
||||
@ -1830,7 +1856,7 @@ pub const Type = extern union {
|
||||
var buf: Payload.ElemType = undefined;
|
||||
return ty.optionalChild(&buf).isValidVarType(is_extern);
|
||||
},
|
||||
.Pointer, .Array => ty = ty.elemType(),
|
||||
.Pointer, .Array, .Vector => ty = ty.elemType(),
|
||||
.ErrorUnion => ty = ty.errorUnionChild(),
|
||||
|
||||
.Fn => @panic("TODO fn isValidVarType"),
|
||||
@ -1846,6 +1872,7 @@ pub const Type = extern union {
|
||||
/// Asserts the type is a pointer or array type.
|
||||
pub fn elemType(self: Type) Type {
|
||||
return switch (self.tag()) {
|
||||
.vector => self.castTag(.vector).?.data.elem_type,
|
||||
.array => self.castTag(.array).?.data.elem_type,
|
||||
.array_sentinel => self.castTag(.array_sentinel).?.data.elem_type,
|
||||
.single_const_pointer,
|
||||
@ -1936,6 +1963,7 @@ pub const Type = extern union {
|
||||
/// Asserts the type is an array or vector.
|
||||
pub fn arrayLen(self: Type) u64 {
|
||||
return switch (self.tag()) {
|
||||
.vector => self.castTag(.vector).?.data.len,
|
||||
.array => self.castTag(.array).?.data.len,
|
||||
.array_sentinel => self.castTag(.array_sentinel).?.data.len,
|
||||
.array_u8 => self.castTag(.array_u8).?.data,
|
||||
@ -1955,6 +1983,7 @@ pub const Type = extern union {
|
||||
.c_const_pointer,
|
||||
.c_mut_pointer,
|
||||
.single_const_pointer_to_comptime_int,
|
||||
.vector,
|
||||
.array,
|
||||
.array_u8,
|
||||
.manyptr_u8,
|
||||
@ -2325,7 +2354,7 @@ pub const Type = extern union {
|
||||
return null;
|
||||
}
|
||||
},
|
||||
.array, .array_u8 => {
|
||||
.vector, .array, .array_u8 => {
|
||||
if (ty.arrayLen() == 0)
|
||||
return Value.initTag(.empty_array);
|
||||
ty = ty.elemType();
|
||||
@ -2730,6 +2759,7 @@ pub const Type = extern union {
|
||||
array_u8_sentinel_0,
|
||||
array,
|
||||
array_sentinel,
|
||||
vector,
|
||||
pointer,
|
||||
single_const_pointer,
|
||||
single_mut_pointer,
|
||||
@ -2845,7 +2875,7 @@ pub const Type = extern union {
|
||||
|
||||
.error_set => Payload.ErrorSet,
|
||||
|
||||
.array => Payload.Array,
|
||||
.array, .vector => Payload.Array,
|
||||
.array_sentinel => Payload.ArraySentinel,
|
||||
.pointer => Payload.Pointer,
|
||||
.function => Payload.Function,
|
||||
@ -2888,9 +2918,7 @@ pub const Type = extern union {
|
||||
};
|
||||
|
||||
pub const Array = struct {
|
||||
pub const base_tag = Tag.array;
|
||||
|
||||
base: Payload = Payload{ .tag = base_tag },
|
||||
base: Payload,
|
||||
data: struct {
|
||||
len: u64,
|
||||
elem_type: Type,
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user