Address Spaces: Pointer and function info in @Type

This commit is contained in:
Robin Voetter 2021-08-30 02:54:03 +02:00
parent 7a5d0cdf45
commit c5945467ac
11 changed files with 122 additions and 49 deletions

View file

@ -235,6 +235,7 @@ pub const TypeInfo = union(enum) {
is_const: bool,
is_volatile: bool,
alignment: comptime_int,
address_space: AddressSpace,
child: type,
is_allowzero: bool,
@ -364,6 +365,7 @@ pub const TypeInfo = union(enum) {
pub const Fn = struct {
calling_convention: CallingConvention,
alignment: comptime_int,
address_space: AddressSpace,
is_generic: bool,
is_var_args: bool,
return_type: ?type,

View file

@ -2472,6 +2472,7 @@ fn CopyPtrAttrs(comptime source: type, comptime size: std.builtin.TypeInfo.Point
.is_volatile = info.is_volatile,
.is_allowzero = info.is_allowzero,
.alignment = info.alignment,
.address_space = info.address_space,
.child = child,
.sentinel = null,
},
@ -2960,6 +2961,7 @@ fn AlignedSlice(comptime AttributeSource: type, comptime new_alignment: u29) typ
.is_volatile = info.is_volatile,
.is_allowzero = info.is_allowzero,
.alignment = new_alignment,
.address_space = info.address_space,
.child = info.child,
.sentinel = null,
},

View file

@ -235,6 +235,7 @@ pub fn Sentinel(comptime T: type, comptime sentinel_val: Elem(T)) type {
.is_const = info.is_const,
.is_volatile = info.is_volatile,
.alignment = info.alignment,
.address_space = info.address_space,
.child = @Type(.{
.Array = .{
.len = array_info.len,
@ -254,6 +255,7 @@ pub fn Sentinel(comptime T: type, comptime sentinel_val: Elem(T)) type {
.is_const = info.is_const,
.is_volatile = info.is_volatile,
.alignment = info.alignment,
.address_space = info.address_space,
.child = info.child,
.is_allowzero = info.is_allowzero,
.sentinel = sentinel_val,
@ -271,6 +273,7 @@ pub fn Sentinel(comptime T: type, comptime sentinel_val: Elem(T)) type {
.is_const = ptr_info.is_const,
.is_volatile = ptr_info.is_volatile,
.alignment = ptr_info.alignment,
.address_space = ptr_info.address_space,
.child = ptr_info.child,
.is_allowzero = ptr_info.is_allowzero,
.sentinel = sentinel_val,

View file

@ -325,6 +325,7 @@ pub fn FlexibleArrayType(comptime SelfType: type, ElementType: type) type {
.is_const = ptr.is_const,
.is_volatile = ptr.is_volatile,
.alignment = @alignOf(ElementType),
.address_space = .generic,
.child = ElementType,
.is_allowzero = true,
.sentinel = null,

View file

@ -6413,7 +6413,7 @@ fn zirTypeInfo(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileEr
switch (ty.zigTypeTag()) {
.Fn => {
const field_values = try sema.arena.alloc(Value, 6);
const field_values = try sema.arena.alloc(Value, 7);
// calling_convention: CallingConvention,
field_values[0] = try Value.Tag.enum_field_index.create(
sema.arena,
@ -6421,14 +6421,19 @@ fn zirTypeInfo(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileEr
);
// alignment: comptime_int,
field_values[1] = try Value.Tag.int_u64.create(sema.arena, ty.abiAlignment(target));
// address_space: AddressSpace,
field_values[2] = try Value.Tag.enum_field_index.create(
sema.arena,
@enumToInt(ty.fnAddressSpace()),
);
// is_generic: bool,
field_values[2] = Value.initTag(.bool_false); // TODO
// is_var_args: bool,
field_values[3] = Value.initTag(.bool_false); // TODO
// is_var_args: bool,
field_values[4] = Value.initTag(.bool_false); // TODO
// return_type: ?type,
field_values[4] = try Value.Tag.ty.create(sema.arena, ty.fnReturnType());
field_values[5] = try Value.Tag.ty.create(sema.arena, ty.fnReturnType());
// args: []const FnArg,
field_values[5] = Value.initTag(.null_value); // TODO
field_values[6] = Value.initTag(.null_value); // TODO
return sema.addConstant(
type_info_ty,

View file

@ -86,6 +86,14 @@ enum CallingConvention {
CallingConventionSysV
};
// Stage 1 supports only the generic address space
enum AddressSpace {
AddressSpaceGeneric,
AddressSpaceGS,
AddressSpaceFS,
AddressSpaceSS,
};
// This one corresponds to the builtin.zig enum.
enum BuiltinPtrSize {
BuiltinPtrSizeOne,

View file

@ -1019,6 +1019,16 @@ bool calling_convention_allows_zig_types(CallingConvention cc) {
zig_unreachable();
}
const char *address_space_name(AddressSpace as) {
switch (as) {
case AddressSpaceGeneric: return "generic";
case AddressSpaceGS: return "gs";
case AddressSpaceFS: return "fs";
case AddressSpaceSS: return "ss";
}
zig_unreachable();
}
ZigType *get_stack_trace_type(CodeGen *g) {
if (g->stack_trace_type == nullptr) {
g->stack_trace_type = get_builtin_type(g, "StackTrace");

View file

@ -242,6 +242,8 @@ Error get_primitive_type(CodeGen *g, Buf *name, ZigType **result);
bool calling_convention_allows_zig_types(CallingConvention cc);
const char *calling_convention_name(CallingConvention cc);
const char *address_space_name(AddressSpace as);
Error ATTRIBUTE_MUST_USE file_fetch(CodeGen *g, Buf *resolved_path, Buf *contents);
void walk_function_params(CodeGen *g, ZigType *fn_type, FnWalk *fn_walk);

View file

@ -17904,7 +17904,7 @@ static ZigValue *create_ptr_like_type_info(IrAnalyze *ira, Scope *scope, AstNode
result->special = ConstValSpecialStatic;
result->type = type_info_pointer_type;
ZigValue **fields = alloc_const_vals_ptrs(ira->codegen, 7);
ZigValue **fields = alloc_const_vals_ptrs(ira->codegen, 8);
result->data.x_struct.fields = fields;
// size: Size
@ -17939,24 +17939,29 @@ static ZigValue *create_ptr_like_type_info(IrAnalyze *ira, Scope *scope, AstNode
lazy_align_of->base.id = LazyValueIdAlignOf;
lazy_align_of->target_type = ir_const_type(ira, scope, source_node, attrs_type->data.pointer.child_type);
}
// child: type
ensure_field_index(result->type, "child", 4);
// address_space: AddressSpace,
ensure_field_index(result->type, "address_space", 4);
fields[4]->special = ConstValSpecialStatic;
fields[4]->type = ira->codegen->builtin_types.entry_type;
fields[4]->data.x_type = attrs_type->data.pointer.child_type;
// is_allowzero: bool
ensure_field_index(result->type, "is_allowzero", 5);
fields[4]->type = get_builtin_type(ira->codegen, "AddressSpace");
bigint_init_unsigned(&fields[4]->data.x_enum_tag, AddressSpaceGeneric);
// child: type
ensure_field_index(result->type, "child", 5);
fields[5]->special = ConstValSpecialStatic;
fields[5]->type = ira->codegen->builtin_types.entry_bool;
fields[5]->data.x_bool = attrs_type->data.pointer.allow_zero;
// sentinel: anytype
ensure_field_index(result->type, "sentinel", 6);
fields[5]->type = ira->codegen->builtin_types.entry_type;
fields[5]->data.x_type = attrs_type->data.pointer.child_type;
// is_allowzero: bool
ensure_field_index(result->type, "is_allowzero", 6);
fields[6]->special = ConstValSpecialStatic;
fields[6]->type = ira->codegen->builtin_types.entry_bool;
fields[6]->data.x_bool = attrs_type->data.pointer.allow_zero;
// sentinel: anytype
ensure_field_index(result->type, "sentinel", 7);
fields[7]->special = ConstValSpecialStatic;
if (attrs_type->data.pointer.sentinel != nullptr) {
fields[6]->type = get_optional_type(ira->codegen, attrs_type->data.pointer.child_type);
set_optional_payload(fields[6], attrs_type->data.pointer.sentinel);
fields[7]->type = get_optional_type(ira->codegen, attrs_type->data.pointer.child_type);
set_optional_payload(fields[7], attrs_type->data.pointer.sentinel);
} else {
fields[6]->type = ira->codegen->builtin_types.entry_null;
fields[7]->type = ira->codegen->builtin_types.entry_null;
}
return result;
@ -18465,7 +18470,7 @@ static Error ir_make_type_info_value(IrAnalyze *ira, Scope *scope, AstNode *sour
result->special = ConstValSpecialStatic;
result->type = ir_type_info_get_type(ira, "Fn", nullptr);
ZigValue **fields = alloc_const_vals_ptrs(ira->codegen, 6);
ZigValue **fields = alloc_const_vals_ptrs(ira->codegen, 7);
result->data.x_struct.fields = fields;
// calling_convention: TypeInfo.CallingConvention
@ -18478,30 +18483,35 @@ static Error ir_make_type_info_value(IrAnalyze *ira, Scope *scope, AstNode *sour
fields[1]->special = ConstValSpecialStatic;
fields[1]->type = ira->codegen->builtin_types.entry_num_lit_int;
bigint_init_unsigned(&fields[1]->data.x_bigint, get_ptr_align(ira->codegen, type_entry));
// is_generic: bool
ensure_field_index(result->type, "is_generic", 2);
bool is_generic = type_entry->data.fn.is_generic;
// address_space: AddressSpace
ensure_field_index(result->type, "address_space", 2);
fields[2]->special = ConstValSpecialStatic;
fields[2]->type = ira->codegen->builtin_types.entry_bool;
fields[2]->data.x_bool = is_generic;
// is_varargs: bool
ensure_field_index(result->type, "is_var_args", 3);
bool is_varargs = type_entry->data.fn.fn_type_id.is_var_args;
fields[2]->type = get_builtin_type(ira->codegen, "AddressSpace");
bigint_init_unsigned(&fields[2]->data.x_enum_tag, AddressSpaceGeneric);
// is_generic: bool
ensure_field_index(result->type, "is_generic", 3);
bool is_generic = type_entry->data.fn.is_generic;
fields[3]->special = ConstValSpecialStatic;
fields[3]->type = ira->codegen->builtin_types.entry_bool;
fields[3]->data.x_bool = is_varargs;
// return_type: ?type
ensure_field_index(result->type, "return_type", 4);
fields[3]->data.x_bool = is_generic;
// is_varargs: bool
ensure_field_index(result->type, "is_var_args", 4);
bool is_varargs = type_entry->data.fn.fn_type_id.is_var_args;
fields[4]->special = ConstValSpecialStatic;
fields[4]->type = get_optional_type(ira->codegen, ira->codegen->builtin_types.entry_type);
fields[4]->type = ira->codegen->builtin_types.entry_bool;
fields[4]->data.x_bool = is_varargs;
// return_type: ?type
ensure_field_index(result->type, "return_type", 5);
fields[5]->special = ConstValSpecialStatic;
fields[5]->type = get_optional_type(ira->codegen, ira->codegen->builtin_types.entry_type);
if (type_entry->data.fn.fn_type_id.return_type == nullptr)
fields[4]->data.x_optional = nullptr;
fields[5]->data.x_optional = nullptr;
else {
ZigValue *return_type = ira->codegen->pass1_arena->create<ZigValue>();
return_type->special = ConstValSpecialStatic;
return_type->type = ira->codegen->builtin_types.entry_type;
return_type->data.x_type = type_entry->data.fn.fn_type_id.return_type;
fields[4]->data.x_optional = return_type;
fields[5]->data.x_optional = return_type;
}
// args: []TypeInfo.FnArg
ZigType *type_info_fn_arg_type = ir_type_info_get_type(ira, "FnArg", nullptr);
@ -18516,7 +18526,7 @@ static Error ir_make_type_info_value(IrAnalyze *ira, Scope *scope, AstNode *sour
fn_arg_array->data.x_array.special = ConstArraySpecialNone;
fn_arg_array->data.x_array.data.s_none.elements = ira->codegen->pass1_arena->allocate<ZigValue>(fn_arg_count);
init_const_slice(ira->codegen, fields[5], fn_arg_array, 0, fn_arg_count, false, nullptr);
init_const_slice(ira->codegen, fields[6], fn_arg_array, 0, fn_arg_count, false, nullptr);
for (size_t fn_arg_index = 0; fn_arg_index < fn_arg_count; fn_arg_index++) {
FnTypeParamInfo *fn_param_info = &type_entry->data.fn.fn_type_id.param_info[fn_arg_index];
@ -18826,11 +18836,11 @@ static ZigType *type_info_to_type(IrAnalyze *ira, Scope *scope, AstNode *source_
assert(size_value->type == ir_type_info_get_type(ira, "Size", type_info_pointer_type));
BuiltinPtrSize size_enum_index = (BuiltinPtrSize)bigint_as_u32(&size_value->data.x_enum_tag);
PtrLen ptr_len = size_enum_index_to_ptr_len(size_enum_index);
ZigType *elem_type = get_const_field_meta_type(ira, source_node, payload, "child", 4);
ZigType *elem_type = get_const_field_meta_type(ira, source_node, payload, "child", 5);
if (type_is_invalid(elem_type))
return ira->codegen->invalid_inst_gen->value->type;
ZigValue *sentinel;
if ((err = get_const_field_sentinel(ira, scope, source_node, payload, "sentinel", 6,
if ((err = get_const_field_sentinel(ira, scope, source_node, payload, "sentinel", 7,
elem_type, &sentinel)))
{
return ira->codegen->invalid_inst_gen->value->type;
@ -18845,6 +18855,19 @@ static ZigType *type_info_to_type(IrAnalyze *ira, Scope *scope, AstNode *source_
if (alignment == nullptr)
return ira->codegen->invalid_inst_gen->value->type;
ZigValue *as_value = get_const_field(ira, source_node, payload, "address_space", 4);
if (as_value == nullptr)
return ira->codegen->invalid_inst_gen->value->type;
assert(as_value->special == ConstValSpecialStatic);
assert(as_value->type == get_builtin_type(ira->codegen, "AddressSpace"));
AddressSpace as = (AddressSpace)bigint_as_u32(&as_value->data.x_enum_tag);
if (as != AddressSpaceGeneric) {
ir_add_error_node(ira, source_node, buf_sprintf(
"address space '%s' not available in stage 1 compiler, must be .generic",
address_space_name(as)));
return ira->codegen->invalid_inst_gen->value->type;
}
bool is_const;
if ((err = get_const_field_bool(ira, source_node, payload, "is_const", 1, &is_const)))
return ira->codegen->invalid_inst_gen->value->type;
@ -18857,13 +18880,12 @@ static ZigType *type_info_to_type(IrAnalyze *ira, Scope *scope, AstNode *source_
}
bool is_allowzero;
if ((err = get_const_field_bool(ira, source_node, payload, "is_allowzero", 5,
if ((err = get_const_field_bool(ira, source_node, payload, "is_allowzero", 6,
&is_allowzero)))
{
return ira->codegen->invalid_inst_gen->value->type;
}
ZigType *ptr_type = get_pointer_to_type_extra2(ira->codegen,
elem_type,
is_const,
@ -19308,9 +19330,22 @@ static ZigType *type_info_to_type(IrAnalyze *ira, Scope *scope, AstNode *source_
if (alignment == nullptr)
return ira->codegen->invalid_inst_gen->value->type;
ZigValue *as_value = get_const_field(ira, source_node, payload, "address_space", 2);
if (as_value == nullptr)
return ira->codegen->invalid_inst_gen->value->type;
assert(as_value->special == ConstValSpecialStatic);
assert(as_value->type == get_builtin_type(ira->codegen, "AddressSpace"));
AddressSpace as = (AddressSpace)bigint_as_u32(&as_value->data.x_enum_tag);
if (as != AddressSpaceGeneric) {
ir_add_error_node(ira, source_node, buf_sprintf(
"address space '%s' not available in stage 1 compiler, must be .generic",
address_space_name(as)));
return ira->codegen->invalid_inst_gen->value->type;
}
Error err;
bool is_generic;
if ((err = get_const_field_bool(ira, source_node, payload, "is_generic", 2, &is_generic)))
if ((err = get_const_field_bool(ira, source_node, payload, "is_generic", 3, &is_generic)))
return ira->codegen->invalid_inst_gen->value->type;
if (is_generic) {
ir_add_error_node(ira, source_node, buf_sprintf("TypeInfo.Fn.is_generic must be false for @Type"));
@ -19318,20 +19353,20 @@ static ZigType *type_info_to_type(IrAnalyze *ira, Scope *scope, AstNode *source_
}
bool is_var_args;
if ((err = get_const_field_bool(ira, source_node, payload, "is_var_args", 3, &is_var_args)))
if ((err = get_const_field_bool(ira, source_node, payload, "is_var_args", 4, &is_var_args)))
return ira->codegen->invalid_inst_gen->value->type;
if (is_var_args && cc != CallingConventionC) {
ir_add_error_node(ira, source_node, buf_sprintf("varargs functions must have C calling convention"));
return ira->codegen->invalid_inst_gen->value->type;
}
ZigType *return_type = get_const_field_meta_type_optional(ira, source_node, payload, "return_type", 4);
ZigType *return_type = get_const_field_meta_type_optional(ira, source_node, payload, "return_type", 5);
if (return_type == nullptr) {
ir_add_error_node(ira, source_node, buf_sprintf("TypeInfo.Fn.return_type must be non-null for @Type"));
return ira->codegen->invalid_inst_gen->value->type;
}
ZigValue *args_value = get_const_field(ira, source_node, payload, "args", 5);
ZigValue *args_value = get_const_field(ira, source_node, payload, "args", 6);
if (args_value == nullptr)
return ira->codegen->invalid_inst_gen->value->type;
assert(args_value->special == ConstValSpecialStatic);

View file

@ -137,6 +137,7 @@ test "@Type create slice with null sentinel" {
.is_volatile = false,
.is_allowzero = false,
.alignment = 8,
.address_space = .generic,
.child = *i32,
.sentinel = null,
},

View file

@ -410,6 +410,7 @@ pub fn addCases(ctx: *TestContext) !void {
\\ .Fn = .{
\\ .calling_convention = .Unspecified,
\\ .alignment = 0,
\\ .address_space = 0,
\\ .is_generic = true,
\\ .is_var_args = false,
\\ .return_type = u0,
@ -426,6 +427,7 @@ pub fn addCases(ctx: *TestContext) !void {
\\ .Fn = .{
\\ .calling_convention = .Unspecified,
\\ .alignment = 0,
\\ .address_space = 0,
\\ .is_generic = false,
\\ .is_var_args = true,
\\ .return_type = u0,
@ -442,6 +444,7 @@ pub fn addCases(ctx: *TestContext) !void {
\\ .Fn = .{
\\ .calling_convention = .Unspecified,
\\ .alignment = 0,
\\ .address_space = 0,
\\ .is_generic = false,
\\ .is_var_args = false,
\\ .return_type = null,
@ -711,6 +714,7 @@ pub fn addCases(ctx: *TestContext) !void {
\\ .is_const = false,
\\ .is_volatile = false,
\\ .alignment = 1,
\\ .address_space = .generic,
\\ .child = u8,
\\ .is_allowzero = false,
\\ .sentinel = 0,