aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/Module.zig6
-rw-r--r--src/astgen.zig2
-rw-r--r--src/type.zig102
-rw-r--r--src/zir_sema.zig46
4 files changed, 108 insertions, 48 deletions
diff --git a/src/Module.zig b/src/Module.zig
index 884b5fb8d4..5ea78d06d1 100644
--- a/src/Module.zig
+++ b/src/Module.zig
@@ -3421,3 +3421,9 @@ pub fn getTarget(self: Module) Target {
pub fn optimizeMode(self: Module) std.builtin.Mode {
return self.comp.bin_file.options.optimize_mode;
}
+
+pub fn validateVarType(mod: *Module, scope: *Scope, src: usize, ty: Type) !void {
+ if (!ty.isValidVarType(false)) {
+ return mod.fail(scope, src, "variable of type '{}' must be const or comptime", .{ty});
+ }
+}
diff --git a/src/astgen.zig b/src/astgen.zig
index 1142907faf..5cf8e12587 100644
--- a/src/astgen.zig
+++ b/src/astgen.zig
@@ -625,7 +625,7 @@ fn varDecl(
const alloc = try addZIRUnOp(mod, scope, name_src, .alloc_mut, type_inst);
break :a .{ .alloc = alloc, .result_loc = .{ .ptr = alloc } };
} else a: {
- const alloc = try addZIRNoOpT(mod, scope, name_src, .alloc_inferred);
+ const alloc = try addZIRNoOpT(mod, scope, name_src, .alloc_inferred_mut);
resolve_inferred_alloc = &alloc.base;
break :a .{ .alloc = &alloc.base, .result_loc = .{ .inferred_ptr = alloc } };
};
diff --git a/src/type.zig b/src/type.zig
index 5e4182b1b6..7d35200727 100644
--- a/src/type.zig
+++ b/src/type.zig
@@ -78,7 +78,8 @@ pub const Type = extern union {
.const_slice,
.mut_slice,
.pointer,
- .inferred_alloc,
+ .inferred_alloc_const,
+ .inferred_alloc_mut,
=> return .Pointer,
.optional,
@@ -159,7 +160,8 @@ pub const Type = extern union {
.optional_single_mut_pointer,
=> self.cast(Payload.ElemType),
- .inferred_alloc => unreachable,
+ .inferred_alloc_const => unreachable,
+ .inferred_alloc_mut => unreachable,
else => null,
};
@@ -387,7 +389,8 @@ pub const Type = extern union {
.enum_literal,
.anyerror_void_error_union,
.@"anyframe",
- .inferred_alloc,
+ .inferred_alloc_const,
+ .inferred_alloc_mut,
=> unreachable,
.array_u8,
@@ -690,7 +693,8 @@ pub const Type = extern union {
const name = ty.castTag(.error_set_single).?.data;
return out_stream.print("error{{{s}}}", .{name});
},
- .inferred_alloc => return out_stream.writeAll("(inferred allocation type)"),
+ .inferred_alloc_const => return out_stream.writeAll("(inferred_alloc_const)"),
+ .inferred_alloc_mut => return out_stream.writeAll("(inferred_alloc_mut)"),
}
unreachable;
}
@@ -738,7 +742,8 @@ pub const Type = extern union {
.single_const_pointer_to_comptime_int => return Value.initTag(.single_const_pointer_to_comptime_int_type),
.const_slice_u8 => return Value.initTag(.const_slice_u8_type),
.enum_literal => return Value.initTag(.enum_literal_type),
- .inferred_alloc => unreachable,
+ .inferred_alloc_const => unreachable,
+ .inferred_alloc_mut => unreachable,
else => return Value.Tag.ty.create(allocator, self),
}
}
@@ -810,7 +815,8 @@ pub const Type = extern union {
.empty_struct,
=> false,
- .inferred_alloc => unreachable,
+ .inferred_alloc_const => unreachable,
+ .inferred_alloc_mut => unreachable,
};
}
@@ -928,7 +934,8 @@ pub const Type = extern union {
.@"undefined",
.enum_literal,
.empty_struct,
- .inferred_alloc,
+ .inferred_alloc_const,
+ .inferred_alloc_mut,
=> unreachable,
};
}
@@ -952,7 +959,8 @@ pub const Type = extern union {
.enum_literal => unreachable,
.single_const_pointer_to_comptime_int => unreachable,
.empty_struct => unreachable,
- .inferred_alloc => unreachable,
+ .inferred_alloc_const => unreachable,
+ .inferred_alloc_mut => unreachable,
.u8,
.i8,
@@ -1131,7 +1139,8 @@ pub const Type = extern union {
.single_const_pointer,
.single_mut_pointer,
.single_const_pointer_to_comptime_int,
- .inferred_alloc,
+ .inferred_alloc_const,
+ .inferred_alloc_mut,
=> true,
.pointer => self.castTag(.pointer).?.data.size == .One,
@@ -1214,7 +1223,8 @@ pub const Type = extern union {
.single_const_pointer,
.single_mut_pointer,
.single_const_pointer_to_comptime_int,
- .inferred_alloc,
+ .inferred_alloc_const,
+ .inferred_alloc_mut,
=> .One,
.pointer => self.castTag(.pointer).?.data.size,
@@ -1285,7 +1295,8 @@ pub const Type = extern union {
.error_set,
.error_set_single,
.empty_struct,
- .inferred_alloc,
+ .inferred_alloc_const,
+ .inferred_alloc_mut,
=> false,
.const_slice,
@@ -1358,7 +1369,8 @@ pub const Type = extern union {
.error_set,
.error_set_single,
.empty_struct,
- .inferred_alloc,
+ .inferred_alloc_const,
+ .inferred_alloc_mut,
=> false,
.single_const_pointer,
@@ -1440,7 +1452,8 @@ pub const Type = extern union {
.error_set,
.error_set_single,
.empty_struct,
- .inferred_alloc,
+ .inferred_alloc_const,
+ .inferred_alloc_mut,
=> false,
.pointer => {
@@ -1517,7 +1530,8 @@ pub const Type = extern union {
.error_set,
.error_set_single,
.empty_struct,
- .inferred_alloc,
+ .inferred_alloc_const,
+ .inferred_alloc_mut,
=> false,
.pointer => {
@@ -1636,7 +1650,8 @@ pub const Type = extern union {
.error_set => unreachable,
.error_set_single => unreachable,
.empty_struct => unreachable,
- .inferred_alloc => unreachable,
+ .inferred_alloc_const => unreachable,
+ .inferred_alloc_mut => unreachable,
.array => self.castTag(.array).?.data.elem_type,
.array_sentinel => self.castTag(.array_sentinel).?.data.elem_type,
@@ -1758,7 +1773,8 @@ pub const Type = extern union {
.error_set,
.error_set_single,
.empty_struct,
- .inferred_alloc,
+ .inferred_alloc_const,
+ .inferred_alloc_mut,
=> unreachable,
.array => self.castTag(.array).?.data.len,
@@ -1825,7 +1841,8 @@ pub const Type = extern union {
.error_set,
.error_set_single,
.empty_struct,
- .inferred_alloc,
+ .inferred_alloc_const,
+ .inferred_alloc_mut,
=> unreachable,
.single_const_pointer,
@@ -1909,7 +1926,8 @@ pub const Type = extern union {
.error_set,
.error_set_single,
.empty_struct,
- .inferred_alloc,
+ .inferred_alloc_const,
+ .inferred_alloc_mut,
=> false,
.int_signed,
@@ -1985,7 +2003,8 @@ pub const Type = extern union {
.error_set,
.error_set_single,
.empty_struct,
- .inferred_alloc,
+ .inferred_alloc_const,
+ .inferred_alloc_mut,
=> false,
.int_unsigned,
@@ -2051,7 +2070,8 @@ pub const Type = extern union {
.error_set,
.error_set_single,
.empty_struct,
- .inferred_alloc,
+ .inferred_alloc_const,
+ .inferred_alloc_mut,
=> unreachable,
.int_unsigned => .{
@@ -2141,7 +2161,8 @@ pub const Type = extern union {
.error_set,
.error_set_single,
.empty_struct,
- .inferred_alloc,
+ .inferred_alloc_const,
+ .inferred_alloc_mut,
=> false,
.usize,
@@ -2254,7 +2275,8 @@ pub const Type = extern union {
.error_set,
.error_set_single,
.empty_struct,
- .inferred_alloc,
+ .inferred_alloc_const,
+ .inferred_alloc_mut,
=> unreachable,
};
}
@@ -2333,7 +2355,8 @@ pub const Type = extern union {
.error_set,
.error_set_single,
.empty_struct,
- .inferred_alloc,
+ .inferred_alloc_const,
+ .inferred_alloc_mut,
=> unreachable,
}
}
@@ -2411,7 +2434,8 @@ pub const Type = extern union {
.error_set,
.error_set_single,
.empty_struct,
- .inferred_alloc,
+ .inferred_alloc_const,
+ .inferred_alloc_mut,
=> unreachable,
}
}
@@ -2489,7 +2513,8 @@ pub const Type = extern union {
.error_set,
.error_set_single,
.empty_struct,
- .inferred_alloc,
+ .inferred_alloc_const,
+ .inferred_alloc_mut,
=> unreachable,
};
}
@@ -2564,7 +2589,8 @@ pub const Type = extern union {
.error_set,
.error_set_single,
.empty_struct,
- .inferred_alloc,
+ .inferred_alloc_const,
+ .inferred_alloc_mut,
=> unreachable,
};
}
@@ -2639,7 +2665,8 @@ pub const Type = extern union {
.error_set,
.error_set_single,
.empty_struct,
- .inferred_alloc,
+ .inferred_alloc_const,
+ .inferred_alloc_mut,
=> unreachable,
};
}
@@ -2714,7 +2741,8 @@ pub const Type = extern union {
.error_set,
.error_set_single,
.empty_struct,
- .inferred_alloc,
+ .inferred_alloc_const,
+ .inferred_alloc_mut,
=> false,
};
}
@@ -2807,7 +2835,8 @@ pub const Type = extern union {
ty = ty.castTag(.pointer).?.data.pointee_type;
continue;
},
- .inferred_alloc => unreachable,
+ .inferred_alloc_const => unreachable,
+ .inferred_alloc_mut => unreachable,
};
}
@@ -2876,7 +2905,8 @@ pub const Type = extern union {
.error_set,
.error_set_single,
.empty_struct,
- .inferred_alloc,
+ .inferred_alloc_const,
+ .inferred_alloc_mut,
=> return false,
.c_const_pointer,
@@ -2962,7 +2992,8 @@ pub const Type = extern union {
.c_const_pointer,
.c_mut_pointer,
.pointer,
- .inferred_alloc,
+ .inferred_alloc_const,
+ .inferred_alloc_mut,
=> unreachable,
.empty_struct => self.castTag(.empty_struct).?.data,
@@ -3077,7 +3108,9 @@ pub const Type = extern union {
/// This is a special value that tracks a set of types that have been stored
/// to an inferred allocation. It does not support most of the normal type queries.
/// However it does respond to `isConstPtr`, `ptrSize`, `zigTypeTag`, etc.
- inferred_alloc, // See last_no_payload_tag below.
+ inferred_alloc_mut,
+ /// Same as `inferred_alloc_mut` but the local is `var` not `const`.
+ inferred_alloc_const, // See last_no_payload_tag below.
// After this, the tag requires a payload.
array_u8,
@@ -3105,7 +3138,7 @@ pub const Type = extern union {
error_set_single,
empty_struct,
- pub const last_no_payload_tag = Tag.inferred_alloc;
+ pub const last_no_payload_tag = Tag.inferred_alloc_const;
pub const no_payload_count = @enumToInt(last_no_payload_tag) + 1;
pub fn Type(comptime t: Tag) type {
@@ -3152,7 +3185,8 @@ pub const Type = extern union {
.anyerror_void_error_union,
.@"anyframe",
.const_slice_u8,
- .inferred_alloc,
+ .inferred_alloc_const,
+ .inferred_alloc_mut,
=> @compileError("Type Tag " ++ @tagName(t) ++ " has no payload"),
.array_u8,
diff --git a/src/zir_sema.zig b/src/zir_sema.zig
index 87b96825f9..629dfa0c9a 100644
--- a/src/zir_sema.zig
+++ b/src/zir_sema.zig
@@ -30,8 +30,18 @@ pub fn analyzeInst(mod: *Module, scope: *Scope, old_inst: *zir.Inst) InnerError!
switch (old_inst.tag) {
.alloc => return analyzeInstAlloc(mod, scope, old_inst.castTag(.alloc).?),
.alloc_mut => return analyzeInstAllocMut(mod, scope, old_inst.castTag(.alloc_mut).?),
- .alloc_inferred => return analyzeInstAllocInferred(mod, scope, old_inst.castTag(.alloc_inferred).?),
- .alloc_inferred_mut => return analyzeInstAllocInferredMut(mod, scope, old_inst.castTag(.alloc_inferred_mut).?),
+ .alloc_inferred => return analyzeInstAllocInferred(
+ mod,
+ scope,
+ old_inst.castTag(.alloc_inferred).?,
+ .inferred_alloc_const,
+ ),
+ .alloc_inferred_mut => return analyzeInstAllocInferred(
+ mod,
+ scope,
+ old_inst.castTag(.alloc_inferred_mut).?,
+ .inferred_alloc_mut,
+ ),
.arg => return analyzeInstArg(mod, scope, old_inst.castTag(.arg).?),
.bitcast_ref => return analyzeInstBitCastRef(mod, scope, old_inst.castTag(.bitcast_ref).?),
.bitcast_result_ptr => return analyzeInstBitCastResultPtr(mod, scope, old_inst.castTag(.bitcast_result_ptr).?),
@@ -423,15 +433,18 @@ fn analyzeInstAlloc(mod: *Module, scope: *Scope, inst: *zir.Inst.UnOp) InnerErro
fn analyzeInstAllocMut(mod: *Module, scope: *Scope, inst: *zir.Inst.UnOp) InnerError!*Inst {
const var_type = try resolveType(mod, scope, inst.positionals.operand);
- if (!var_type.isValidVarType(false)) {
- return mod.fail(scope, inst.base.src, "variable of type '{}' must be const or comptime", .{var_type});
- }
+ try mod.validateVarType(scope, inst.base.src, var_type);
const ptr_type = try mod.simplePtrType(scope, inst.base.src, var_type, true, .One);
const b = try mod.requireRuntimeBlock(scope, inst.base.src);
return mod.addNoOp(b, inst.base.src, ptr_type, .alloc);
}
-fn analyzeInstAllocInferred(mod: *Module, scope: *Scope, inst: *zir.Inst.NoOp) InnerError!*Inst {
+fn analyzeInstAllocInferred(
+ mod: *Module,
+ scope: *Scope,
+ inst: *zir.Inst.NoOp,
+ mut_tag: Type.Tag,
+) InnerError!*Inst {
const val_payload = try scope.arena().create(Value.Payload.InferredAlloc);
val_payload.* = .{
.data = .{},
@@ -441,7 +454,11 @@ fn analyzeInstAllocInferred(mod: *Module, scope: *Scope, inst: *zir.Inst.NoOp) I
// to a normal instruction when we hit `resolve_inferred_alloc`. So we append
// to the block even though it is currently a `.constant`.
const result = try mod.constInst(scope, inst.base.src, .{
- .ty = Type.initTag(.inferred_alloc),
+ .ty = switch (mut_tag) {
+ .inferred_alloc_const => Type.initTag(.inferred_alloc_const),
+ .inferred_alloc_mut => Type.initTag(.inferred_alloc_mut),
+ else => unreachable,
+ },
.val = Value.initPayload(&val_payload.base),
});
const block = try mod.requireFunctionBlock(scope, inst.base.src);
@@ -449,10 +466,6 @@ fn analyzeInstAllocInferred(mod: *Module, scope: *Scope, inst: *zir.Inst.NoOp) I
return result;
}
-fn analyzeInstAllocInferredMut(mod: *Module, scope: *Scope, inst: *zir.Inst.NoOp) InnerError!*Inst {
- return mod.fail(scope, inst.base.src, "TODO implement analyzeInstAllocInferredMut", .{});
-}
-
fn analyzeInstResolveInferredAlloc(
mod: *Module,
scope: *Scope,
@@ -463,8 +476,15 @@ fn analyzeInstResolveInferredAlloc(
const inferred_alloc = ptr_val.castTag(.inferred_alloc).?;
const peer_inst_list = inferred_alloc.data.stored_inst_list.items;
const final_elem_ty = try mod.resolvePeerTypes(scope, peer_inst_list);
- const is_mut = true;
- const final_ptr_ty = try mod.simplePtrType(scope, inst.base.src, final_elem_ty, is_mut, .One);
+ const var_is_mut = switch (ptr.ty.tag()) {
+ .inferred_alloc_const => false,
+ .inferred_alloc_mut => true,
+ else => unreachable,
+ };
+ if (var_is_mut) {
+ try mod.validateVarType(scope, inst.base.src, final_elem_ty);
+ }
+ const final_ptr_ty = try mod.simplePtrType(scope, inst.base.src, final_elem_ty, true, .One);
// Change it to a normal alloc.
ptr.ty = final_ptr_ty;