AstGen: implement @Vector

This commit is contained in:
Andrew Kelley 2021-04-24 17:31:52 -07:00
parent e018e64a53
commit ff2ec0dc5a
5 changed files with 82 additions and 15 deletions

View File

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

View File

@ -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,
},
},
});
};

View File

@ -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();

View File

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

View File

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