diff --git a/lib/std/builtin.zig b/lib/std/builtin.zig index 09d93d5d21..11273eedeb 100644 --- a/lib/std/builtin.zig +++ b/lib/std/builtin.zig @@ -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, diff --git a/lib/std/mem.zig b/lib/std/mem.zig index 9eaf185119..95d4c919db 100644 --- a/lib/std/mem.zig +++ b/lib/std/mem.zig @@ -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, }, diff --git a/lib/std/meta.zig b/lib/std/meta.zig index a1bfacf597..62866bb711 100644 --- a/lib/std/meta.zig +++ b/lib/std/meta.zig @@ -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, diff --git a/lib/std/zig/c_translation.zig b/lib/std/zig/c_translation.zig index bb8a699f69..999572d212 100644 --- a/lib/std/zig/c_translation.zig +++ b/lib/std/zig/c_translation.zig @@ -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, diff --git a/src/Sema.zig b/src/Sema.zig index d6e926e604..bf676866a1 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -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, diff --git a/src/stage1/all_types.hpp b/src/stage1/all_types.hpp index 4004199eb6..13c37fc839 100644 --- a/src/stage1/all_types.hpp +++ b/src/stage1/all_types.hpp @@ -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, diff --git a/src/stage1/analyze.cpp b/src/stage1/analyze.cpp index 2eb609ef1a..320d8ff9b2 100644 --- a/src/stage1/analyze.cpp +++ b/src/stage1/analyze.cpp @@ -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"); diff --git a/src/stage1/analyze.hpp b/src/stage1/analyze.hpp index 8290ef572c..6d584ff361 100644 --- a/src/stage1/analyze.hpp +++ b/src/stage1/analyze.hpp @@ -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); diff --git a/src/stage1/ir.cpp b/src/stage1/ir.cpp index 0604c05c46..a41384cee6 100644 --- a/src/stage1/ir.cpp +++ b/src/stage1/ir.cpp @@ -16124,7 +16124,7 @@ static Stage1AirInst *ir_analyze_instruction_optional_unwrap_ptr(IrAnalyze *ira, static Stage1AirInst *ir_analyze_instruction_ctz(IrAnalyze *ira, Stage1ZirInstCtz *instruction) { Error err; - + ZigType *int_type = ir_resolve_int_type(ira, instruction->type->child); if (type_is_invalid(int_type)) return ira->codegen->invalid_inst_gen; @@ -16166,7 +16166,7 @@ static Stage1AirInst *ir_analyze_instruction_ctz(IrAnalyze *ira, Stage1ZirInstCt return ira->codegen->invalid_inst_gen; if (val->special == ConstValSpecialUndef) return ir_const_undef(ira, instruction->base.scope, instruction->base.source_node, ira->codegen->builtin_types.entry_num_lit_int); - + if (is_vector) { ZigType *smallest_vec_type = get_vector_type(ira->codegen, vector_len, smallest_type); Stage1AirInst *result = ir_const(ira, instruction->base.scope, instruction->base.source_node, smallest_vec_type); @@ -16200,7 +16200,7 @@ static Stage1AirInst *ir_analyze_instruction_ctz(IrAnalyze *ira, Stage1ZirInstCt static Stage1AirInst *ir_analyze_instruction_clz(IrAnalyze *ira, Stage1ZirInstClz *instruction) { Error err; - + ZigType *int_type = ir_resolve_int_type(ira, instruction->type->child); if (type_is_invalid(int_type)) return ira->codegen->invalid_inst_gen; @@ -16242,7 +16242,7 @@ static Stage1AirInst *ir_analyze_instruction_clz(IrAnalyze *ira, Stage1ZirInstCl return ira->codegen->invalid_inst_gen; if (val->special == ConstValSpecialUndef) return ir_const_undef(ira, instruction->base.scope, instruction->base.source_node, ira->codegen->builtin_types.entry_num_lit_int); - + if (is_vector) { ZigType *smallest_vec_type = get_vector_type(ira->codegen, vector_len, smallest_type); Stage1AirInst *result = ir_const(ira, instruction->base.scope, instruction->base.source_node, smallest_vec_type); @@ -16276,7 +16276,7 @@ static Stage1AirInst *ir_analyze_instruction_clz(IrAnalyze *ira, Stage1ZirInstCl static Stage1AirInst *ir_analyze_instruction_pop_count(IrAnalyze *ira, Stage1ZirInstPopCount *instruction) { Error err; - + ZigType *int_type = ir_resolve_int_type(ira, instruction->type->child); if (type_is_invalid(int_type)) return ira->codegen->invalid_inst_gen; @@ -16318,7 +16318,7 @@ static Stage1AirInst *ir_analyze_instruction_pop_count(IrAnalyze *ira, Stage1Zir return ira->codegen->invalid_inst_gen; if (val->special == ConstValSpecialUndef) return ir_const_undef(ira, instruction->base.scope, instruction->base.source_node, ira->codegen->builtin_types.entry_num_lit_int); - + if (is_vector) { ZigType *smallest_vec_type = get_vector_type(ira->codegen, vector_len, smallest_type); Stage1AirInst *result = ir_const(ira, instruction->base.scope, instruction->base.source_node, smallest_vec_type); @@ -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(); 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(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); diff --git a/test/behavior/type.zig b/test/behavior/type.zig index 3a56f2171f..cd5d2c3e06 100644 --- a/test/behavior/type.zig +++ b/test/behavior/type.zig @@ -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, }, diff --git a/test/compile_errors.zig b/test/compile_errors.zig index 9fd125a775..3e9508be37 100644 --- a/test/compile_errors.zig +++ b/test/compile_errors.zig @@ -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,