Commit 95e83afa98

Robin Voetter <robin@voetter.nl>
2021-09-06 00:29:04
Address Spaces: Yeet address space on function prototypes
This is a property which solely belongs to pointers to functions, not to the functions themselves. This cannot be properly represented by stage 2 at the moment, as type with zigTypeTag() == .Fn is overloaded for for function pointers and function prototypes.
1 parent 5a142df
lib/std/builtin.zig
@@ -365,7 +365,6 @@ 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,
src/codegen/llvm.zig
@@ -700,7 +700,8 @@ pub const DeclGen = struct {
                     @intCast(c_uint, llvm_params.len),
                     llvm.Bool.fromBool(is_var_args),
                 );
-                const llvm_addrspace = self.llvmAddressSpace(t.fnAddressSpace());
+                // TODO make .Fn not both a pointer type and a prototype
+                const llvm_addrspace = self.llvmAddressSpace(.generic);
                 return llvm_fn_ty.pointerType(llvm_addrspace);
             },
             .ComptimeInt => unreachable,
src/stage1/ir.cpp
@@ -18483,35 +18483,30 @@ 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));
-                // address_space: AddressSpace
-                ensure_field_index(result->type, "address_space", 2);
-                fields[2]->special = ConstValSpecialStatic;
-                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);
+                ensure_field_index(result->type, "is_generic", 2);
                 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_generic;
+                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", 4);
+                ensure_field_index(result->type, "is_var_args", 3);
                 bool is_varargs = type_entry->data.fn.fn_type_id.is_var_args;
-                fields[4]->special = ConstValSpecialStatic;
-                fields[4]->type = ira->codegen->builtin_types.entry_bool;
-                fields[4]->data.x_bool = is_varargs;
+                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", 5);
-                fields[5]->special = ConstValSpecialStatic;
-                fields[5]->type = get_optional_type(ira->codegen, ira->codegen->builtin_types.entry_type);
+                ensure_field_index(result->type, "return_type", 4);
+                fields[4]->special = ConstValSpecialStatic;
+                fields[4]->type = get_optional_type(ira->codegen, ira->codegen->builtin_types.entry_type);
                 if (type_entry->data.fn.fn_type_id.return_type == nullptr)
-                    fields[5]->data.x_optional = nullptr;
+                    fields[4]->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[5]->data.x_optional = return_type;
+                    fields[4]->data.x_optional = return_type;
                 }
                 // args: []TypeInfo.FnArg
                 ZigType *type_info_fn_arg_type = ir_type_info_get_type(ira, "FnArg", nullptr);
@@ -18526,7 +18521,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[6], fn_arg_array, 0, fn_arg_count, false, nullptr);
+                init_const_slice(ira->codegen, fields[5], 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];
@@ -19330,22 +19325,9 @@ 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", 3, &is_generic)))
+            if ((err = get_const_field_bool(ira, source_node, payload, "is_generic", 2, &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"));
@@ -19353,20 +19335,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", 4, &is_var_args)))
+            if ((err = get_const_field_bool(ira, source_node, payload, "is_var_args", 3, &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", 5);
+            ZigType *return_type = get_const_field_meta_type_optional(ira, source_node, payload, "return_type", 4);
             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", 6);
+            ZigValue *args_value = get_const_field(ira, source_node, payload, "args", 5);
             if (args_value == nullptr)
                 return ira->codegen->invalid_inst_gen->value->type;
             assert(args_value->special == ConstValSpecialStatic);
src/AstGen.zig
@@ -1117,9 +1117,9 @@ fn fnProtoExpr(
         break :inst try expr(gz, scope, align_rl, fn_proto.ast.align_expr);
     };
 
-    const addrspace_inst: Zir.Inst.Ref = if (fn_proto.ast.addrspace_expr == 0) .none else inst: {
-        break :inst try expr(gz, scope, .{ .ty = .address_space_type }, fn_proto.ast.addrspace_expr);
-    };
+    if (fn_proto.ast.addrspace_expr != 0) {
+        return astgen.failNode(fn_proto.ast.addrspace_expr, "addrspace not allowed on function prototypes", .{});
+    }
 
     if (fn_proto.ast.section_expr != 0) {
         return astgen.failNode(fn_proto.ast.section_expr, "linksection not allowed on function prototypes", .{});
@@ -1153,7 +1153,6 @@ fn fnProtoExpr(
         .body = &[0]Zir.Inst.Index{},
         .cc = cc,
         .align_inst = align_inst,
-        .addrspace_inst = addrspace_inst,
         .lib_name = 0,
         .is_var_args = is_var_args,
         .is_inferred_error = false,
@@ -3089,7 +3088,6 @@ fn fnDecl(
             .body = &[0]Zir.Inst.Index{},
             .cc = cc,
             .align_inst = .none, // passed in the per-decl data
-            .addrspace_inst = .none, // passed in the per-decl data
             .lib_name = lib_name,
             .is_var_args = is_var_args,
             .is_inferred_error = false,
@@ -3129,7 +3127,6 @@ fn fnDecl(
             .body = fn_gz.instructions.items,
             .cc = cc,
             .align_inst = .none, // passed in the per-decl data
-            .addrspace_inst = .none, // passed in the per-decl data
             .lib_name = lib_name,
             .is_var_args = is_var_args,
             .is_inferred_error = is_inferred_error,
@@ -3481,7 +3478,6 @@ fn testDecl(
         .body = fn_block.instructions.items,
         .cc = .none,
         .align_inst = .none,
-        .addrspace_inst = .none,
         .lib_name = 0,
         .is_var_args = false,
         .is_inferred_error = true,
@@ -9217,7 +9213,6 @@ const GenZir = struct {
         ret_br: Zir.Inst.Index,
         cc: Zir.Inst.Ref,
         align_inst: Zir.Inst.Ref,
-        addrspace_inst: Zir.Inst.Ref,
         lib_name: u32,
         is_var_args: bool,
         is_inferred_error: bool,
@@ -9261,7 +9256,7 @@ const GenZir = struct {
 
         if (args.cc != .none or args.lib_name != 0 or
             args.is_var_args or args.is_test or args.align_inst != .none or
-            args.addrspace_inst != .none or args.is_extern)
+            args.is_extern)
         {
             try astgen.extra.ensureUnusedCapacity(
                 gpa,
@@ -9269,7 +9264,6 @@ const GenZir = struct {
                     args.ret_ty.len + args.body.len + src_locs.len +
                     @boolToInt(args.lib_name != 0) +
                     @boolToInt(args.align_inst != .none) +
-                    @boolToInt(args.addrspace_inst != .none) +
                     @boolToInt(args.cc != .none),
             );
             const payload_index = astgen.addExtraAssumeCapacity(Zir.Inst.ExtendedFunc{
@@ -9287,9 +9281,6 @@ const GenZir = struct {
             if (args.align_inst != .none) {
                 astgen.extra.appendAssumeCapacity(@enumToInt(args.align_inst));
             }
-            if (args.addrspace_inst != .none) {
-                astgen.extra.appendAssumeCapacity(@enumToInt(args.addrspace_inst));
-            }
             astgen.extra.appendSliceAssumeCapacity(args.ret_ty);
             astgen.extra.appendSliceAssumeCapacity(args.body);
             astgen.extra.appendSliceAssumeCapacity(src_locs);
@@ -9308,7 +9299,6 @@ const GenZir = struct {
                         .has_lib_name = args.lib_name != 0,
                         .has_cc = args.cc != .none,
                         .has_align = args.align_inst != .none,
-                        .has_addrspace = args.addrspace_inst != .none,
                         .is_test = args.is_test,
                         .is_extern = args.is_extern,
                     }),
src/Module.zig
@@ -3220,7 +3220,12 @@ fn semaDecl(mod: *Module, decl: *Decl) !bool {
         };
 
         break :blk switch (decl.zirAddrspaceRef()) {
-            .none => .generic,
+            .none => switch (addrspace_ctx) {
+                .function => target_util.defaultAddressSpace(sema.mod.getTarget(), .function),
+                .variable => target_util.defaultAddressSpace(sema.mod.getTarget(), .global_mutable),
+                .constant => target_util.defaultAddressSpace(sema.mod.getTarget(), .global_constant),
+                else => unreachable,
+            },
             else => |addrspace_ref| try sema.analyzeAddrspace(&block_scope, src, addrspace_ref, addrspace_ctx),
         };
     };
@@ -4359,26 +4364,21 @@ pub fn simplePtrType(
     elem_ty: Type,
     mutable: bool,
     size: std.builtin.TypeInfo.Pointer.Size,
+    @"addrspace": std.builtin.AddressSpace,
 ) Allocator.Error!Type {
-    if (!mutable and size == .Slice and elem_ty.eql(Type.initTag(.u8))) {
-        return Type.initTag(.const_slice_u8);
-    }
-    // TODO stage1 type inference bug
-    const T = Type.Tag;
-
-    const type_payload = try arena.create(Type.Payload.ElemType);
-    type_payload.* = .{
-        .base = .{
-            .tag = switch (size) {
-                .One => if (mutable) T.single_mut_pointer else T.single_const_pointer,
-                .Many => if (mutable) T.many_mut_pointer else T.many_const_pointer,
-                .C => if (mutable) T.c_mut_pointer else T.c_const_pointer,
-                .Slice => if (mutable) T.mut_slice else T.const_slice,
-            },
-        },
-        .data = elem_ty,
-    };
-    return Type.initPayload(&type_payload.base);
+    return ptrType(
+        arena,
+        elem_ty,
+        null,
+        0,
+        @"addrspace",
+        0,
+        0,
+        mutable,
+        false,
+        false,
+        size,
+    );
 }
 
 pub fn ptrType(
@@ -4396,47 +4396,43 @@ pub fn ptrType(
 ) Allocator.Error!Type {
     assert(host_size == 0 or bit_offset < host_size * 8);
 
-    // TODO check if type can be represented by simplePtrType
-    return Type.Tag.pointer.create(arena, .{
-        .pointee_type = elem_ty,
-        .sentinel = sentinel,
-        .@"align" = @"align",
-        .@"addrspace" = @"addrspace",
-        .bit_offset = bit_offset,
-        .host_size = host_size,
-        .@"allowzero" = @"allowzero",
-        .mutable = mutable,
-        .@"volatile" = @"volatile",
-        .size = size,
-    });
-}
+    if (sentinel != null or @"align" != 0 or @"addrspace" != .generic or
+        bit_offset != 0 or host_size != 0 or @"allowzero" or @"volatile")
+    {
+        return Type.Tag.pointer.create(arena, .{
+            .pointee_type = elem_ty,
+            .sentinel = sentinel,
+            .@"align" = @"align",
+            .@"addrspace" = @"addrspace",
+            .bit_offset = bit_offset,
+            .host_size = host_size,
+            .@"allowzero" = @"allowzero",
+            .mutable = mutable,
+            .@"volatile" = @"volatile",
+            .size = size,
+        });
+    }
 
-/// Create a pointer type with an explicit address space. This function might return results
-/// of either simplePtrType or ptrType, depending on the address space.
-/// TODO(Snektron) unify ptrType functions.
-pub fn simplePtrTypeWithAddressSpace(
-    arena: *Allocator,
-    elem_ty: Type,
-    mutable: bool,
-    size: std.builtin.TypeInfo.Pointer.Size,
-    address_space: std.builtin.AddressSpace,
-) Allocator.Error!Type {
-    switch (address_space) {
-        .generic => return simplePtrType(arena, elem_ty, mutable, size),
-        else => return ptrType(
-            arena,
-            elem_ty,
-            null,
-            0,
-            address_space,
-            0,
-            0,
-            mutable,
-            false,
-            false,
-            size,
-        ),
+    if (!mutable and size == .Slice and elem_ty.eql(Type.initTag(.u8))) {
+        return Type.initTag(.const_slice_u8);
     }
+
+    // TODO stage1 type inference bug
+    const T = Type.Tag;
+
+    const type_payload = try arena.create(Type.Payload.ElemType);
+    type_payload.* = .{
+        .base = .{
+            .tag = switch (size) {
+                .One => if (mutable) T.single_mut_pointer else T.single_const_pointer,
+                .Many => if (mutable) T.many_mut_pointer else T.many_const_pointer,
+                .C => if (mutable) T.c_mut_pointer else T.c_const_pointer,
+                .Slice => if (mutable) T.mut_slice else T.const_slice,
+            },
+        },
+        .data = elem_ty,
+    };
+    return Type.initPayload(&type_payload.base);
 }
 
 pub fn optionalType(arena: *Allocator, child_type: Type) Allocator.Error!Type {
src/Sema.zig
@@ -1373,7 +1373,13 @@ fn zirRetPtr(
         return sema.analyzeComptimeAlloc(block, sema.fn_ret_ty);
     }
 
-    const ptr_type = try Module.simplePtrType(sema.arena, sema.fn_ret_ty, true, .One);
+    const ptr_type = try Module.simplePtrType(
+        sema.arena,
+        sema.fn_ret_ty,
+        true,
+        .One,
+        target_util.defaultAddressSpace(sema.mod.getTarget(), .local),
+    );
     return block.addTy(.alloc, ptr_type);
 }
 
@@ -1521,7 +1527,13 @@ fn zirAlloc(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileError
     const ty_src: LazySrcLoc = .{ .node_offset_var_decl_ty = inst_data.src_node };
     const var_decl_src = inst_data.src();
     const var_type = try sema.resolveType(block, ty_src, inst_data.operand);
-    const ptr_type = try Module.simplePtrType(sema.arena, var_type, true, .One);
+    const ptr_type = try Module.simplePtrType(
+        sema.arena,
+        var_type,
+        true,
+        .One,
+        target_util.defaultAddressSpace(sema.mod.getTarget(), .local),
+    );
     try sema.requireRuntimeBlock(block, var_decl_src);
     return block.addTy(.alloc, ptr_type);
 }
@@ -1538,7 +1550,13 @@ fn zirAllocMut(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileEr
         return sema.analyzeComptimeAlloc(block, var_type);
     }
     try sema.validateVarType(block, ty_src, var_type);
-    const ptr_type = try Module.simplePtrType(sema.arena, var_type, true, .One);
+    const ptr_type = try Module.simplePtrType(
+        sema.arena,
+        var_type,
+        true,
+        .One,
+        target_util.defaultAddressSpace(sema.mod.getTarget(), .local),
+    );
     try sema.requireRuntimeBlock(block, var_decl_src);
     return block.addTy(.alloc, ptr_type);
 }
@@ -1598,7 +1616,13 @@ fn zirResolveInferredAlloc(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Inde
         try sema.mod.declareDeclDependency(sema.owner_decl, decl);
 
         const final_elem_ty = try decl.ty.copy(sema.arena);
-        const final_ptr_ty = try Module.simplePtrType(sema.arena, final_elem_ty, true, .One);
+        const final_ptr_ty = try Module.simplePtrType(
+            sema.arena,
+            final_elem_ty,
+            true,
+            .One,
+            target_util.defaultAddressSpace(sema.mod.getTarget(), .local),
+        );
         const final_ptr_ty_inst = try sema.addType(final_ptr_ty);
         sema.air_instructions.items(.data)[ptr_inst].ty_pl.ty = final_ptr_ty_inst;
 
@@ -1620,7 +1644,13 @@ fn zirResolveInferredAlloc(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Inde
             try sema.validateVarType(block, ty_src, final_elem_ty);
         }
         // Change it to a normal alloc.
-        const final_ptr_ty = try Module.simplePtrType(sema.arena, final_elem_ty, true, .One);
+        const final_ptr_ty = try Module.simplePtrType(
+            sema.arena,
+            final_elem_ty,
+            true,
+            .One,
+            target_util.defaultAddressSpace(sema.mod.getTarget(), .local),
+        );
         sema.air_instructions.set(ptr_inst, .{
             .tag = .alloc,
             .data = .{ .ty = final_ptr_ty },
@@ -1774,7 +1804,14 @@ fn zirStoreToBlockPtr(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) Co
     }
     const ptr = sema.resolveInst(bin_inst.lhs);
     const value = sema.resolveInst(bin_inst.rhs);
-    const ptr_ty = try Module.simplePtrType(sema.arena, sema.typeOf(value), true, .One);
+    const ptr_ty = try Module.simplePtrType(
+        sema.arena,
+        sema.typeOf(value),
+        true,
+        .One,
+        // TODO figure out which address space is appropriate here
+        target_util.defaultAddressSpace(sema.mod.getTarget(), .local),
+    );
     // TODO detect when this store should be done at compile-time. For example,
     // if expressions should force it when the condition is compile-time known.
     const src: LazySrcLoc = .unneeded;
@@ -1821,7 +1858,14 @@ fn zirStoreToInferredPtr(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index)
         // for the inferred allocation.
         try inferred_alloc.data.stored_inst_list.append(sema.arena, operand);
         // Create a runtime bitcast instruction with exactly the type the pointer wants.
-        const ptr_ty = try Module.simplePtrType(sema.arena, operand_ty, true, .One);
+        const ptr_ty = try Module.simplePtrType(
+            sema.arena,
+            operand_ty,
+            true,
+            .One,
+            // TODO figure out which address space is appropriate here
+            target_util.defaultAddressSpace(sema.mod.getTarget(), .local),
+        );
         const bitcasted_ptr = try block.addTyOp(.bitcast, ptr_ty, ptr);
         return sema.storePtr(block, src, bitcasted_ptr, operand);
     }
@@ -3658,7 +3702,7 @@ fn zirOptionalPayloadPtr(
     }
 
     const child_type = try opt_type.optionalChildAlloc(sema.arena);
-    const child_pointer = try Module.simplePtrTypeWithAddressSpace(
+    const child_pointer = try Module.simplePtrType(
         sema.arena,
         child_type,
         !optional_ptr_ty.isConstPtr(),
@@ -3779,7 +3823,7 @@ fn zirErrUnionPayloadPtr(
         return sema.mod.fail(&block.base, src, "expected error union type, found {}", .{operand_ty.elemType()});
 
     const payload_ty = operand_ty.elemType().errorUnionPayload();
-    const operand_pointer_ty = try Module.simplePtrTypeWithAddressSpace(
+    const operand_pointer_ty = try Module.simplePtrType(
         sema.arena,
         payload_ty,
         !operand_ty.isConstPtr(),
@@ -3907,7 +3951,6 @@ fn zirFunc(
         ret_ty_body,
         cc,
         Value.initTag(.null_value),
-        .generic,
         false,
         inferred_error_set,
         false,
@@ -3924,7 +3967,6 @@ fn funcCommon(
     ret_ty_body: []const Zir.Inst.Index,
     cc: std.builtin.CallingConvention,
     align_val: Value,
-    address_space: std.builtin.AddressSpace,
     var_args: bool,
     inferred_error_set: bool,
     is_extern: bool,
@@ -3982,7 +4024,7 @@ fn funcCommon(
         // Hot path for some common function types.
         // TODO can we eliminate some of these Type tag values? seems unnecessarily complicated.
         if (!is_generic and block.params.items.len == 0 and !var_args and
-            align_val.tag() == .null_value and !inferred_error_set and address_space == .generic)
+            align_val.tag() == .null_value and !inferred_error_set)
         {
             if (bare_return_type.zigTypeTag() == .NoReturn and cc == .Unspecified) {
                 break :fn_ty Type.initTag(.fn_noreturn_no_args);
@@ -4034,7 +4076,6 @@ fn funcCommon(
             .comptime_params = comptime_params.ptr,
             .return_type = return_type,
             .cc = cc,
-            .@"addrspace" = address_space,
             .is_var_args = var_args,
             .is_generic = is_generic,
         });
@@ -6413,7 +6454,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, 7);
+            const field_values = try sema.arena.alloc(Value, 6);
             // calling_convention: CallingConvention,
             field_values[0] = try Value.Tag.enum_field_index.create(
                 sema.arena,
@@ -6421,19 +6462,14 @@ 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[3] = Value.initTag(.bool_false); // TODO
+            field_values[2] = Value.initTag(.bool_false); // TODO
             // is_var_args: bool,
-            field_values[4] = Value.initTag(.bool_false); // TODO
+            field_values[3] = Value.initTag(.bool_false); // TODO
             // return_type: ?type,
-            field_values[5] = try Value.Tag.ty.create(sema.arena, ty.fnReturnType());
+            field_values[4] = try Value.Tag.ty.create(sema.arena, ty.fnReturnType());
             // args: []const FnArg,
-            field_values[6] = Value.initTag(.null_value); // TODO
+            field_values[5] = Value.initTag(.null_value); // TODO
 
             return sema.addConstant(
                 type_info_ty,
@@ -8063,7 +8099,6 @@ fn zirFuncExtended(
     const src: LazySrcLoc = .{ .node_offset = extra.data.src_node };
     const cc_src: LazySrcLoc = .{ .node_offset_fn_type_cc = extra.data.src_node };
     const align_src: LazySrcLoc = src; // TODO add a LazySrcLoc that points at align
-    const addrspace_src: LazySrcLoc = src; // TODO(Snektron) add a LazySrcLoc that points at addrspace
     const small = @bitCast(Zir.Inst.ExtendedFunc.Small, extended.small);
 
     var extra_index: usize = extra.end;
@@ -8088,12 +8123,6 @@ fn zirFuncExtended(
         break :blk align_tv.val;
     } else Value.initTag(.null_value);
 
-    const address_space: std.builtin.AddressSpace = if (small.has_addrspace) blk: {
-        const addrspace_ref = @intToEnum(Zir.Inst.Ref, sema.code.extra[extra_index]);
-        extra_index += 1;
-        break :blk try sema.analyzeAddrspace(block, addrspace_src, addrspace_ref, .function);
-    } else .generic;
-
     const ret_ty_body = sema.code.extra[extra_index..][0..extra.data.ret_body_len];
     extra_index += ret_ty_body.len;
 
@@ -8116,7 +8145,6 @@ fn zirFuncExtended(
         ret_ty_body,
         cc,
         align_val,
-        address_space,
         is_var_args,
         is_inferred_error,
         is_extern,
@@ -8309,7 +8337,13 @@ fn panicWithMsg(
     const panic_fn = try sema.getBuiltin(block, src, "panic");
     const unresolved_stack_trace_ty = try sema.getBuiltinType(block, src, "StackTrace");
     const stack_trace_ty = try sema.resolveTypeFields(block, src, unresolved_stack_trace_ty);
-    const ptr_stack_trace_ty = try Module.simplePtrType(arena, stack_trace_ty, true, .One);
+    const ptr_stack_trace_ty = try Module.simplePtrType(
+        arena,
+        stack_trace_ty,
+        true,
+        .One,
+        target_util.defaultAddressSpace(sema.mod.getTarget(), .global_constant), // TODO might need a place that is more dynamic
+    );
     const null_stack_trace = try sema.addConstant(
         try Module.optionalType(arena, ptr_stack_trace_ty),
         Value.initTag(.null_value),
@@ -8788,7 +8822,7 @@ fn structFieldPtr(
     const field_index = struct_obj.fields.getIndex(field_name) orelse
         return sema.failWithBadFieldAccess(block, struct_obj, field_name_src, field_name);
     const field = struct_obj.fields.values()[field_index];
-    const ptr_field_ty = try Module.simplePtrTypeWithAddressSpace(
+    const ptr_field_ty = try Module.simplePtrType(
         arena,
         field.ty,
         struct_ptr_ty.ptrIsMutable(),
@@ -8893,7 +8927,7 @@ fn unionFieldPtr(
         return sema.failWithBadUnionFieldAccess(block, union_obj, field_name_src, field_name);
 
     const field = union_obj.fields.values()[field_index];
-    const ptr_field_ty = try Module.simplePtrTypeWithAddressSpace(
+    const ptr_field_ty = try Module.simplePtrType(
         arena,
         field.ty,
         union_ptr_ty.ptrIsMutable(),
@@ -9075,7 +9109,7 @@ fn elemPtrArray(
 ) CompileError!Air.Inst.Ref {
     const array_ptr_ty = sema.typeOf(array_ptr);
     const pointee_type = array_ptr_ty.elemType().elemType();
-    const result_ty = try Module.simplePtrTypeWithAddressSpace(
+    const result_ty = try Module.simplePtrType(
         sema.arena,
         pointee_type,
         array_ptr_ty.ptrIsMutable(),
@@ -9581,11 +9615,11 @@ fn analyzeDeclRef(sema: *Sema, decl: *Decl) CompileError!Air.Inst.Ref {
     const decl_tv = try decl.typedValue();
     if (decl_tv.val.castTag(.variable)) |payload| {
         const variable = payload.data;
-        const ty = try Module.simplePtrTypeWithAddressSpace(sema.arena, decl_tv.ty, variable.is_mutable, .One, decl.@"addrspace");
+        const ty = try Module.simplePtrType(sema.arena, decl_tv.ty, variable.is_mutable, .One, decl.@"addrspace");
         return sema.addConstant(ty, try Value.Tag.decl_ref.create(sema.arena, decl));
     }
     return sema.addConstant(
-        try Module.simplePtrTypeWithAddressSpace(sema.arena, decl_tv.ty, false, .One, decl.@"addrspace"),
+        try Module.simplePtrType(sema.arena, decl_tv.ty, false, .One, decl.@"addrspace"),
         try Value.Tag.decl_ref.create(sema.arena, decl),
     );
 }
@@ -9608,8 +9642,9 @@ fn analyzeRef(
     }
 
     try sema.requireRuntimeBlock(block, src);
-    const ptr_type = try Module.simplePtrType(sema.arena, operand_ty, false, .One);
-    const mut_ptr_type = try Module.simplePtrType(sema.arena, operand_ty, true, .One);
+    const address_space = target_util.defaultAddressSpace(sema.mod.getTarget(), .local);
+    const ptr_type = try Module.simplePtrType(sema.arena, operand_ty, false, .One, address_space);
+    const mut_ptr_type = try Module.simplePtrType(sema.arena, operand_ty, true, .One, address_space);
     const alloc = try block.addTy(.alloc, mut_ptr_type);
     try sema.storePtr(block, src, alloc, operand);
 
@@ -10955,7 +10990,13 @@ fn analyzeComptimeAlloc(
     block: *Scope.Block,
     var_type: Type,
 ) CompileError!Air.Inst.Ref {
-    const ptr_type = try Module.simplePtrType(sema.arena, var_type, true, .One);
+    const ptr_type = try Module.simplePtrType(
+        sema.arena,
+        var_type,
+        true,
+        .One,
+        target_util.defaultAddressSpace(sema.mod.getTarget(), .global_constant),
+    );
 
     var anon_decl = try block.startAnonDecl();
     defer anon_decl.deinit();
src/target.zig
@@ -544,3 +544,21 @@ pub fn largestAtomicBits(target: std.Target) u32 {
         .x86_64 => 128,
     };
 }
+
+pub fn defaultAddressSpace(
+    target: std.Target,
+    context: enum {
+        /// Query the default address space for global constant values.
+        global_constant,
+        /// Query the default address space for global mutable values.
+        global_mutable,
+        /// Query the default address space for function-local values.
+        local,
+        /// Query the default address space for functions themselves.
+        function,
+    },
+) std.builtin.AddressSpace {
+    _ = target;
+    _ = context;
+    return .generic;
+}
src/type.zig
@@ -530,8 +530,6 @@ pub const Type = extern union {
                     return false;
                 if (a.fnCallingConvention() != b.fnCallingConvention())
                     return false;
-                if (a.fnAddressSpace() != b.fnAddressSpace())
-                    return false;
                 const a_param_len = a.fnParamLen();
                 const b_param_len = b.fnParamLen();
                 if (a_param_len != b_param_len)
@@ -838,7 +836,6 @@ pub const Type = extern union {
                     .return_type = try payload.return_type.copy(allocator),
                     .param_types = param_types,
                     .cc = payload.cc,
-                    .@"addrspace" = payload.@"addrspace",
                     .is_var_args = payload.is_var_args,
                     .is_generic = payload.is_generic,
                     .comptime_params = comptime_params.ptr,
@@ -1001,9 +998,6 @@ pub const Type = extern union {
                     try writer.writeAll(") callconv(.");
                     try writer.writeAll(@tagName(payload.cc));
                     try writer.writeAll(") ");
-                    if (payload.@"addrspace" != .generic) {
-                        try writer.print("addrspace(.{s}) ", .{@tagName(payload.@"addrspace")});
-                    }
                     ty = payload.return_type;
                     continue;
                 },
@@ -2730,18 +2724,6 @@ pub const Type = extern union {
         };
     }
 
-    pub fn fnAddressSpace(self: Type) std.builtin.AddressSpace {
-        return switch (self.tag()) {
-            .fn_noreturn_no_args => .generic,
-            .fn_void_no_args => .generic,
-            .fn_naked_noreturn_no_args => .generic,
-            .fn_ccc_void_no_args => .generic,
-            .function => self.castTag(.function).?.data.@"addrspace",
-
-            else => unreachable,
-        };
-    }
-
     pub fn fnInfo(ty: Type) Payload.Function.Data {
         return switch (ty.tag()) {
             .fn_noreturn_no_args => .{
@@ -2749,7 +2731,6 @@ pub const Type = extern union {
                 .comptime_params = undefined,
                 .return_type = initTag(.noreturn),
                 .cc = .Unspecified,
-                .@"addrspace" = .generic,
                 .is_var_args = false,
                 .is_generic = false,
             },
@@ -2758,7 +2739,6 @@ pub const Type = extern union {
                 .comptime_params = undefined,
                 .return_type = initTag(.void),
                 .cc = .Unspecified,
-                .@"addrspace" = .generic,
                 .is_var_args = false,
                 .is_generic = false,
             },
@@ -2767,7 +2747,6 @@ pub const Type = extern union {
                 .comptime_params = undefined,
                 .return_type = initTag(.noreturn),
                 .cc = .Naked,
-                .@"addrspace" = .generic,
                 .is_var_args = false,
                 .is_generic = false,
             },
@@ -2776,7 +2755,6 @@ pub const Type = extern union {
                 .comptime_params = undefined,
                 .return_type = initTag(.void),
                 .cc = .C,
-                .@"addrspace" = .generic,
                 .is_var_args = false,
                 .is_generic = false,
             },
@@ -3648,7 +3626,6 @@ pub const Type = extern union {
                 comptime_params: [*]bool,
                 return_type: Type,
                 cc: std.builtin.CallingConvention,
-                @"addrspace": std.builtin.AddressSpace,
                 is_var_args: bool,
                 is_generic: bool,
 
src/Zir.zig
@@ -2309,7 +2309,6 @@ pub const Inst = struct {
     /// 0. lib_name: u32, // null terminated string index, if has_lib_name is set
     /// 1. cc: Ref, // if has_cc is set
     /// 2. align: Ref, // if has_align is set
-    /// 3. addrspace: Ref, // if has_addrspace is set
     /// 3. return_type: Index // for each ret_body_len
     /// 4. body: Index // for each body_len
     /// 5. src_locs: Func.SrcLocs // if body_len != 0
@@ -2327,10 +2326,9 @@ pub const Inst = struct {
             has_lib_name: bool,
             has_cc: bool,
             has_align: bool,
-            has_addrspace: bool,
             is_test: bool,
             is_extern: bool,
-            _: u8 = undefined,
+            _: u9 = undefined,
         };
     };
 
@@ -4483,7 +4481,6 @@ const Writer = struct {
             false,
             .none,
             .none,
-            .none,
             body,
             src,
             src_locs,
@@ -4512,11 +4509,6 @@ const Writer = struct {
             extra_index += 1;
             break :blk align_inst;
         };
-        const addrspace_inst: Inst.Ref = if (!small.has_addrspace) .none else blk: {
-            const addrspace_inst = @intToEnum(Zir.Inst.Ref, self.code.extra[extra_index]);
-            extra_index += 1;
-            break :blk addrspace_inst;
-        };
 
         const ret_ty_body = self.code.extra[extra_index..][0..extra.data.ret_body_len];
         extra_index += ret_ty_body.len;
@@ -4536,7 +4528,6 @@ const Writer = struct {
             small.is_extern,
             cc,
             align_inst,
-            addrspace_inst,
             body,
             src,
             src_locs,
@@ -4619,7 +4610,6 @@ const Writer = struct {
         is_extern: bool,
         cc: Inst.Ref,
         align_inst: Inst.Ref,
-        addrspace_inst: Inst.Ref,
         body: []const Inst.Index,
         src: LazySrcLoc,
         src_locs: Zir.Inst.Func.SrcLocs,
@@ -4637,7 +4627,6 @@ const Writer = struct {
 
         try self.writeOptionalInstRef(stream, ", cc=", cc);
         try self.writeOptionalInstRef(stream, ", align=", align_inst);
-        try self.writeOptionalInstRef(stream, ", addrspace=", addrspace_inst);
         try self.writeFlag(stream, ", vargs", var_args);
         try self.writeFlag(stream, ", extern", is_extern);
         try self.writeFlag(stream, ", inferror", inferred_error_set);
@@ -4915,7 +4904,6 @@ fn findDeclsInner(
                     extra_index += @boolToInt(small.has_lib_name);
                     extra_index += @boolToInt(small.has_cc);
                     extra_index += @boolToInt(small.has_align);
-                    extra_index += @boolToInt(small.has_addrspace);
                     const body = zir.extra[extra_index..][0..extra.data.body_len];
                     return zir.findDeclsBody(list, body);
                 },
@@ -5119,7 +5107,6 @@ pub fn getFnInfo(zir: Zir, fn_inst: Inst.Index) FnInfo {
             extra_index += @boolToInt(small.has_lib_name);
             extra_index += @boolToInt(small.has_cc);
             extra_index += @boolToInt(small.has_align);
-            extra_index += @boolToInt(small.has_addrspace);
             const ret_ty_body = zir.extra[extra_index..][0..extra.data.ret_body_len];
             extra_index += ret_ty_body.len;
             const body = zir.extra[extra_index..][0..extra.data.body_len];
test/compile_errors.zig
@@ -410,7 +410,6 @@ pub fn addCases(ctx: *TestContext) !void {
         \\    .Fn = .{
         \\        .calling_convention = .Unspecified,
         \\        .alignment = 0,
-        \\        .address_space = .generic,
         \\        .is_generic = true,
         \\        .is_var_args = false,
         \\        .return_type = u0,
@@ -427,7 +426,6 @@ pub fn addCases(ctx: *TestContext) !void {
         \\    .Fn = .{
         \\        .calling_convention = .Unspecified,
         \\        .alignment = 0,
-        \\        .address_space = .generic,
         \\        .is_generic = false,
         \\        .is_var_args = true,
         \\        .return_type = u0,
@@ -444,7 +442,6 @@ pub fn addCases(ctx: *TestContext) !void {
         \\    .Fn = .{
         \\        .calling_convention = .Unspecified,
         \\        .alignment = 0,
-        \\        .address_space = .generic,
         \\        .is_generic = false,
         \\        .is_var_args = false,
         \\        .return_type = null,
@@ -456,23 +453,6 @@ pub fn addCases(ctx: *TestContext) !void {
         "tmp.zig:1:20: error: TypeInfo.Fn.return_type must be non-null for @Type",
     });
 
-    ctx.objErrStage1("@Type(.Fn) with invalid address space ",
-        \\const Foo = @Type(.{
-        \\    .Fn = .{
-        \\        .calling_convention = .Unspecified,
-        \\        .alignment = 0,
-        \\        .address_space = .fs,
-        \\        .is_generic = false,
-        \\        .is_var_args = false,
-        \\        .return_type = u0,
-        \\        .args = &[_]@import("std").builtin.TypeInfo.FnArg{},
-        \\    },
-        \\});
-        \\comptime { _ = Foo; }
-    , &[_][]const u8{
-        "tmp.zig:1:20: error: address space 'fs' not available in stage 1 compiler, must be .generic",
-    });
-
     ctx.objErrStage1("@Type for union with opaque field",
         \\const TypeInfo = @import("std").builtin.TypeInfo;
         \\const Untagged = @Type(.{