aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Kelley <andrew@ziglang.org>2021-12-27 17:56:33 -0700
committerAndrew Kelley <andrew@ziglang.org>2021-12-27 17:56:33 -0700
commit9dd4fb4130a71d2aaaaa361d8ee0b7135cb84162 (patch)
tree569ebd4a536b1df12976d6c6c19e3725ef6b7e98
parent886df772f06377df95f867e8b18ee47bbd0fcd8b (diff)
downloadzig-9dd4fb4130a71d2aaaaa361d8ee0b7135cb84162.tar.gz
zig-9dd4fb4130a71d2aaaaa361d8ee0b7135cb84162.zip
stage2: fix 0-bit function parameters
Before this commit, Zig would incorrectly emit `arg` AIR instructions for parameters whose types were 0-bit.
-rw-r--r--src/Module.zig24
-rw-r--r--src/Sema.zig8
-rw-r--r--test/behavior/enum_llvm.zig32
-rw-r--r--test/behavior/enum_stage1.zig32
4 files changed, 54 insertions, 42 deletions
diff --git a/src/Module.zig b/src/Module.zig
index 25e262855c..2c5c01bb7a 100644
--- a/src/Module.zig
+++ b/src/Module.zig
@@ -4327,16 +4327,16 @@ pub fn analyzeFnBody(mod: *Module, decl: *Decl, func: *Fn, arena: Allocator) Sem
var runtime_param_index: usize = 0;
var total_param_index: usize = 0;
for (fn_info.param_body) |inst| {
- const name = switch (zir_tags[inst]) {
+ const param: struct { name: u32, src: LazySrcLoc } = switch (zir_tags[inst]) {
.param, .param_comptime => blk: {
- const inst_data = sema.code.instructions.items(.data)[inst].pl_tok;
- const extra = sema.code.extraData(Zir.Inst.Param, inst_data.payload_index).data;
- break :blk extra.name;
+ const pl_tok = sema.code.instructions.items(.data)[inst].pl_tok;
+ const extra = sema.code.extraData(Zir.Inst.Param, pl_tok.payload_index).data;
+ break :blk .{ .name = extra.name, .src = pl_tok.src() };
},
.param_anytype, .param_anytype_comptime => blk: {
const str_tok = sema.code.instructions.items(.data)[inst].str_tok;
- break :blk str_tok.start;
+ break :blk .{ .name = str_tok.start, .src = str_tok.src() };
},
else => continue,
@@ -4352,6 +4352,18 @@ pub fn analyzeFnBody(mod: *Module, decl: *Decl, func: *Fn, arena: Allocator) Sem
}
}
const param_type = fn_ty.fnParamType(runtime_param_index);
+ const opt_opv = sema.typeHasOnePossibleValue(&inner_block, param.src, param_type) catch |err| switch (err) {
+ error.NeededSourceLocation => unreachable,
+ error.GenericPoison => unreachable,
+ error.ComptimeReturn => unreachable,
+ else => |e| return e,
+ };
+ if (opt_opv) |opv| {
+ const arg = try sema.addConstant(param_type, opv);
+ sema.inst_map.putAssumeCapacityNoClobber(inst, arg);
+ total_param_index += 1;
+ continue;
+ }
const ty_ref = try sema.addType(param_type);
const arg_index = @intCast(u32, sema.air_instructions.len);
inner_block.instructions.appendAssumeCapacity(arg_index);
@@ -4359,7 +4371,7 @@ pub fn analyzeFnBody(mod: *Module, decl: *Decl, func: *Fn, arena: Allocator) Sem
.tag = .arg,
.data = .{ .ty_str = .{
.ty = ty_ref,
- .str = name,
+ .str = param.name,
} },
});
sema.inst_map.putAssumeCapacityNoClobber(inst, Air.indexToRef(arg_index));
diff --git a/src/Sema.zig b/src/Sema.zig
index d273d1d6e8..f1431272db 100644
--- a/src/Sema.zig
+++ b/src/Sema.zig
@@ -266,7 +266,7 @@ pub const Block = struct {
});
}
- pub fn addBinOp(
+ fn addBinOp(
block: *Block,
tag: Air.Inst.Tag,
lhs: Air.Inst.Ref,
@@ -281,7 +281,7 @@ pub const Block = struct {
});
}
- pub fn addArg(block: *Block, ty: Type, name: u32) error{OutOfMemory}!Air.Inst.Ref {
+ fn addArg(block: *Block, ty: Type, name: u32) error{OutOfMemory}!Air.Inst.Ref {
return block.addInst(.{
.tag = .arg,
.data = .{ .ty_str = .{
@@ -291,7 +291,7 @@ pub const Block = struct {
});
}
- pub fn addStructFieldPtr(
+ fn addStructFieldPtr(
block: *Block,
struct_ptr: Air.Inst.Ref,
field_index: u32,
@@ -15339,7 +15339,7 @@ fn getBuiltinType(
/// in `Sema` is for calling during semantic analysis, and performs field resolution
/// to get the answer. The one in `Type` is for calling during codegen and asserts
/// that the types are already resolved.
-fn typeHasOnePossibleValue(
+pub fn typeHasOnePossibleValue(
sema: *Sema,
block: *Block,
src: LazySrcLoc,
diff --git a/test/behavior/enum_llvm.zig b/test/behavior/enum_llvm.zig
index c0d536c029..700e396087 100644
--- a/test/behavior/enum_llvm.zig
+++ b/test/behavior/enum_llvm.zig
@@ -90,3 +90,35 @@ fn getB(data: *const BitFieldOfEnums) B {
fn getC(data: *const BitFieldOfEnums) C {
return data.c;
}
+
+const EnumWithOneMember = enum { Eof };
+
+fn doALoopThing(id: EnumWithOneMember) void {
+ while (true) {
+ if (id == EnumWithOneMember.Eof) {
+ break;
+ }
+ @compileError("above if condition should be comptime");
+ }
+}
+
+test "comparison operator on enum with one member is comptime known" {
+ doALoopThing(EnumWithOneMember.Eof);
+}
+
+const State = enum { Start };
+test "switch on enum with one member is comptime known" {
+ var state = State.Start;
+ switch (state) {
+ State.Start => return,
+ }
+ @compileError("analysis should not reach here");
+}
+
+test "enum literal in array literal" {
+ const Items = enum { one, two };
+ const array = [_]Items{ .one, .two };
+
+ try expect(array[0] == .one);
+ try expect(array[1] == .two);
+}
diff --git a/test/behavior/enum_stage1.zig b/test/behavior/enum_stage1.zig
index 59c1b93586..50955d4388 100644
--- a/test/behavior/enum_stage1.zig
+++ b/test/behavior/enum_stage1.zig
@@ -2,38 +2,6 @@ const expect = @import("std").testing.expect;
const mem = @import("std").mem;
const Tag = @import("std").meta.Tag;
-const EnumWithOneMember = enum { Eof };
-
-fn doALoopThing(id: EnumWithOneMember) void {
- while (true) {
- if (id == EnumWithOneMember.Eof) {
- break;
- }
- @compileError("above if condition should be comptime");
- }
-}
-
-test "comparison operator on enum with one member is comptime known" {
- doALoopThing(EnumWithOneMember.Eof);
-}
-
-const State = enum { Start };
-test "switch on enum with one member is comptime known" {
- var state = State.Start;
- switch (state) {
- State.Start => return,
- }
- @compileError("analysis should not reach here");
-}
-
-test "enum literal in array literal" {
- const Items = enum { one, two };
- const array = [_]Items{ .one, .two };
-
- try expect(array[0] == .one);
- try expect(array[1] == .two);
-}
-
test "enum value allocation" {
const LargeEnum = enum(u32) {
A0 = 0x80000000,