authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-08-18 22:02:55-04:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2020-08-18 22:02:55-04:00
log771f40204e769f92bb28bdb9c44e3ddd9d8c4386
tree9335aaca57403c0b71916b2304af2568cbdaed05
parent626d94c2a11aecebf59348d5031df58e7337cfb1
parente4aefc6d0f9b08a98f566cb8280a6195c08f7a82
signaturebadge-question-mark Signed by PGP key 4AEE18F83AFDEB23

Merge pull request #6086 from Vexu/stage2

Stage2: more astgen stuff

8 files changed, 842 insertions(+), 83 deletions(-)

lib/std/zig.zig+101
......@@ -80,6 +80,107 @@ pub fn binNameAlloc(
8080 }
8181}
8282
83/// Only validates escape sequence characters.
84/// Slice must be valid utf8 starting and ending with "'" and exactly one codepoint in between.
85pub fn parseCharLiteral(
86 slice: []const u8,
87 bad_index: *usize, // populated if error.InvalidCharacter is returned)
88) error{InvalidCharacter}!u32 {
89 std.debug.assert(slice.len >= 3 and slice[0] == '\'' and slice[slice.len - 1] == '\'');
90
91 if (slice[1] == '\\') {
92 switch (slice[2]) {
93 'n' => return '\n',
94 'r' => return '\r',
95 '\\' => return '\\',
96 't' => return '\t',
97 '\'' => return '\'',
98 '"' => return '"',
99 'x' => {
100 if (slice.len != 6) {
101 bad_index.* = slice.len - 2;
102 return error.InvalidCharacter;
103 }
104
105 var value: u32 = 0;
106 for (slice[3..5]) |c, i| {
107 switch (slice[3]) {
108 '0'...'9' => {
109 value *= 16;
110 value += c - '0';
111 },
112 'a'...'f' => {
113 value *= 16;
114 value += c - 'a';
115 },
116 'A'...'F' => {
117 value *= 16;
118 value += c - 'a';
119 },
120 else => {
121 bad_index.* = i;
122 return error.InvalidCharacter;
123 },
124 }
125 }
126 return value;
127 },
128 'u' => {
129 if (slice.len < 6 or slice[3] != '{') {
130 bad_index.* = 2;
131 return error.InvalidCharacter;
132 }
133 var value: u32 = 0;
134 for (slice[4..]) |c, i| {
135 if (value > 0x10ffff) {
136 bad_index.* = i;
137 return error.InvalidCharacter;
138 }
139 switch (c) {
140 '0'...'9' => {
141 value *= 16;
142 value += c - '0';
143 },
144 'a'...'f' => {
145 value *= 16;
146 value += c - 'a';
147 },
148 'A'...'F' => {
149 value *= 16;
150 value += c - 'A';
151 },
152 '}' => break,
153 else => {
154 bad_index.* = i;
155 return error.InvalidCharacter;
156 },
157 }
158 }
159 return value;
160 },
161 else => {
162 bad_index.* = 2;
163 return error.InvalidCharacter;
164 }
165 }
166 }
167 return std.unicode.utf8Decode(slice[1 .. slice.len - 1]) catch unreachable;
168}
169
170test "parseCharLiteral" {
171 var bad_index: usize = undefined;
172 std.testing.expectEqual(try parseCharLiteral("'a'", &bad_index), 'a');
173 std.testing.expectEqual(try parseCharLiteral("'ä'", &bad_index), 'ä');
174 std.testing.expectEqual(try parseCharLiteral("'\\x00'", &bad_index), 0);
175 std.testing.expectEqual(try parseCharLiteral("'ぁ'", &bad_index), 0x3041);
176 std.testing.expectEqual(try parseCharLiteral("'\\u{3041}'", &bad_index), 0x3041);
177
178 std.testing.expectError(error.InvalidCharacter, parseCharLiteral("'\\x0'", &bad_index));
179 std.testing.expectError(error.InvalidCharacter, parseCharLiteral("'\\y'", &bad_index));
180 std.testing.expectError(error.InvalidCharacter, parseCharLiteral("'\\u'", &bad_index));
181 std.testing.expectError(error.InvalidCharacter, parseCharLiteral("'\\u{FFFFFF}'", &bad_index));
182}
183
83184test "" {
84185 @import("std").meta.refAllDecls(@This());
85186}
src-self-hosted/Module.zig+66-1
......@@ -2902,7 +2902,7 @@ pub fn floatSub(self: *Module, scope: *Scope, float_type: Type, src: usize, lhs:
29022902 return Value.initPayload(val_payload);
29032903}
29042904
2905pub fn singlePtrType(self: *Module, scope: *Scope, src: usize, mutable: bool, elem_ty: Type) error{OutOfMemory}!Type {
2905pub fn singlePtrType(self: *Module, scope: *Scope, src: usize, mutable: bool, elem_ty: Type) Allocator.Error!Type {
29062906 const type_payload = try scope.arena().create(Type.Payload.Pointer);
29072907 type_payload.* = .{
29082908 .base = .{ .tag = if (mutable) .single_mut_pointer else .single_const_pointer },
......@@ -2911,6 +2911,71 @@ pub fn singlePtrType(self: *Module, scope: *Scope, src: usize, mutable: bool, el
29112911 return Type.initPayload(&type_payload.base);
29122912}
29132913
2914pub fn optionalType(self: *Module, scope: *Scope, child_type: Type) Allocator.Error!Type {
2915 return Type.initPayload(switch (child_type.tag()) {
2916 .single_const_pointer => blk: {
2917 const payload = try scope.arena().create(Type.Payload.Pointer);
2918 payload.* = .{
2919 .base = .{ .tag = .optional_single_const_pointer },
2920 .pointee_type = child_type.elemType(),
2921 };
2922 break :blk &payload.base;
2923 },
2924 .single_mut_pointer => blk: {
2925 const payload = try scope.arena().create(Type.Payload.Pointer);
2926 payload.* = .{
2927 .base = .{ .tag = .optional_single_mut_pointer },
2928 .pointee_type = child_type.elemType(),
2929 };
2930 break :blk &payload.base;
2931 },
2932 else => blk: {
2933 const payload = try scope.arena().create(Type.Payload.Optional);
2934 payload.* = .{
2935 .child_type = child_type,
2936 };
2937 break :blk &payload.base;
2938 },
2939 });
2940}
2941
2942pub fn arrayType(self: *Module, scope: *Scope, len: u64, sentinel: ?Value, elem_type: Type) Allocator.Error!Type {
2943 if (elem_type.eql(Type.initTag(.u8))) {
2944 if (sentinel) |some| {
2945 if (some.eql(Value.initTag(.zero))) {
2946 const payload = try scope.arena().create(Type.Payload.Array_u8_Sentinel0);
2947 payload.* = .{
2948 .len = len,
2949 };
2950 return Type.initPayload(&payload.base);
2951 }
2952 } else {
2953 const payload = try scope.arena().create(Type.Payload.Array_u8);
2954 payload.* = .{
2955 .len = len,
2956 };
2957 return Type.initPayload(&payload.base);
2958 }
2959 }
2960
2961 if (sentinel) |some| {
2962 const payload = try scope.arena().create(Type.Payload.ArraySentinel);
2963 payload.* = .{
2964 .len = len,
2965 .sentinel = some,
2966 .elem_type = elem_type,
2967 };
2968 return Type.initPayload(&payload.base);
2969 }
2970
2971 const payload = try scope.arena().create(Type.Payload.Array);
2972 payload.* = .{
2973 .len = len,
2974 .elem_type = elem_type,
2975 };
2976 return Type.initPayload(&payload.base);
2977}
2978
29142979pub fn dumpInst(self: *Module, scope: *Scope, inst: *Inst) void {
29152980 const zir_module = scope.namespace();
29162981 const source = zir_module.getSource(self) catch @panic("dumpInst failed to get source");
src-self-hosted/astgen.zig+340-24
......@@ -20,6 +20,8 @@ pub const ResultLoc = union(enum) {
2020 /// The expression must generate a pointer rather than a value. For example, the left hand side
2121 /// of an assignment uses an "LValue" result location.
2222 lvalue,
23 /// The expression must generate a pointer
24 ref,
2325 /// The expression will be type coerced into this type, but it will be evaluated as an rvalue.
2426 ty: *zir.Inst,
2527 /// The expression must store its result into this typed pointer.
......@@ -46,6 +48,132 @@ pub fn typeExpr(mod: *Module, scope: *Scope, type_node: *ast.Node) InnerError!*z
4648
4749/// Turn Zig AST into untyped ZIR istructions.
4850pub fn expr(mod: *Module, scope: *Scope, rl: ResultLoc, node: *ast.Node) InnerError!*zir.Inst {
51 if (rl == .lvalue) {
52 switch (node.tag) {
53 .Root => unreachable,
54 .Use => unreachable,
55 .TestDecl => unreachable,
56 .DocComment => unreachable,
57 .VarDecl => unreachable,
58 .SwitchCase => unreachable,
59 .SwitchElse => unreachable,
60 .Else => unreachable,
61 .Payload => unreachable,
62 .PointerPayload => unreachable,
63 .PointerIndexPayload => unreachable,
64 .ErrorTag => unreachable,
65 .FieldInitializer => unreachable,
66 .ContainerField => unreachable,
67
68 .Assign,
69 .AssignBitAnd,
70 .AssignBitOr,
71 .AssignBitShiftLeft,
72 .AssignBitShiftRight,
73 .AssignBitXor,
74 .AssignDiv,
75 .AssignSub,
76 .AssignSubWrap,
77 .AssignMod,
78 .AssignAdd,
79 .AssignAddWrap,
80 .AssignMul,
81 .AssignMulWrap,
82 .Add,
83 .AddWrap,
84 .Sub,
85 .SubWrap,
86 .Mul,
87 .MulWrap,
88 .Div,
89 .Mod,
90 .BitAnd,
91 .BitOr,
92 .BitShiftLeft,
93 .BitShiftRight,
94 .BitXor,
95 .BangEqual,
96 .EqualEqual,
97 .GreaterThan,
98 .GreaterOrEqual,
99 .LessThan,
100 .LessOrEqual,
101 .ArrayCat,
102 .ArrayMult,
103 .BoolAnd,
104 .BoolOr,
105 .Asm,
106 .StringLiteral,
107 .IntegerLiteral,
108 .Call,
109 .Unreachable,
110 .Return,
111 .If,
112 .While,
113 .BoolNot,
114 .AddressOf,
115 .FloatLiteral,
116 .UndefinedLiteral,
117 .BoolLiteral,
118 .NullLiteral,
119 .OptionalType,
120 .Block,
121 .LabeledBlock,
122 .Break,
123 .PtrType,
124 .GroupedExpression,
125 .ArrayType,
126 .ArrayTypeSentinel,
127 .EnumLiteral,
128 .MultilineStringLiteral,
129 .CharLiteral,
130 .Defer,
131 .Catch,
132 .ErrorUnion,
133 .MergeErrorSets,
134 .Range,
135 .OrElse,
136 .Await,
137 .BitNot,
138 .Negation,
139 .NegationWrap,
140 .Resume,
141 .Try,
142 .SliceType,
143 .Slice,
144 .ArrayInitializer,
145 .ArrayInitializerDot,
146 .StructInitializer,
147 .StructInitializerDot,
148 .Switch,
149 .For,
150 .Suspend,
151 .Continue,
152 .AnyType,
153 .ErrorType,
154 .FnProto,
155 .AnyFrameType,
156 .ErrorSetDecl,
157 .ContainerDecl,
158 .Comptime,
159 .Nosuspend,
160 => return mod.failNode(scope, node, "invalid left-hand side to assignment", .{}),
161
162 // @field can be assigned to
163 .BuiltinCall => {
164 const call = node.castTag(.BuiltinCall).?;
165 const tree = scope.tree();
166 const builtin_name = tree.tokenSlice(call.builtin_token);
167
168 if (!mem.eql(u8, builtin_name, "@field")) {
169 return mod.failNode(scope, node, "invalid left-hand side to assignment", .{});
170 }
171 },
172
173 // can be assigned to
174 .UnwrapOptional, .Deref, .Period, .ArrayAccess, .Identifier => {},
175 }
176 }
49177 switch (node.tag) {
50178 .Root => unreachable, // Top-level declaration.
51179 .Use => unreachable, // Top-level declaration.
......@@ -60,6 +188,7 @@ pub fn expr(mod: *Module, scope: *Scope, rl: ResultLoc, node: *ast.Node) InnerEr
60188 .PointerIndexPayload => unreachable, // Handled explicitly.
61189 .ErrorTag => unreachable, // Handled explicitly.
62190 .FieldInitializer => unreachable, // Handled explicitly.
191 .ContainerField => unreachable, // Handled explicitly.
63192
64193 .Assign => return rlWrapVoid(mod, scope, rl, node, try assign(mod, scope, node.castTag(.Assign).?)),
65194 .AssignBitAnd => return rlWrapVoid(mod, scope, rl, node, try assignOp(mod, scope, node.castTag(.AssignBitAnd).?, .bitand)),
......@@ -100,6 +229,9 @@ pub fn expr(mod: *Module, scope: *Scope, rl: ResultLoc, node: *ast.Node) InnerEr
100229 .ArrayCat => return simpleBinOp(mod, scope, rl, node.castTag(.ArrayCat).?, .array_cat),
101230 .ArrayMult => return simpleBinOp(mod, scope, rl, node.castTag(.ArrayMult).?, .array_mul),
102231
232 .BoolAnd => return boolBinOp(mod, scope, rl, node.castTag(.BoolAnd).?),
233 .BoolOr => return boolBinOp(mod, scope, rl, node.castTag(.BoolOr).?),
234
103235 .Identifier => return try identifier(mod, scope, rl, node.castTag(.Identifier).?),
104236 .Asm => return rlWrap(mod, scope, rl, try assembly(mod, scope, node.castTag(.Asm).?)),
105237 .StringLiteral => return rlWrap(mod, scope, rl, try stringLiteral(mod, scope, node.castTag(.StringLiteral).?)),
......@@ -124,11 +256,15 @@ pub fn expr(mod: *Module, scope: *Scope, rl: ResultLoc, node: *ast.Node) InnerEr
124256 .LabeledBlock => return labeledBlockExpr(mod, scope, rl, node.castTag(.LabeledBlock).?),
125257 .Break => return rlWrap(mod, scope, rl, try breakExpr(mod, scope, node.castTag(.Break).?)),
126258 .PtrType => return rlWrap(mod, scope, rl, try ptrType(mod, scope, node.castTag(.PtrType).?)),
259 .GroupedExpression => return expr(mod, scope, rl, node.castTag(.GroupedExpression).?.expr),
260 .ArrayType => return rlWrap(mod, scope, rl, try arrayType(mod, scope, node.castTag(.ArrayType).?)),
261 .ArrayTypeSentinel => return rlWrap(mod, scope, rl, try arrayTypeSentinel(mod, scope, node.castTag(.ArrayTypeSentinel).?)),
262 .EnumLiteral => return rlWrap(mod, scope, rl, try enumLiteral(mod, scope, node.castTag(.EnumLiteral).?)),
263 .MultilineStringLiteral => return rlWrap(mod, scope, rl, try multilineStrLiteral(mod, scope, node.castTag(.MultilineStringLiteral).?)),
264 .CharLiteral => return rlWrap(mod, scope, rl, try charLiteral(mod, scope, node.castTag(.CharLiteral).?)),
127265
128266 .Defer => return mod.failNode(scope, node, "TODO implement astgen.expr for .Defer", .{}),
129267 .Catch => return mod.failNode(scope, node, "TODO implement astgen.expr for .Catch", .{}),
130 .BoolAnd => return mod.failNode(scope, node, "TODO implement astgen.expr for .BoolAnd", .{}),
131 .BoolOr => return mod.failNode(scope, node, "TODO implement astgen.expr for .BoolOr", .{}),
132268 .ErrorUnion => return mod.failNode(scope, node, "TODO implement astgen.expr for .ErrorUnion", .{}),
133269 .MergeErrorSets => return mod.failNode(scope, node, "TODO implement astgen.expr for .MergeErrorSets", .{}),
134270 .Range => return mod.failNode(scope, node, "TODO implement astgen.expr for .Range", .{}),
......@@ -139,8 +275,6 @@ pub fn expr(mod: *Module, scope: *Scope, rl: ResultLoc, node: *ast.Node) InnerEr
139275 .NegationWrap => return mod.failNode(scope, node, "TODO implement astgen.expr for .NegationWrap", .{}),
140276 .Resume => return mod.failNode(scope, node, "TODO implement astgen.expr for .Resume", .{}),
141277 .Try => return mod.failNode(scope, node, "TODO implement astgen.expr for .Try", .{}),
142 .ArrayType => return mod.failNode(scope, node, "TODO implement astgen.expr for .ArrayType", .{}),
143 .ArrayTypeSentinel => return mod.failNode(scope, node, "TODO implement astgen.expr for .ArrayTypeSentinel", .{}),
144278 .SliceType => return mod.failNode(scope, node, "TODO implement astgen.expr for .SliceType", .{}),
145279 .Slice => return mod.failNode(scope, node, "TODO implement astgen.expr for .Slice", .{}),
146280 .ArrayAccess => return mod.failNode(scope, node, "TODO implement astgen.expr for .ArrayAccess", .{}),
......@@ -156,15 +290,10 @@ pub fn expr(mod: *Module, scope: *Scope, rl: ResultLoc, node: *ast.Node) InnerEr
156290 .ErrorType => return mod.failNode(scope, node, "TODO implement astgen.expr for .ErrorType", .{}),
157291 .FnProto => return mod.failNode(scope, node, "TODO implement astgen.expr for .FnProto", .{}),
158292 .AnyFrameType => return mod.failNode(scope, node, "TODO implement astgen.expr for .AnyFrameType", .{}),
159 .EnumLiteral => return mod.failNode(scope, node, "TODO implement astgen.expr for .EnumLiteral", .{}),
160 .MultilineStringLiteral => return mod.failNode(scope, node, "TODO implement astgen.expr for .MultilineStringLiteral", .{}),
161 .CharLiteral => return mod.failNode(scope, node, "TODO implement astgen.expr for .CharLiteral", .{}),
162 .GroupedExpression => return mod.failNode(scope, node, "TODO implement astgen.expr for .GroupedExpression", .{}),
163293 .ErrorSetDecl => return mod.failNode(scope, node, "TODO implement astgen.expr for .ErrorSetDecl", .{}),
164294 .ContainerDecl => return mod.failNode(scope, node, "TODO implement astgen.expr for .ContainerDecl", .{}),
165295 .Comptime => return mod.failNode(scope, node, "TODO implement astgen.expr for .Comptime", .{}),
166296 .Nosuspend => return mod.failNode(scope, node, "TODO implement astgen.expr for .Nosuspend", .{}),
167 .ContainerField => return mod.failNode(scope, node, "TODO implement astgen.expr for .ContainerField", .{}),
168297 }
169298}
170299
......@@ -187,7 +316,7 @@ fn breakExpr(mod: *Module, parent_scope: *Scope, node: *ast.Node.ControlFlowExpr
187316 // proper type inference requires peer type resolution on the block's
188317 // break operand expressions.
189318 const branch_rl: ResultLoc = switch (label.result_loc) {
190 .discard, .none, .ty, .ptr, .lvalue => label.result_loc,
319 .discard, .none, .ty, .ptr, .lvalue, .ref => label.result_loc,
191320 .inferred_ptr, .bitcasted_ptr, .block_ptr => .{ .block_ptr = label.block_inst },
192321 };
193322 const operand = try expr(mod, parent_scope, branch_rl, rhs);
......@@ -426,7 +555,7 @@ fn boolNot(mod: *Module, scope: *Scope, node: *ast.Node.SimplePrefixOp) InnerErr
426555}
427556
428557fn addressOf(mod: *Module, scope: *Scope, node: *ast.Node.SimplePrefixOp) InnerError!*zir.Inst {
429 return expr(mod, scope, .lvalue, node.rhs);
558 return expr(mod, scope, .ref, node.rhs);
430559}
431560
432561fn optionalType(mod: *Module, scope: *Scope, node: *ast.Node.SimplePrefixOp) InnerError!*zir.Inst {
......@@ -484,13 +613,65 @@ fn ptrType(mod: *Module, scope: *Scope, node: *ast.Node.PtrType) InnerError!*zir
484613 return addZIRInst(mod, scope, src, zir.Inst.PtrType, .{ .child_type = child_type }, kw_args);
485614}
486615
616fn arrayType(mod: *Module, scope: *Scope, node: *ast.Node.ArrayType) !*zir.Inst {
617 const tree = scope.tree();
618 const src = tree.token_locs[node.op_token].start;
619 const meta_type = try addZIRInstConst(mod, scope, src, .{
620 .ty = Type.initTag(.type),
621 .val = Value.initTag(.type_type),
622 });
623 const usize_type = try addZIRInstConst(mod, scope, src, .{
624 .ty = Type.initTag(.type),
625 .val = Value.initTag(.usize_type),
626 });
627
628 // TODO check for [_]T
629 const len = try expr(mod, scope, .{ .ty = usize_type }, node.len_expr);
630 const child_type = try expr(mod, scope, .{ .ty = meta_type }, node.rhs);
631
632 return addZIRBinOp(mod, scope, src, .array_type, len, child_type);
633}
634
635fn arrayTypeSentinel(mod: *Module, scope: *Scope, node: *ast.Node.ArrayTypeSentinel) !*zir.Inst {
636 const tree = scope.tree();
637 const src = tree.token_locs[node.op_token].start;
638 const meta_type = try addZIRInstConst(mod, scope, src, .{
639 .ty = Type.initTag(.type),
640 .val = Value.initTag(.type_type),
641 });
642 const usize_type = try addZIRInstConst(mod, scope, src, .{
643 .ty = Type.initTag(.type),
644 .val = Value.initTag(.usize_type),
645 });
646
647 // TODO check for [_]T
648 const len = try expr(mod, scope, .{ .ty = usize_type }, node.len_expr);
649 const sentinel_uncasted = try expr(mod, scope, .none, node.sentinel);
650 const elem_type = try expr(mod, scope, .{ .ty = meta_type }, node.rhs);
651 const sentinel = try addZIRBinOp(mod, scope, src, .as, elem_type, sentinel_uncasted);
652
653 return addZIRInst(mod, scope, src, zir.Inst.ArrayTypeSentinel, .{
654 .len = len,
655 .sentinel = sentinel,
656 .elem_type = elem_type,
657 }, .{});
658}
659
660fn enumLiteral(mod: *Module, scope: *Scope, node: *ast.Node.EnumLiteral) !*zir.Inst {
661 const tree = scope.tree();
662 const src = tree.token_locs[node.name].start;
663 const name = try identifierTokenString(mod, scope, node.name);
664
665 return addZIRInst(mod, scope, src, zir.Inst.EnumLiteral, .{ .name = name }, .{});
666}
667
487668fn unwrapOptional(mod: *Module, scope: *Scope, rl: ResultLoc, node: *ast.Node.SimpleSuffixOp) InnerError!*zir.Inst {
488669 const tree = scope.tree();
489670 const src = tree.token_locs[node.rtoken].start;
490671
491 const operand = try expr(mod, scope, .lvalue, node.lhs);
672 const operand = try expr(mod, scope, .ref, node.lhs);
492673 const unwrapped_ptr = try addZIRUnOp(mod, scope, src, .unwrap_optional_safe, operand);
493 if (rl == .lvalue) return unwrapped_ptr;
674 if (rl == .lvalue or rl == .ref) return unwrapped_ptr;
494675
495676 return rlWrap(mod, scope, rl, try addZIRUnOp(mod, scope, src, .deref, unwrapped_ptr));
496677}
......@@ -568,6 +749,88 @@ fn simpleBinOp(
568749 return rlWrap(mod, scope, rl, result);
569750}
570751
752fn boolBinOp(
753 mod: *Module,
754 scope: *Scope,
755 rl: ResultLoc,
756 infix_node: *ast.Node.SimpleInfixOp,
757) InnerError!*zir.Inst {
758 const tree = scope.tree();
759 const src = tree.token_locs[infix_node.op_token].start;
760 const bool_type = try addZIRInstConst(mod, scope, src, .{
761 .ty = Type.initTag(.type),
762 .val = Value.initTag(.bool_type),
763 });
764
765 var block_scope: Scope.GenZIR = .{
766 .parent = scope,
767 .decl = scope.decl().?,
768 .arena = scope.arena(),
769 .instructions = .{},
770 };
771 defer block_scope.instructions.deinit(mod.gpa);
772
773 const lhs = try expr(mod, scope, .{ .ty = bool_type }, infix_node.lhs);
774 const condbr = try addZIRInstSpecial(mod, &block_scope.base, src, zir.Inst.CondBr, .{
775 .condition = lhs,
776 .then_body = undefined, // populated below
777 .else_body = undefined, // populated below
778 }, .{});
779
780 const block = try addZIRInstBlock(mod, scope, src, .{
781 .instructions = try block_scope.arena.dupe(*zir.Inst, block_scope.instructions.items),
782 });
783
784 var rhs_scope: Scope.GenZIR = .{
785 .parent = scope,
786 .decl = block_scope.decl,
787 .arena = block_scope.arena,
788 .instructions = .{},
789 };
790 defer rhs_scope.instructions.deinit(mod.gpa);
791
792 const rhs = try expr(mod, &rhs_scope.base, .{ .ty = bool_type }, infix_node.rhs);
793 _ = try addZIRInst(mod, &rhs_scope.base, src, zir.Inst.Break, .{
794 .block = block,
795 .operand = rhs,
796 }, .{});
797
798 var const_scope: Scope.GenZIR = .{
799 .parent = scope,
800 .decl = block_scope.decl,
801 .arena = block_scope.arena,
802 .instructions = .{},
803 };
804 defer const_scope.instructions.deinit(mod.gpa);
805
806 const is_bool_and = infix_node.base.tag == .BoolAnd;
807 _ = try addZIRInst(mod, &const_scope.base, src, zir.Inst.Break, .{
808 .block = block,
809 .operand = try addZIRInstConst(mod, &const_scope.base, src, .{
810 .ty = Type.initTag(.bool),
811 .val = if (is_bool_and) Value.initTag(.bool_false) else Value.initTag(.bool_true),
812 }),
813 }, .{});
814
815 if (is_bool_and) {
816 // if lhs // AND
817 // break rhs
818 // else
819 // break false
820 condbr.positionals.then_body = .{ .instructions = try rhs_scope.arena.dupe(*zir.Inst, rhs_scope.instructions.items) };
821 condbr.positionals.else_body = .{ .instructions = try const_scope.arena.dupe(*zir.Inst, const_scope.instructions.items) };
822 } else {
823 // if lhs // OR
824 // break true
825 // else
826 // break rhs
827 condbr.positionals.then_body = .{ .instructions = try const_scope.arena.dupe(*zir.Inst, const_scope.instructions.items) };
828 condbr.positionals.else_body = .{ .instructions = try rhs_scope.arena.dupe(*zir.Inst, rhs_scope.instructions.items) };
829 }
830
831 return rlWrap(mod, scope, rl, &block.base);
832}
833
571834const CondKind = union(enum) {
572835 bool,
573836 optional: ?*zir.Inst,
......@@ -583,13 +846,13 @@ const CondKind = union(enum) {
583846 return try expr(mod, &block_scope.base, .{ .ty = bool_type }, cond_node);
584847 },
585848 .optional => {
586 const cond_ptr = try expr(mod, &block_scope.base, .lvalue, cond_node);
849 const cond_ptr = try expr(mod, &block_scope.base, .ref, cond_node);
587850 self.* = .{ .optional = cond_ptr };
588851 const result = try addZIRUnOp(mod, &block_scope.base, src, .deref, cond_ptr);
589852 return try addZIRUnOp(mod, &block_scope.base, src, .isnonnull, result);
590853 },
591854 .err_union => {
592 const err_ptr = try expr(mod, &block_scope.base, .lvalue, cond_node);
855 const err_ptr = try expr(mod, &block_scope.base, .ref, cond_node);
593856 self.* = .{ .err_union = err_ptr };
594857 const result = try addZIRUnOp(mod, &block_scope.base, src, .deref, err_ptr);
595858 return try addZIRUnOp(mod, &block_scope.base, src, .iserr, result);
......@@ -600,7 +863,11 @@ const CondKind = union(enum) {
600863 fn thenSubScope(self: CondKind, mod: *Module, then_scope: *Scope.GenZIR, src: usize, payload_node: ?*ast.Node) !*Scope {
601864 if (self == .bool) return &then_scope.base;
602865
603 const payload = payload_node.?.castTag(.PointerPayload).?;
866 const payload = payload_node.?.castTag(.PointerPayload) orelse {
867 // condition is error union and payload is not explicitly ignored
868 _ = try addZIRUnOp(mod, &then_scope.base, src, .ensure_err_payload_void, self.err_union.?);
869 return &then_scope.base;
870 };
604871 const is_ptr = payload.ptr_token != null;
605872 const ident_node = payload.value_symbol.castTag(.Identifier).?;
606873
......@@ -680,7 +947,7 @@ fn ifExpr(mod: *Module, scope: *Scope, rl: ResultLoc, if_node: *ast.Node.If) Inn
680947 // proper type inference requires peer type resolution on the if's
681948 // branches.
682949 const branch_rl: ResultLoc = switch (rl) {
683 .discard, .none, .ty, .ptr, .lvalue => rl,
950 .discard, .none, .ty, .ptr, .lvalue, .ref => rl,
684951 .inferred_ptr, .bitcasted_ptr, .block_ptr => .{ .block_ptr = block },
685952 };
686953
......@@ -810,7 +1077,7 @@ fn whileExpr(mod: *Module, scope: *Scope, rl: ResultLoc, while_node: *ast.Node.W
8101077 // proper type inference requires peer type resolution on the while's
8111078 // branches.
8121079 const branch_rl: ResultLoc = switch (rl) {
813 .discard, .none, .ty, .ptr, .lvalue => rl,
1080 .discard, .none, .ty, .ptr, .lvalue, .ref => rl,
8141081 .inferred_ptr, .bitcasted_ptr, .block_ptr => .{ .block_ptr = while_block },
8151082 };
8161083
......@@ -941,7 +1208,7 @@ fn identifier(mod: *Module, scope: *Scope, rl: ResultLoc, ident: *ast.Node.OneTo
9411208 .local_ptr => {
9421209 const local_ptr = s.cast(Scope.LocalPtr).?;
9431210 if (mem.eql(u8, local_ptr.name, ident_name)) {
944 if (rl == .lvalue) {
1211 if (rl == .lvalue or rl == .ref) {
9451212 return local_ptr.ptr;
9461213 } else {
9471214 const result = try addZIRUnOp(mod, scope, src, .deref, local_ptr.ptr);
......@@ -983,6 +1250,53 @@ fn stringLiteral(mod: *Module, scope: *Scope, str_lit: *ast.Node.OneToken) Inner
9831250 return addZIRInst(mod, scope, src, zir.Inst.Str, .{ .bytes = bytes }, .{});
9841251}
9851252
1253fn multilineStrLiteral(mod: *Module, scope: *Scope, node: *ast.Node.MultilineStringLiteral) !*zir.Inst {
1254 const tree = scope.tree();
1255 const lines = node.linesConst();
1256 const src = tree.token_locs[lines[0]].start;
1257
1258 // line lengths and new lines
1259 var len = lines.len - 1;
1260 for (lines) |line| {
1261 len += tree.tokenSlice(line).len - 2;
1262 }
1263
1264 const bytes = try scope.arena().alloc(u8, len);
1265 var i: usize = 0;
1266 for (lines) |line, line_i| {
1267 if (line_i != 0) {
1268 bytes[i] = '\n';
1269 i += 1;
1270 }
1271 const slice = tree.tokenSlice(line)[2..];
1272 mem.copy(u8, bytes[i..], slice);
1273 i += slice.len;
1274 }
1275
1276 return addZIRInst(mod, scope, src, zir.Inst.Str, .{ .bytes = bytes }, .{});
1277}
1278
1279fn charLiteral(mod: *Module, scope: *Scope, node: *ast.Node.OneToken) !*zir.Inst {
1280 const tree = scope.tree();
1281 const src = tree.token_locs[node.token].start;
1282 const slice = tree.tokenSlice(node.token);
1283
1284 var bad_index: usize = undefined;
1285 const value = std.zig.parseCharLiteral(slice, &bad_index) catch |err| switch (err) {
1286 error.InvalidCharacter => {
1287 const bad_byte = slice[bad_index];
1288 return mod.fail(scope, src + bad_index, "invalid character: '{c}'\n", .{bad_byte});
1289 },
1290 };
1291
1292 const int_payload = try scope.arena().create(Value.Payload.Int_u64);
1293 int_payload.* = .{ .int = value };
1294 return addZIRInstConst(mod, scope, src, .{
1295 .ty = Type.initTag(.comptime_int),
1296 .val = Value.initPayload(&int_payload.base),
1297 });
1298}
1299
9861300fn integerLiteral(mod: *Module, scope: *Scope, int_lit: *ast.Node.OneToken) InnerError!*zir.Inst {
9871301 const arena = scope.arena();
9881302 const tree = scope.tree();
......@@ -1158,7 +1472,8 @@ fn as(mod: *Module, scope: *Scope, rl: ResultLoc, call: *ast.Node.BuiltinCall) I
11581472 _ = try addZIRUnOp(mod, scope, result.src, .ensure_result_non_error, result);
11591473 return result;
11601474 },
1161 .lvalue => {
1475 .lvalue => unreachable,
1476 .ref => {
11621477 const result = try expr(mod, scope, .{ .ty = dest_type }, params[1]);
11631478 return addZIRUnOp(mod, scope, result.src, .ref, result);
11641479 },
......@@ -1209,9 +1524,10 @@ fn bitCast(mod: *Module, scope: *Scope, rl: ResultLoc, call: *ast.Node.BuiltinCa
12091524 _ = try addZIRUnOp(mod, scope, result.src, .ensure_result_non_error, result);
12101525 return result;
12111526 },
1212 .lvalue => {
1213 const operand = try expr(mod, scope, .lvalue, params[1]);
1214 const result = try addZIRBinOp(mod, scope, src, .bitcast_lvalue, dest_type, operand);
1527 .lvalue => unreachable,
1528 .ref => {
1529 const operand = try expr(mod, scope, .ref, params[1]);
1530 const result = try addZIRBinOp(mod, scope, src, .bitcast_ref, dest_type, operand);
12151531 return result;
12161532 },
12171533 .ty => |result_ty| {
......@@ -1476,7 +1792,7 @@ fn rlWrap(mod: *Module, scope: *Scope, rl: ResultLoc, result: *zir.Inst) InnerEr
14761792 _ = try addZIRUnOp(mod, scope, result.src, .ensure_result_non_error, result);
14771793 return result;
14781794 },
1479 .lvalue => {
1795 .lvalue, .ref => {
14801796 // We need a pointer but we have a value.
14811797 return addZIRUnOp(mod, scope, result.src, .ref, result);
14821798 },
src-self-hosted/type.zig+172-22
......@@ -65,7 +65,7 @@ pub const Type = extern union {
6565 .fn_ccc_void_no_args => return .Fn,
6666 .function => return .Fn,
6767
68 .array, .array_u8_sentinel_0 => return .Array,
68 .array, .array_u8_sentinel_0, .array_u8, .array_sentinel => return .Array,
6969 .single_const_pointer => return .Pointer,
7070 .single_mut_pointer => return .Pointer,
7171 .single_const_pointer_to_comptime_int => return .Pointer,
......@@ -75,6 +75,7 @@ pub const Type = extern union {
7575 .optional_single_const_pointer,
7676 .optional_single_mut_pointer,
7777 => return .Optional,
78 .enum_literal => return .EnumLiteral,
7879 }
7980 }
8081
......@@ -127,6 +128,7 @@ pub const Type = extern union {
127128 if (zig_tag_a != zig_tag_b)
128129 return false;
129130 switch (zig_tag_a) {
131 .EnumLiteral => return true,
130132 .Type => return true,
131133 .Void => return true,
132134 .Bool => return true,
......@@ -211,7 +213,6 @@ pub const Type = extern union {
211213 .Frame,
212214 .AnyFrame,
213215 .Vector,
214 .EnumLiteral,
215216 => std.debug.panic("TODO implement Type equality comparison of {} and {}", .{ a, b }),
216217 }
217218 }
......@@ -327,9 +328,11 @@ pub const Type = extern union {
327328 .fn_ccc_void_no_args,
328329 .single_const_pointer_to_comptime_int,
329330 .const_slice_u8,
331 .enum_literal,
330332 => unreachable,
331333
332334 .array_u8_sentinel_0 => return self.copyPayloadShallow(allocator, Payload.Array_u8_Sentinel0),
335 .array_u8 => return self.copyPayloadShallow(allocator, Payload.Array_u8),
333336 .array => {
334337 const payload = @fieldParentPtr(Payload.Array, "base", self.ptr_otherwise);
335338 const new_payload = try allocator.create(Payload.Array);
......@@ -340,6 +343,17 @@ pub const Type = extern union {
340343 };
341344 return Type{ .ptr_otherwise = &new_payload.base };
342345 },
346 .array_sentinel => {
347 const payload = @fieldParentPtr(Payload.ArraySentinel, "base", self.ptr_otherwise);
348 const new_payload = try allocator.create(Payload.ArraySentinel);
349 new_payload.* = .{
350 .base = payload.base,
351 .len = payload.len,
352 .sentinel = try payload.sentinel.copy(allocator),
353 .elem_type = try payload.elem_type.copy(allocator),
354 };
355 return Type{ .ptr_otherwise = &new_payload.base };
356 },
343357 .int_signed => return self.copyPayloadShallow(allocator, Payload.IntSigned),
344358 .int_unsigned => return self.copyPayloadShallow(allocator, Payload.IntUnsigned),
345359 .function => {
......@@ -425,6 +439,7 @@ pub const Type = extern union {
425439 .noreturn,
426440 => return out_stream.writeAll(@tagName(t)),
427441
442 .enum_literal => return out_stream.writeAll("@TypeOf(.EnumLiteral)"),
428443 .@"null" => return out_stream.writeAll("@TypeOf(null)"),
429444 .@"undefined" => return out_stream.writeAll("@TypeOf(undefined)"),
430445
......@@ -445,6 +460,10 @@ pub const Type = extern union {
445460 try payload.return_type.format("", .{}, out_stream);
446461 },
447462
463 .array_u8 => {
464 const payload = @fieldParentPtr(Payload.Array_u8, "base", ty.ptr_otherwise);
465 return out_stream.print("[{}]u8", .{payload.len});
466 },
448467 .array_u8_sentinel_0 => {
449468 const payload = @fieldParentPtr(Payload.Array_u8_Sentinel0, "base", ty.ptr_otherwise);
450469 return out_stream.print("[{}:0]u8", .{payload.len});
......@@ -455,6 +474,12 @@ pub const Type = extern union {
455474 ty = payload.elem_type;
456475 continue;
457476 },
477 .array_sentinel => {
478 const payload = @fieldParentPtr(Payload.ArraySentinel, "base", ty.ptr_otherwise);
479 try out_stream.print("[{}:{}]", .{ payload.len, payload.sentinel });
480 ty = payload.elem_type;
481 continue;
482 },
458483 .single_const_pointer => {
459484 const payload = @fieldParentPtr(Payload.Pointer, "base", ty.ptr_otherwise);
460485 try out_stream.writeAll("*const ");
......@@ -539,6 +564,7 @@ pub const Type = extern union {
539564 .fn_ccc_void_no_args => return Value.initTag(.fn_ccc_void_no_args_type),
540565 .single_const_pointer_to_comptime_int => return Value.initTag(.single_const_pointer_to_comptime_int_type),
541566 .const_slice_u8 => return Value.initTag(.const_slice_u8_type),
567 .enum_literal => return Value.initTag(.enum_literal_type),
542568 else => {
543569 const ty_payload = try allocator.create(Value.Payload.Ty);
544570 ty_payload.* = .{ .ty = self };
......@@ -588,6 +614,8 @@ pub const Type = extern union {
588614 => true,
589615 // TODO lazy types
590616 .array => self.elemType().hasCodeGenBits() and self.arrayLen() != 0,
617 .array_u8 => self.arrayLen() != 0,
618 .array_sentinel => self.elemType().hasCodeGenBits(),
591619 .single_const_pointer => self.elemType().hasCodeGenBits(),
592620 .single_mut_pointer => self.elemType().hasCodeGenBits(),
593621 .int_signed => self.cast(Payload.IntSigned).?.bits == 0,
......@@ -601,6 +629,7 @@ pub const Type = extern union {
601629 .noreturn,
602630 .@"null",
603631 .@"undefined",
632 .enum_literal,
604633 => false,
605634 };
606635 }
......@@ -616,6 +645,7 @@ pub const Type = extern union {
616645 .i8,
617646 .bool,
618647 .array_u8_sentinel_0,
648 .array_u8,
619649 => return 1,
620650
621651 .fn_noreturn_no_args, // represents machine code; not a pointer
......@@ -659,7 +689,7 @@ pub const Type = extern union {
659689
660690 .anyerror => return 2, // TODO revisit this when we have the concept of the error tag type
661691
662 .array => return self.cast(Payload.Array).?.elem_type.abiAlignment(target),
692 .array, .array_sentinel => return self.elemType().abiAlignment(target),
663693
664694 .int_signed, .int_unsigned => {
665695 const bits: u16 = if (self.cast(Payload.IntSigned)) |pl|
......@@ -691,6 +721,7 @@ pub const Type = extern union {
691721 .noreturn,
692722 .@"null",
693723 .@"undefined",
724 .enum_literal,
694725 => unreachable,
695726 };
696727 }
......@@ -711,18 +742,25 @@ pub const Type = extern union {
711742 .noreturn => unreachable,
712743 .@"null" => unreachable,
713744 .@"undefined" => unreachable,
745 .enum_literal => unreachable,
714746
715747 .u8,
716748 .i8,
717749 .bool,
718750 => return 1,
719751
720 .array_u8_sentinel_0 => @fieldParentPtr(Payload.Array_u8_Sentinel0, "base", self.ptr_otherwise).len,
752 .array_u8 => @fieldParentPtr(Payload.Array_u8_Sentinel0, "base", self.ptr_otherwise).len,
753 .array_u8_sentinel_0 => @fieldParentPtr(Payload.Array_u8_Sentinel0, "base", self.ptr_otherwise).len + 1,
721754 .array => {
722755 const payload = @fieldParentPtr(Payload.Array, "base", self.ptr_otherwise);
723756 const elem_size = std.math.max(payload.elem_type.abiAlignment(target), payload.elem_type.abiSize(target));
724757 return payload.len * elem_size;
725758 },
759 .array_sentinel => {
760 const payload = @fieldParentPtr(Payload.ArraySentinel, "base", self.ptr_otherwise);
761 const elem_size = std.math.max(payload.elem_type.abiAlignment(target), payload.elem_type.abiSize(target));
762 return (payload.len + 1) * elem_size;
763 },
726764 .i16, .u16 => return 2,
727765 .i32, .u32 => return 4,
728766 .i64, .u64 => return 8,
......@@ -818,6 +856,8 @@ pub const Type = extern union {
818856 .@"null",
819857 .@"undefined",
820858 .array,
859 .array_sentinel,
860 .array_u8,
821861 .array_u8_sentinel_0,
822862 .const_slice_u8,
823863 .fn_noreturn_no_args,
......@@ -830,6 +870,7 @@ pub const Type = extern union {
830870 .optional,
831871 .optional_single_mut_pointer,
832872 .optional_single_const_pointer,
873 .enum_literal,
833874 => false,
834875
835876 .single_const_pointer,
......@@ -875,6 +916,8 @@ pub const Type = extern union {
875916 .@"null",
876917 .@"undefined",
877918 .array,
919 .array_sentinel,
920 .array_u8,
878921 .array_u8_sentinel_0,
879922 .single_const_pointer,
880923 .single_mut_pointer,
......@@ -889,6 +932,7 @@ pub const Type = extern union {
889932 .optional,
890933 .optional_single_mut_pointer,
891934 .optional_single_const_pointer,
935 .enum_literal,
892936 => false,
893937
894938 .const_slice_u8 => true,
......@@ -931,6 +975,8 @@ pub const Type = extern union {
931975 .@"null",
932976 .@"undefined",
933977 .array,
978 .array_sentinel,
979 .array_u8,
934980 .array_u8_sentinel_0,
935981 .fn_noreturn_no_args,
936982 .fn_void_no_args,
......@@ -943,6 +989,7 @@ pub const Type = extern union {
943989 .optional,
944990 .optional_single_mut_pointer,
945991 .optional_single_const_pointer,
992 .enum_literal,
946993 => false,
947994
948995 .single_const_pointer,
......@@ -988,6 +1035,8 @@ pub const Type = extern union {
9881035 .@"null",
9891036 .@"undefined",
9901037 .array,
1038 .array_sentinel,
1039 .array_u8,
9911040 .array_u8_sentinel_0,
9921041 .fn_noreturn_no_args,
9931042 .fn_void_no_args,
......@@ -1003,6 +1052,7 @@ pub const Type = extern union {
10031052 .optional,
10041053 .optional_single_mut_pointer,
10051054 .optional_single_const_pointer,
1055 .enum_literal,
10061056 => false,
10071057 };
10081058 }
......@@ -1023,6 +1073,45 @@ pub const Type = extern union {
10231073 }
10241074 }
10251075
1076 /// Returns if type can be used for a runtime variable
1077 pub fn isValidVarType(self: Type) bool {
1078 var ty = self;
1079 while (true) switch (ty.zigTypeTag()) {
1080 .Bool,
1081 .Int,
1082 .Float,
1083 .ErrorSet,
1084 .Enum,
1085 .Frame,
1086 .AnyFrame,
1087 .Vector,
1088 => return true,
1089
1090 .BoundFn,
1091 .ComptimeFloat,
1092 .ComptimeInt,
1093 .EnumLiteral,
1094 .NoReturn,
1095 .Type,
1096 .Void,
1097 .Undefined,
1098 .Null,
1099 .Opaque,
1100 => return false,
1101
1102 .Optional => {
1103 var buf: Payload.Pointer = undefined;
1104 return ty.optionalChild(&buf).isValidVarType();
1105 },
1106 .Pointer, .Array => ty = ty.elemType(),
1107
1108 .ErrorUnion => @panic("TODO fn isValidVarType"),
1109 .Fn => @panic("TODO fn isValidVarType"),
1110 .Struct => @panic("TODO struct isValidVarType"),
1111 .Union => @panic("TODO union isValidVarType"),
1112 };
1113 }
1114
10261115 /// Asserts the type is a pointer or array type.
10271116 pub fn elemType(self: Type) Type {
10281117 return switch (self.tag()) {
......@@ -1069,12 +1158,14 @@ pub const Type = extern union {
10691158 .optional,
10701159 .optional_single_const_pointer,
10711160 .optional_single_mut_pointer,
1161 .enum_literal,
10721162 => unreachable,
10731163
10741164 .array => self.cast(Payload.Array).?.elem_type,
1165 .array_sentinel => self.cast(Payload.ArraySentinel).?.elem_type,
10751166 .single_const_pointer => self.castPointer().?.pointee_type,
10761167 .single_mut_pointer => self.castPointer().?.pointee_type,
1077 .array_u8_sentinel_0, .const_slice_u8 => Type.initTag(.u8),
1168 .array_u8, .array_u8_sentinel_0, .const_slice_u8 => Type.initTag(.u8),
10781169 .single_const_pointer_to_comptime_int => Type.initTag(.comptime_int),
10791170 };
10801171 }
......@@ -1173,9 +1264,12 @@ pub const Type = extern union {
11731264 .optional,
11741265 .optional_single_mut_pointer,
11751266 .optional_single_const_pointer,
1267 .enum_literal,
11761268 => unreachable,
11771269
11781270 .array => self.cast(Payload.Array).?.len,
1271 .array_sentinel => self.cast(Payload.ArraySentinel).?.len,
1272 .array_u8 => self.cast(Payload.Array_u8).?.len,
11791273 .array_u8_sentinel_0 => self.cast(Payload.Array_u8_Sentinel0).?.len,
11801274 };
11811275 }
......@@ -1230,9 +1324,11 @@ pub const Type = extern union {
12301324 .optional,
12311325 .optional_single_mut_pointer,
12321326 .optional_single_const_pointer,
1327 .enum_literal,
12331328 => unreachable,
12341329
1235 .array => return null,
1330 .array, .array_u8 => return null,
1331 .array_sentinel => return self.cast(Payload.ArraySentinel).?.sentinel,
12361332 .array_u8_sentinel_0 => return Value.initTag(.zero),
12371333 };
12381334 }
......@@ -1266,10 +1362,12 @@ pub const Type = extern union {
12661362 .fn_ccc_void_no_args,
12671363 .function,
12681364 .array,
1365 .array_sentinel,
1366 .array_u8,
1367 .array_u8_sentinel_0,
12691368 .single_const_pointer,
12701369 .single_mut_pointer,
12711370 .single_const_pointer_to_comptime_int,
1272 .array_u8_sentinel_0,
12731371 .const_slice_u8,
12741372 .int_unsigned,
12751373 .u8,
......@@ -1284,6 +1382,7 @@ pub const Type = extern union {
12841382 .optional,
12851383 .optional_single_mut_pointer,
12861384 .optional_single_const_pointer,
1385 .enum_literal,
12871386 => false,
12881387
12891388 .int_signed,
......@@ -1324,10 +1423,12 @@ pub const Type = extern union {
13241423 .fn_ccc_void_no_args,
13251424 .function,
13261425 .array,
1426 .array_sentinel,
1427 .array_u8,
1428 .array_u8_sentinel_0,
13271429 .single_const_pointer,
13281430 .single_mut_pointer,
13291431 .single_const_pointer_to_comptime_int,
1330 .array_u8_sentinel_0,
13311432 .const_slice_u8,
13321433 .int_signed,
13331434 .i8,
......@@ -1342,6 +1443,7 @@ pub const Type = extern union {
13421443 .optional,
13431444 .optional_single_mut_pointer,
13441445 .optional_single_const_pointer,
1446 .enum_literal,
13451447 => false,
13461448
13471449 .int_unsigned,
......@@ -1382,14 +1484,17 @@ pub const Type = extern union {
13821484 .fn_ccc_void_no_args,
13831485 .function,
13841486 .array,
1487 .array_sentinel,
1488 .array_u8,
1489 .array_u8_sentinel_0,
13851490 .single_const_pointer,
13861491 .single_mut_pointer,
13871492 .single_const_pointer_to_comptime_int,
1388 .array_u8_sentinel_0,
13891493 .const_slice_u8,
13901494 .optional,
13911495 .optional_single_mut_pointer,
13921496 .optional_single_const_pointer,
1497 .enum_literal,
13931498 => unreachable,
13941499
13951500 .int_unsigned => .{ .signed = false, .bits = self.cast(Payload.IntUnsigned).?.bits },
......@@ -1438,10 +1543,12 @@ pub const Type = extern union {
14381543 .fn_ccc_void_no_args,
14391544 .function,
14401545 .array,
1546 .array_sentinel,
1547 .array_u8,
1548 .array_u8_sentinel_0,
14411549 .single_const_pointer,
14421550 .single_mut_pointer,
14431551 .single_const_pointer_to_comptime_int,
1444 .array_u8_sentinel_0,
14451552 .const_slice_u8,
14461553 .int_unsigned,
14471554 .int_signed,
......@@ -1456,6 +1563,7 @@ pub const Type = extern union {
14561563 .optional,
14571564 .optional_single_mut_pointer,
14581565 .optional_single_const_pointer,
1566 .enum_literal,
14591567 => false,
14601568
14611569 .usize,
......@@ -1523,10 +1631,12 @@ pub const Type = extern union {
15231631 .@"null",
15241632 .@"undefined",
15251633 .array,
1634 .array_sentinel,
1635 .array_u8,
1636 .array_u8_sentinel_0,
15261637 .single_const_pointer,
15271638 .single_mut_pointer,
15281639 .single_const_pointer_to_comptime_int,
1529 .array_u8_sentinel_0,
15301640 .const_slice_u8,
15311641 .u8,
15321642 .i8,
......@@ -1551,6 +1661,7 @@ pub const Type = extern union {
15511661 .optional,
15521662 .optional_single_mut_pointer,
15531663 .optional_single_const_pointer,
1664 .enum_literal,
15541665 => unreachable,
15551666 };
15561667 }
......@@ -1584,10 +1695,12 @@ pub const Type = extern union {
15841695 .@"null",
15851696 .@"undefined",
15861697 .array,
1698 .array_sentinel,
1699 .array_u8,
1700 .array_u8_sentinel_0,
15871701 .single_const_pointer,
15881702 .single_mut_pointer,
15891703 .single_const_pointer_to_comptime_int,
1590 .array_u8_sentinel_0,
15911704 .const_slice_u8,
15921705 .u8,
15931706 .i8,
......@@ -1612,6 +1725,7 @@ pub const Type = extern union {
16121725 .optional,
16131726 .optional_single_mut_pointer,
16141727 .optional_single_const_pointer,
1728 .enum_literal,
16151729 => unreachable,
16161730 }
16171731 }
......@@ -1644,10 +1758,12 @@ pub const Type = extern union {
16441758 .@"null",
16451759 .@"undefined",
16461760 .array,
1761 .array_sentinel,
1762 .array_u8,
1763 .array_u8_sentinel_0,
16471764 .single_const_pointer,
16481765 .single_mut_pointer,
16491766 .single_const_pointer_to_comptime_int,
1650 .array_u8_sentinel_0,
16511767 .const_slice_u8,
16521768 .u8,
16531769 .i8,
......@@ -1672,6 +1788,7 @@ pub const Type = extern union {
16721788 .optional,
16731789 .optional_single_mut_pointer,
16741790 .optional_single_const_pointer,
1791 .enum_literal,
16751792 => unreachable,
16761793 }
16771794 }
......@@ -1704,10 +1821,12 @@ pub const Type = extern union {
17041821 .@"null",
17051822 .@"undefined",
17061823 .array,
1824 .array_sentinel,
1825 .array_u8,
1826 .array_u8_sentinel_0,
17071827 .single_const_pointer,
17081828 .single_mut_pointer,
17091829 .single_const_pointer_to_comptime_int,
1710 .array_u8_sentinel_0,
17111830 .const_slice_u8,
17121831 .u8,
17131832 .i8,
......@@ -1732,6 +1851,7 @@ pub const Type = extern union {
17321851 .optional,
17331852 .optional_single_mut_pointer,
17341853 .optional_single_const_pointer,
1854 .enum_literal,
17351855 => unreachable,
17361856 };
17371857 }
......@@ -1761,10 +1881,12 @@ pub const Type = extern union {
17611881 .@"null",
17621882 .@"undefined",
17631883 .array,
1884 .array_sentinel,
1885 .array_u8,
1886 .array_u8_sentinel_0,
17641887 .single_const_pointer,
17651888 .single_mut_pointer,
17661889 .single_const_pointer_to_comptime_int,
1767 .array_u8_sentinel_0,
17681890 .const_slice_u8,
17691891 .u8,
17701892 .i8,
......@@ -1789,6 +1911,7 @@ pub const Type = extern union {
17891911 .optional,
17901912 .optional_single_mut_pointer,
17911913 .optional_single_const_pointer,
1914 .enum_literal,
17921915 => unreachable,
17931916 };
17941917 }
......@@ -1818,10 +1941,12 @@ pub const Type = extern union {
18181941 .@"null",
18191942 .@"undefined",
18201943 .array,
1944 .array_sentinel,
1945 .array_u8,
1946 .array_u8_sentinel_0,
18211947 .single_const_pointer,
18221948 .single_mut_pointer,
18231949 .single_const_pointer_to_comptime_int,
1824 .array_u8_sentinel_0,
18251950 .const_slice_u8,
18261951 .u8,
18271952 .i8,
......@@ -1846,6 +1971,7 @@ pub const Type = extern union {
18461971 .optional,
18471972 .optional_single_mut_pointer,
18481973 .optional_single_const_pointer,
1974 .enum_literal,
18491975 => unreachable,
18501976 };
18511977 }
......@@ -1895,14 +2021,17 @@ pub const Type = extern union {
18952021 .fn_ccc_void_no_args,
18962022 .function,
18972023 .array,
2024 .array_sentinel,
2025 .array_u8,
2026 .array_u8_sentinel_0,
18982027 .single_const_pointer,
18992028 .single_mut_pointer,
19002029 .single_const_pointer_to_comptime_int,
1901 .array_u8_sentinel_0,
19022030 .const_slice_u8,
19032031 .optional,
19042032 .optional_single_mut_pointer,
19052033 .optional_single_const_pointer,
2034 .enum_literal,
19062035 => false,
19072036 };
19082037 }
......@@ -1944,12 +2073,14 @@ pub const Type = extern union {
19442073 .fn_ccc_void_no_args,
19452074 .function,
19462075 .single_const_pointer_to_comptime_int,
2076 .array_sentinel,
19472077 .array_u8_sentinel_0,
19482078 .const_slice_u8,
19492079 .c_void,
19502080 .optional,
19512081 .optional_single_mut_pointer,
19522082 .optional_single_const_pointer,
2083 .enum_literal,
19532084 => return null,
19542085
19552086 .void => return Value.initTag(.void_value),
......@@ -1971,11 +2102,10 @@ pub const Type = extern union {
19712102 return null;
19722103 }
19732104 },
1974 .array => {
1975 const array = ty.cast(Payload.Array).?;
1976 if (array.len == 0)
2105 .array, .array_u8 => {
2106 if (ty.arrayLen() == 0)
19772107 return Value.initTag(.empty_array);
1978 ty = array.elem_type;
2108 ty = ty.elemType();
19792109 continue;
19802110 },
19812111 .single_const_pointer, .single_mut_pointer => {
......@@ -2022,7 +2152,6 @@ pub const Type = extern union {
20222152 .fn_ccc_void_no_args,
20232153 .function,
20242154 .single_const_pointer_to_comptime_int,
2025 .array_u8_sentinel_0,
20262155 .const_slice_u8,
20272156 .c_void,
20282157 .void,
......@@ -2032,11 +2161,15 @@ pub const Type = extern union {
20322161 .int_unsigned,
20332162 .int_signed,
20342163 .array,
2164 .array_sentinel,
2165 .array_u8,
2166 .array_u8_sentinel_0,
20352167 .single_const_pointer,
20362168 .single_mut_pointer,
20372169 .optional,
20382170 .optional_single_mut_pointer,
20392171 .optional_single_const_pointer,
2172 .enum_literal,
20402173 => return false,
20412174 };
20422175 }
......@@ -2080,6 +2213,7 @@ pub const Type = extern union {
20802213 comptime_int,
20812214 comptime_float,
20822215 noreturn,
2216 enum_literal,
20832217 @"null",
20842218 @"undefined",
20852219 fn_noreturn_no_args,
......@@ -2090,8 +2224,10 @@ pub const Type = extern union {
20902224 const_slice_u8, // See last_no_payload_tag below.
20912225 // After this, the tag requires a payload.
20922226
2227 array_u8,
20932228 array_u8_sentinel_0,
20942229 array,
2230 array_sentinel,
20952231 single_const_pointer,
20962232 single_mut_pointer,
20972233 int_signed,
......@@ -2114,11 +2250,25 @@ pub const Type = extern union {
21142250 len: u64,
21152251 };
21162252
2253 pub const Array_u8 = struct {
2254 base: Payload = Payload{ .tag = .array_u8 },
2255
2256 len: u64,
2257 };
2258
21172259 pub const Array = struct {
21182260 base: Payload = Payload{ .tag = .array },
21192261
2262 len: u64,
21202263 elem_type: Type,
2264 };
2265
2266 pub const ArraySentinel = struct {
2267 base: Payload = Payload{ .tag = .array_sentinel },
2268
21212269 len: u64,
2270 sentinel: Value,
2271 elem_type: Type,
21222272 };
21232273
21242274 pub const Pointer = struct {
src-self-hosted/value.zig+33-2
......@@ -60,6 +60,7 @@ pub const Value = extern union {
6060 fn_ccc_void_no_args_type,
6161 single_const_pointer_to_comptime_int_type,
6262 const_slice_u8_type,
63 enum_literal_type,
6364
6465 undef,
6566 zero,
......@@ -87,6 +88,7 @@ pub const Value = extern union {
8788 float_32,
8889 float_64,
8990 float_128,
91 enum_literal,
9092
9193 pub const last_no_payload_tag = Tag.bool_false;
9294 pub const no_payload_count = @enumToInt(last_no_payload_tag) + 1;
......@@ -164,6 +166,7 @@ pub const Value = extern union {
164166 .fn_ccc_void_no_args_type,
165167 .single_const_pointer_to_comptime_int_type,
166168 .const_slice_u8_type,
169 .enum_literal_type,
167170 .undef,
168171 .zero,
169172 .void_value,
......@@ -213,7 +216,7 @@ pub const Value = extern union {
213216 };
214217 return Value{ .ptr_otherwise = &new_payload.base };
215218 },
216 .bytes => return self.copyPayloadShallow(allocator, Payload.Bytes),
219 .enum_literal, .bytes => return self.copyPayloadShallow(allocator, Payload.Bytes),
217220 .repeated => {
218221 const payload = @fieldParentPtr(Payload.Repeated, "base", self.ptr_otherwise);
219222 const new_payload = try allocator.create(Payload.Repeated);
......@@ -285,6 +288,7 @@ pub const Value = extern union {
285288 .fn_ccc_void_no_args_type => return out_stream.writeAll("fn() callconv(.C) void"),
286289 .single_const_pointer_to_comptime_int_type => return out_stream.writeAll("*const comptime_int"),
287290 .const_slice_u8_type => return out_stream.writeAll("[]const u8"),
291 .enum_literal_type => return out_stream.writeAll("@TypeOf(.EnumLiteral)"),
288292
289293 .null_value => return out_stream.writeAll("null"),
290294 .undef => return out_stream.writeAll("undefined"),
......@@ -318,7 +322,7 @@ pub const Value = extern union {
318322 val = elem_ptr.array_ptr;
319323 },
320324 .empty_array => return out_stream.writeAll(".{}"),
321 .bytes => return std.zig.renderStringLiteral(self.cast(Payload.Bytes).?.data, out_stream),
325 .enum_literal, .bytes => return std.zig.renderStringLiteral(self.cast(Payload.Bytes).?.data, out_stream),
322326 .repeated => {
323327 try out_stream.writeAll("(repeated) ");
324328 val = val.cast(Payload.Repeated).?.val;
......@@ -391,6 +395,7 @@ pub const Value = extern union {
391395 .fn_ccc_void_no_args_type => Type.initTag(.fn_ccc_void_no_args),
392396 .single_const_pointer_to_comptime_int_type => Type.initTag(.single_const_pointer_to_comptime_int),
393397 .const_slice_u8_type => Type.initTag(.const_slice_u8),
398 .enum_literal_type => Type.initTag(.enum_literal),
394399
395400 .undef,
396401 .zero,
......@@ -414,6 +419,7 @@ pub const Value = extern union {
414419 .float_32,
415420 .float_64,
416421 .float_128,
422 .enum_literal,
417423 => unreachable,
418424 };
419425 }
......@@ -462,6 +468,7 @@ pub const Value = extern union {
462468 .fn_ccc_void_no_args_type,
463469 .single_const_pointer_to_comptime_int_type,
464470 .const_slice_u8_type,
471 .enum_literal_type,
465472 .null_value,
466473 .function,
467474 .ref_val,
......@@ -476,6 +483,7 @@ pub const Value = extern union {
476483 .void_value,
477484 .unreachable_value,
478485 .empty_array,
486 .enum_literal,
479487 => unreachable,
480488
481489 .undef => unreachable,
......@@ -537,6 +545,7 @@ pub const Value = extern union {
537545 .fn_ccc_void_no_args_type,
538546 .single_const_pointer_to_comptime_int_type,
539547 .const_slice_u8_type,
548 .enum_literal_type,
540549 .null_value,
541550 .function,
542551 .ref_val,
......@@ -551,6 +560,7 @@ pub const Value = extern union {
551560 .void_value,
552561 .unreachable_value,
553562 .empty_array,
563 .enum_literal,
554564 => unreachable,
555565
556566 .undef => unreachable,
......@@ -612,6 +622,7 @@ pub const Value = extern union {
612622 .fn_ccc_void_no_args_type,
613623 .single_const_pointer_to_comptime_int_type,
614624 .const_slice_u8_type,
625 .enum_literal_type,
615626 .null_value,
616627 .function,
617628 .ref_val,
......@@ -626,6 +637,7 @@ pub const Value = extern union {
626637 .void_value,
627638 .unreachable_value,
628639 .empty_array,
640 .enum_literal,
629641 => unreachable,
630642
631643 .undef => unreachable,
......@@ -713,6 +725,7 @@ pub const Value = extern union {
713725 .fn_ccc_void_no_args_type,
714726 .single_const_pointer_to_comptime_int_type,
715727 .const_slice_u8_type,
728 .enum_literal_type,
716729 .null_value,
717730 .function,
718731 .ref_val,
......@@ -728,6 +741,7 @@ pub const Value = extern union {
728741 .void_value,
729742 .unreachable_value,
730743 .empty_array,
744 .enum_literal,
731745 => unreachable,
732746
733747 .zero,
......@@ -793,6 +807,7 @@ pub const Value = extern union {
793807 .fn_ccc_void_no_args_type,
794808 .single_const_pointer_to_comptime_int_type,
795809 .const_slice_u8_type,
810 .enum_literal_type,
796811 .null_value,
797812 .function,
798813 .ref_val,
......@@ -807,6 +822,7 @@ pub const Value = extern union {
807822 .void_value,
808823 .unreachable_value,
809824 .empty_array,
825 .enum_literal,
810826 => unreachable,
811827
812828 .zero,
......@@ -953,6 +969,7 @@ pub const Value = extern union {
953969 .fn_ccc_void_no_args_type,
954970 .single_const_pointer_to_comptime_int_type,
955971 .const_slice_u8_type,
972 .enum_literal_type,
956973 .bool_true,
957974 .bool_false,
958975 .null_value,
......@@ -970,6 +987,7 @@ pub const Value = extern union {
970987 .empty_array,
971988 .void_value,
972989 .unreachable_value,
990 .enum_literal,
973991 => unreachable,
974992
975993 .zero => false,
......@@ -1025,6 +1043,7 @@ pub const Value = extern union {
10251043 .fn_ccc_void_no_args_type,
10261044 .single_const_pointer_to_comptime_int_type,
10271045 .const_slice_u8_type,
1046 .enum_literal_type,
10281047 .null_value,
10291048 .function,
10301049 .ref_val,
......@@ -1036,6 +1055,7 @@ pub const Value = extern union {
10361055 .void_value,
10371056 .unreachable_value,
10381057 .empty_array,
1058 .enum_literal,
10391059 => unreachable,
10401060
10411061 .zero,
......@@ -1102,6 +1122,11 @@ pub const Value = extern union {
11021122 }
11031123
11041124 pub fn eql(a: Value, b: Value) bool {
1125 if (a.tag() == b.tag() and a.tag() == .enum_literal) {
1126 const a_name = @fieldParentPtr(Payload.Bytes, "base", a.ptr_otherwise).data;
1127 const b_name = @fieldParentPtr(Payload.Bytes, "base", b.ptr_otherwise).data;
1128 return std.mem.eql(u8, a_name, b_name);
1129 }
11051130 // TODO non numerical comparisons
11061131 return compare(a, .eq, b);
11071132 }
......@@ -1151,6 +1176,7 @@ pub const Value = extern union {
11511176 .fn_ccc_void_no_args_type,
11521177 .single_const_pointer_to_comptime_int_type,
11531178 .const_slice_u8_type,
1179 .enum_literal_type,
11541180 .zero,
11551181 .bool_true,
11561182 .bool_false,
......@@ -1170,6 +1196,7 @@ pub const Value = extern union {
11701196 .void_value,
11711197 .unreachable_value,
11721198 .empty_array,
1199 .enum_literal,
11731200 => unreachable,
11741201
11751202 .ref_val => self.cast(Payload.RefVal).?.val,
......@@ -1227,6 +1254,7 @@ pub const Value = extern union {
12271254 .fn_ccc_void_no_args_type,
12281255 .single_const_pointer_to_comptime_int_type,
12291256 .const_slice_u8_type,
1257 .enum_literal_type,
12301258 .zero,
12311259 .bool_true,
12321260 .bool_false,
......@@ -1246,6 +1274,7 @@ pub const Value = extern union {
12461274 .float_128,
12471275 .void_value,
12481276 .unreachable_value,
1277 .enum_literal,
12491278 => unreachable,
12501279
12511280 .empty_array => unreachable, // out of bounds array index
......@@ -1320,6 +1349,7 @@ pub const Value = extern union {
13201349 .fn_ccc_void_no_args_type,
13211350 .single_const_pointer_to_comptime_int_type,
13221351 .const_slice_u8_type,
1352 .enum_literal_type,
13231353 .zero,
13241354 .empty_array,
13251355 .bool_true,
......@@ -1339,6 +1369,7 @@ pub const Value = extern union {
13391369 .float_64,
13401370 .float_128,
13411371 .void_value,
1372 .enum_literal,
13421373 => false,
13431374
13441375 .undef => unreachable,
src-self-hosted/zir.zig+47-5
......@@ -47,6 +47,10 @@ pub const Inst = struct {
4747 array_cat,
4848 /// Array multiplication `a ** b`
4949 array_mul,
50 /// Create an array type
51 array_type,
52 /// Create an array type with sentinel
53 array_type_sentinel,
5054 /// Function parameter value. These must be first in a function's main block,
5155 /// in respective order with the parameters.
5256 arg,
......@@ -58,11 +62,11 @@ pub const Inst = struct {
5862 bitand,
5963 /// TODO delete this instruction, it has no purpose.
6064 bitcast,
61 /// An arbitrary typed pointer, which is to be used as an L-Value, is pointer-casted
62 /// to a new L-Value. The destination type is given by LHS. The cast is to be evaluated
65 /// An arbitrary typed pointer is pointer-casted to a new Pointer.
66 /// The destination type is given by LHS. The cast is to be evaluated
6367 /// as if it were a bit-cast operation from the operand pointer element type to the
6468 /// provided destination type.
65 bitcast_lvalue,
69 bitcast_ref,
6670 /// A typed result location pointer is bitcasted to a new result location pointer.
6771 /// The new result location pointer has an inferred type.
6872 bitcast_result_ptr,
......@@ -225,6 +229,10 @@ pub const Inst = struct {
225229 unwrap_err_safe,
226230 /// Same as previous, but without safety checks. Used for orelse, if and while
227231 unwrap_err_unsafe,
232 /// Takes a *E!T and raises a compiler error if T != void
233 ensure_err_payload_void,
234 /// Enum literal
235 enum_literal,
228236
229237 pub fn Type(tag: Tag) type {
230238 return switch (tag) {
......@@ -250,7 +258,7 @@ pub const Inst = struct {
250258 .ensure_result_non_error,
251259 .bitcast_result_ptr,
252260 .ref,
253 .bitcast_lvalue,
261 .bitcast_ref,
254262 .typeof,
255263 .single_const_ptr_type,
256264 .single_mut_ptr_type,
......@@ -259,12 +267,14 @@ pub const Inst = struct {
259267 .unwrap_optional_unsafe,
260268 .unwrap_err_safe,
261269 .unwrap_err_unsafe,
270 .ensure_err_payload_void,
262271 => UnOp,
263272
264273 .add,
265274 .addwrap,
266275 .array_cat,
267276 .array_mul,
277 .array_type,
268278 .bitand,
269279 .bitor,
270280 .div,
......@@ -291,6 +301,7 @@ pub const Inst = struct {
291301 => BinOp,
292302
293303 .arg => Arg,
304 .array_type_sentinel => ArrayTypeSentinel,
294305 .block => Block,
295306 .@"break" => Break,
296307 .breakvoid => BreakVoid,
......@@ -317,6 +328,7 @@ pub const Inst = struct {
317328 .elemptr => ElemPtr,
318329 .condbr => CondBr,
319330 .ptr_type => PtrType,
331 .enum_literal => EnumLiteral,
320332 };
321333 }
322334
......@@ -330,12 +342,14 @@ pub const Inst = struct {
330342 .alloc_inferred,
331343 .array_cat,
332344 .array_mul,
345 .array_type,
346 .array_type_sentinel,
333347 .arg,
334348 .as,
335349 .@"asm",
336350 .bitand,
337351 .bitcast,
338 .bitcast_lvalue,
352 .bitcast_ref,
339353 .bitcast_result_ptr,
340354 .bitor,
341355 .block,
......@@ -398,6 +412,8 @@ pub const Inst = struct {
398412 .unwrap_err_safe,
399413 .unwrap_err_unsafe,
400414 .ptr_type,
415 .ensure_err_payload_void,
416 .enum_literal,
401417 => false,
402418
403419 .@"break",
......@@ -845,6 +861,28 @@ pub const Inst = struct {
845861 sentinel: ?*Inst = null,
846862 },
847863 };
864
865 pub const ArrayTypeSentinel = struct {
866 pub const base_tag = Tag.array_type_sentinel;
867 base: Inst,
868
869 positionals: struct {
870 len: *Inst,
871 sentinel: *Inst,
872 elem_type: *Inst,
873 },
874 kw_args: struct {},
875 };
876
877 pub const EnumLiteral = struct {
878 pub const base_tag = Tag.enum_literal;
879 base: Inst,
880
881 positionals: struct {
882 name: []const u8,
883 },
884 kw_args: struct {},
885 };
848886};
849887
850888pub const ErrorMsg = struct {
......@@ -1922,6 +1960,10 @@ const EmitZIR = struct {
19221960 return self.emitUnnamedDecl(&str_inst.base);
19231961 },
19241962 .Void => return self.emitPrimitive(src, .void_value),
1963 .Bool => if (typed_value.val.toBool())
1964 return self.emitPrimitive(src, .@"true")
1965 else
1966 return self.emitPrimitive(src, .@"false"),
19251967 else => |t| std.debug.panic("TODO implement emitTypedValue for {}", .{@tagName(t)}),
19261968 }
19271969 }
src-self-hosted/zir_sema.zig+51-29
......@@ -29,7 +29,7 @@ pub fn analyzeInst(mod: *Module, scope: *Scope, old_inst: *zir.Inst) InnerError!
2929 .alloc => return analyzeInstAlloc(mod, scope, old_inst.castTag(.alloc).?),
3030 .alloc_inferred => return analyzeInstAllocInferred(mod, scope, old_inst.castTag(.alloc_inferred).?),
3131 .arg => return analyzeInstArg(mod, scope, old_inst.castTag(.arg).?),
32 .bitcast_lvalue => return analyzeInstBitCastLValue(mod, scope, old_inst.castTag(.bitcast_lvalue).?),
32 .bitcast_ref => return analyzeInstBitCastRef(mod, scope, old_inst.castTag(.bitcast_ref).?),
3333 .bitcast_result_ptr => return analyzeInstBitCastResultPtr(mod, scope, old_inst.castTag(.bitcast_result_ptr).?),
3434 .block => return analyzeInstBlock(mod, scope, old_inst.castTag(.block).?),
3535 .@"break" => return analyzeInstBreak(mod, scope, old_inst.castTag(.@"break").?),
......@@ -112,6 +112,10 @@ pub fn analyzeInst(mod: *Module, scope: *Scope, old_inst: *zir.Inst) InnerError!
112112 .unwrap_optional_unsafe => return analyzeInstUnwrapOptional(mod, scope, old_inst.castTag(.unwrap_optional_unsafe).?, false),
113113 .unwrap_err_safe => return analyzeInstUnwrapErr(mod, scope, old_inst.castTag(.unwrap_err_safe).?, true),
114114 .unwrap_err_unsafe => return analyzeInstUnwrapErr(mod, scope, old_inst.castTag(.unwrap_err_unsafe).?, false),
115 .ensure_err_payload_void => return analyzeInstEnsureErrPayloadVoid(mod, scope, old_inst.castTag(.ensure_err_payload_void).?),
116 .array_type => return analyzeInstArrayType(mod, scope, old_inst.castTag(.array_type).?),
117 .array_type_sentinel => return analyzeInstArrayTypeSentinel(mod, scope, old_inst.castTag(.array_type_sentinel).?),
118 .enum_literal => return analyzeInstEnumLiteral(mod, scope, old_inst.castTag(.enum_literal).?),
115119 }
116120}
117121
......@@ -295,8 +299,8 @@ fn analyzeInstCoerceResultBlockPtr(
295299 return mod.fail(scope, inst.base.src, "TODO implement analyzeInstCoerceResultBlockPtr", .{});
296300}
297301
298fn analyzeInstBitCastLValue(mod: *Module, scope: *Scope, inst: *zir.Inst.UnOp) InnerError!*Inst {
299 return mod.fail(scope, inst.base.src, "TODO implement analyzeInstBitCastLValue", .{});
302fn analyzeInstBitCastRef(mod: *Module, scope: *Scope, inst: *zir.Inst.UnOp) InnerError!*Inst {
303 return mod.fail(scope, inst.base.src, "TODO implement analyzeInstBitCastRef", .{});
300304}
301305
302306fn analyzeInstBitCastResultPtr(mod: *Module, scope: *Scope, inst: *zir.Inst.UnOp) InnerError!*Inst {
......@@ -361,6 +365,10 @@ fn analyzeInstEnsureResultNonError(mod: *Module, scope: *Scope, inst: *zir.Inst.
361365
362366fn analyzeInstAlloc(mod: *Module, scope: *Scope, inst: *zir.Inst.UnOp) InnerError!*Inst {
363367 const var_type = try resolveType(mod, scope, inst.positionals.operand);
368 // TODO this should happen only for var allocs
369 if (!var_type.isValidVarType()) {
370 return mod.fail(scope, inst.base.src, "variable of type '{}' must be const or comptime", .{var_type});
371 }
364372 const ptr_type = try mod.singlePtrType(scope, inst.base.src, true, var_type);
365373 const b = try mod.requireRuntimeBlock(scope, inst.base.src);
366374 return mod.addNoOp(b, inst.base.src, ptr_type, .alloc);
......@@ -675,31 +683,36 @@ fn analyzeInstIntType(mod: *Module, scope: *Scope, inttype: *zir.Inst.IntType) I
675683fn analyzeInstOptionalType(mod: *Module, scope: *Scope, optional: *zir.Inst.UnOp) InnerError!*Inst {
676684 const child_type = try resolveType(mod, scope, optional.positionals.operand);
677685
678 return mod.constType(scope, optional.base.src, Type.initPayload(switch (child_type.tag()) {
679 .single_const_pointer => blk: {
680 const payload = try scope.arena().create(Type.Payload.Pointer);
681 payload.* = .{
682 .base = .{ .tag = .optional_single_const_pointer },
683 .pointee_type = child_type.elemType(),
684 };
685 break :blk &payload.base;
686 },
687 .single_mut_pointer => blk: {
688 const payload = try scope.arena().create(Type.Payload.Pointer);
689 payload.* = .{
690 .base = .{ .tag = .optional_single_mut_pointer },
691 .pointee_type = child_type.elemType(),
692 };
693 break :blk &payload.base;
694 },
695 else => blk: {
696 const payload = try scope.arena().create(Type.Payload.Optional);
697 payload.* = .{
698 .child_type = child_type,
699 };
700 break :blk &payload.base;
701 },
702 }));
686 return mod.constType(scope, optional.base.src, try mod.optionalType(scope, child_type));
687}
688
689fn analyzeInstArrayType(mod: *Module, scope: *Scope, array: *zir.Inst.BinOp) InnerError!*Inst {
690 // TODO these should be lazily evaluated
691 const len = try resolveInstConst(mod, scope, array.positionals.lhs);
692 const elem_type = try resolveType(mod, scope, array.positionals.rhs);
693
694 return mod.constType(scope, array.base.src, try mod.arrayType(scope, len.val.toUnsignedInt(), null, elem_type));
695}
696
697fn analyzeInstArrayTypeSentinel(mod: *Module, scope: *Scope, array: *zir.Inst.ArrayTypeSentinel) InnerError!*Inst {
698 // TODO these should be lazily evaluated
699 const len = try resolveInstConst(mod, scope, array.positionals.len);
700 const sentinel = try resolveInstConst(mod, scope, array.positionals.sentinel);
701 const elem_type = try resolveType(mod, scope, array.positionals.elem_type);
702
703 return mod.constType(scope, array.base.src, try mod.arrayType(scope, len.val.toUnsignedInt(), sentinel.val, elem_type));
704}
705
706fn analyzeInstEnumLiteral(mod: *Module, scope: *Scope, inst: *zir.Inst.EnumLiteral) InnerError!*Inst {
707 const payload = try scope.arena().create(Value.Payload.Bytes);
708 payload.* = .{
709 .base = .{ .tag = .enum_literal },
710 .data = try scope.arena().dupe(u8, inst.positionals.name),
711 };
712 return mod.constInst(scope, inst.base.src, .{
713 .ty = Type.initTag(.enum_literal),
714 .val = Value.initPayload(&payload.base),
715 });
703716}
704717
705718fn analyzeInstUnwrapOptional(mod: *Module, scope: *Scope, unwrap: *zir.Inst.UnOp, safety_check: bool) InnerError!*Inst {
......@@ -735,6 +748,10 @@ fn analyzeInstUnwrapErr(mod: *Module, scope: *Scope, unwrap: *zir.Inst.UnOp, saf
735748 return mod.fail(scope, unwrap.base.src, "TODO implement analyzeInstUnwrapErr", .{});
736749}
737750
751fn analyzeInstEnsureErrPayloadVoid(mod: *Module, scope: *Scope, unwrap: *zir.Inst.UnOp) InnerError!*Inst {
752 return mod.fail(scope, unwrap.base.src, "TODO implement analyzeInstEnsureErrPayloadVoid", .{});
753}
754
738755fn analyzeInstFnType(mod: *Module, scope: *Scope, fntype: *zir.Inst.FnType) InnerError!*Inst {
739756 const return_type = try resolveType(mod, scope, fntype.positionals.return_type);
740757
......@@ -760,7 +777,12 @@ fn analyzeInstFnType(mod: *Module, scope: *Scope, fntype: *zir.Inst.FnType) Inne
760777 const arena = scope.arena();
761778 const param_types = try arena.alloc(Type, fntype.positionals.param_types.len);
762779 for (fntype.positionals.param_types) |param_type, i| {
763 param_types[i] = try resolveType(mod, scope, param_type);
780 const resolved = try resolveType(mod, scope, param_type);
781 // TODO skip for comptime params
782 if (!resolved.isValidVarType()) {
783 return mod.fail(scope, param_type.src, "parameter of type '{}' must be declared comptime", .{resolved});
784 }
785 param_types[i] = resolved;
764786 }
765787
766788 const payload = try arena.create(Type.Payload.Function);
test/stage2/compare_output.zig+32
......@@ -543,6 +543,38 @@ pub fn addCases(ctx: *TestContext) !void {
543543 ,
544544 "",
545545 );
546
547 case.addCompareOutput(
548 \\export fn _start() noreturn {
549 \\ const ignore =
550 \\ \\ cool thx
551 \\ \\
552 \\ ;
553 \\ add('ぁ', '\x03');
554 \\
555 \\ exit();
556 \\}
557 \\
558 \\fn add(a: u32, b: u32) void {
559 \\ assert(a + b == 12356);
560 \\}
561 \\
562 \\pub fn assert(ok: bool) void {
563 \\ if (!ok) unreachable; // assertion failure
564 \\}
565 \\
566 \\fn exit() noreturn {
567 \\ asm volatile ("syscall"
568 \\ :
569 \\ : [number] "{rax}" (231),
570 \\ [arg1] "{rdi}" (0)
571 \\ : "rcx", "r11", "memory"
572 \\ );
573 \\ unreachable;
574 \\}
575 ,
576 "",
577 );
546578 }
547579
548580 {