authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-08-24 15:42:30-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-08-24 15:42:30-07:00
logb30c5380765bea26647a72ec55f9191824e00d4e
tree7c3df86465e4319d4ed1b237d6b0f1fa3f166e81
parentfd9f509d6dcad43f5b1bf17e57b1f0b200755df8
parent16d54c70eb35b58e871c538bf172991aa81191fe

Merge branch 'Vexu-stage2'

closes #6148

6 files changed, 662 insertions(+), 76 deletions(-)

src-self-hosted/Module.zig+42
......@@ -80,6 +80,9 @@ deletion_set: std.ArrayListUnmanaged(*Decl) = .{},
8080root_name: []u8,
8181keep_source_files_loaded: bool,
8282
83/// Error tags and their values, tag names are duped with mod.gpa.
84global_error_set: std.StringHashMapUnmanaged(u16) = .{},
85
8386pub const InnerError = error{ OutOfMemory, AnalysisFail };
8487
8588const WorkItem = union(enum) {
......@@ -928,6 +931,11 @@ pub fn deinit(self: *Module) void {
928931
929932 self.symbol_exports.deinit(gpa);
930933 self.root_scope.destroy(gpa);
934
935 for (self.global_error_set.items()) |entry| {
936 gpa.free(entry.key);
937 }
938 self.global_error_set.deinit(gpa);
931939 self.* = undefined;
932940}
933941
......@@ -2072,6 +2080,18 @@ fn createNewDecl(
20722080 return new_decl;
20732081}
20742082
2083/// Get error value for error tag `name`.
2084pub fn getErrorValue(self: *Module, name: []const u8) !std.StringHashMapUnmanaged(u16).Entry {
2085 const gop = try self.global_error_set.getOrPut(self.gpa, name);
2086 if (gop.found_existing)
2087 return gop.entry.*;
2088 errdefer self.global_error_set.removeAssertDiscard(name);
2089
2090 gop.entry.key = try self.gpa.dupe(u8, name);
2091 gop.entry.value = @intCast(u16, self.global_error_set.items().len - 1);
2092 return gop.entry.*;
2093}
2094
20752095/// TODO split this into `requireRuntimeBlock` and `requireFunctionBlock` and audit callsites.
20762096pub fn requireRuntimeBlock(self: *Module, scope: *Scope, src: usize) !*Scope.Block {
20772097 return scope.cast(Scope.Block) orelse
......@@ -3309,6 +3329,28 @@ pub fn arrayType(self: *Module, scope: *Scope, len: u64, sentinel: ?Value, elem_
33093329 return Type.initPayload(&payload.base);
33103330}
33113331
3332pub fn errorUnionType(self: *Module, scope: *Scope, error_set: Type, payload: Type) Allocator.Error!Type {
3333 assert(error_set.zigTypeTag() == .ErrorSet);
3334 if (error_set.eql(Type.initTag(.anyerror)) and payload.eql(Type.initTag(.void))) {
3335 return Type.initTag(.anyerror_void_error_union);
3336 }
3337
3338 const result = try scope.arena().create(Type.Payload.ErrorUnion);
3339 result.* = .{
3340 .error_set = error_set,
3341 .payload = payload,
3342 };
3343 return Type.initPayload(&result.base);
3344}
3345
3346pub fn anyframeType(self: *Module, scope: *Scope, return_type: Type) Allocator.Error!Type {
3347 const result = try scope.arena().create(Type.Payload.AnyFrame);
3348 result.* = .{
3349 .return_type = return_type,
3350 };
3351 return Type.initPayload(&result.base);
3352}
3353
33123354pub fn dumpInst(self: *Module, scope: *Scope, inst: *Inst) void {
33133355 const zir_module = scope.namespace();
33143356 const source = zir_module.getSource(self) catch @panic("dumpInst failed to get source");
src-self-hosted/astgen.zig+100-61
......@@ -232,6 +232,11 @@ pub fn expr(mod: *Module, scope: *Scope, rl: ResultLoc, node: *ast.Node) InnerEr
232232 .BoolAnd => return boolBinOp(mod, scope, rl, node.castTag(.BoolAnd).?),
233233 .BoolOr => return boolBinOp(mod, scope, rl, node.castTag(.BoolOr).?),
234234
235 .BoolNot => return rlWrap(mod, scope, rl, try boolNot(mod, scope, node.castTag(.BoolNot).?)),
236 .BitNot => return rlWrap(mod, scope, rl, try bitNot(mod, scope, node.castTag(.BitNot).?)),
237 .Negation => return rlWrap(mod, scope, rl, try negation(mod, scope, node.castTag(.Negation).?, .sub)),
238 .NegationWrap => return rlWrap(mod, scope, rl, try negation(mod, scope, node.castTag(.NegationWrap).?, .subwrap)),
239
235240 .Identifier => return try identifier(mod, scope, rl, node.castTag(.Identifier).?),
236241 .Asm => return rlWrap(mod, scope, rl, try assembly(mod, scope, node.castTag(.Asm).?)),
237242 .StringLiteral => return rlWrap(mod, scope, rl, try stringLiteral(mod, scope, node.castTag(.StringLiteral).?)),
......@@ -242,9 +247,8 @@ pub fn expr(mod: *Module, scope: *Scope, rl: ResultLoc, node: *ast.Node) InnerEr
242247 .Return => return ret(mod, scope, node.castTag(.Return).?),
243248 .If => return ifExpr(mod, scope, rl, node.castTag(.If).?),
244249 .While => return whileExpr(mod, scope, rl, node.castTag(.While).?),
245 .Period => return rlWrap(mod, scope, rl, try field(mod, scope, node.castTag(.Period).?)),
250 .Period => return field(mod, scope, rl, node.castTag(.Period).?),
246251 .Deref => return rlWrap(mod, scope, rl, try deref(mod, scope, node.castTag(.Deref).?)),
247 .BoolNot => return rlWrap(mod, scope, rl, try boolNot(mod, scope, node.castTag(.BoolNot).?)),
248252 .AddressOf => return rlWrap(mod, scope, rl, try addressOf(mod, scope, node.castTag(.AddressOf).?)),
249253 .FloatLiteral => return rlWrap(mod, scope, rl, try floatLiteral(mod, scope, node.castTag(.FloatLiteral).?)),
250254 .UndefinedLiteral => return rlWrap(mod, scope, rl, try undefLiteral(mod, scope, node.castTag(.UndefinedLiteral).?)),
......@@ -263,17 +267,17 @@ pub fn expr(mod: *Module, scope: *Scope, rl: ResultLoc, node: *ast.Node) InnerEr
263267 .MultilineStringLiteral => return rlWrap(mod, scope, rl, try multilineStrLiteral(mod, scope, node.castTag(.MultilineStringLiteral).?)),
264268 .CharLiteral => return rlWrap(mod, scope, rl, try charLiteral(mod, scope, node.castTag(.CharLiteral).?)),
265269 .SliceType => return rlWrap(mod, scope, rl, try sliceType(mod, scope, node.castTag(.SliceType).?)),
270 .ErrorUnion => return rlWrap(mod, scope, rl, try typeInixOp(mod, scope, node.castTag(.ErrorUnion).?, .error_union_type)),
271 .MergeErrorSets => return rlWrap(mod, scope, rl, try typeInixOp(mod, scope, node.castTag(.MergeErrorSets).?, .merge_error_sets)),
272 .AnyFrameType => return rlWrap(mod, scope, rl, try anyFrameType(mod, scope, node.castTag(.AnyFrameType).?)),
273 .ErrorSetDecl => return errorSetDecl(mod, scope, rl, node.castTag(.ErrorSetDecl).?),
274 .ErrorType => return rlWrap(mod, scope, rl, try errorType(mod, scope, node.castTag(.ErrorType).?)),
266275
267276 .Defer => return mod.failNode(scope, node, "TODO implement astgen.expr for .Defer", .{}),
268277 .Catch => return mod.failNode(scope, node, "TODO implement astgen.expr for .Catch", .{}),
269 .ErrorUnion => return mod.failNode(scope, node, "TODO implement astgen.expr for .ErrorUnion", .{}),
270 .MergeErrorSets => return mod.failNode(scope, node, "TODO implement astgen.expr for .MergeErrorSets", .{}),
271278 .Range => return mod.failNode(scope, node, "TODO implement astgen.expr for .Range", .{}),
272279 .OrElse => return mod.failNode(scope, node, "TODO implement astgen.expr for .OrElse", .{}),
273280 .Await => return mod.failNode(scope, node, "TODO implement astgen.expr for .Await", .{}),
274 .BitNot => return mod.failNode(scope, node, "TODO implement astgen.expr for .BitNot", .{}),
275 .Negation => return mod.failNode(scope, node, "TODO implement astgen.expr for .Negation", .{}),
276 .NegationWrap => return mod.failNode(scope, node, "TODO implement astgen.expr for .NegationWrap", .{}),
277281 .Resume => return mod.failNode(scope, node, "TODO implement astgen.expr for .Resume", .{}),
278282 .Try => return mod.failNode(scope, node, "TODO implement astgen.expr for .Try", .{}),
279283 .Slice => return mod.failNode(scope, node, "TODO implement astgen.expr for .Slice", .{}),
......@@ -287,10 +291,7 @@ pub fn expr(mod: *Module, scope: *Scope, rl: ResultLoc, node: *ast.Node) InnerEr
287291 .Suspend => return mod.failNode(scope, node, "TODO implement astgen.expr for .Suspend", .{}),
288292 .Continue => return mod.failNode(scope, node, "TODO implement astgen.expr for .Continue", .{}),
289293 .AnyType => return mod.failNode(scope, node, "TODO implement astgen.expr for .AnyType", .{}),
290 .ErrorType => return mod.failNode(scope, node, "TODO implement astgen.expr for .ErrorType", .{}),
291294 .FnProto => return mod.failNode(scope, node, "TODO implement astgen.expr for .FnProto", .{}),
292 .AnyFrameType => return mod.failNode(scope, node, "TODO implement astgen.expr for .AnyFrameType", .{}),
293 .ErrorSetDecl => return mod.failNode(scope, node, "TODO implement astgen.expr for .ErrorSetDecl", .{}),
294295 .ContainerDecl => return mod.failNode(scope, node, "TODO implement astgen.expr for .ContainerDecl", .{}),
295296 .Comptime => return mod.failNode(scope, node, "TODO implement astgen.expr for .Comptime", .{}),
296297 .Nosuspend => return mod.failNode(scope, node, "TODO implement astgen.expr for .Nosuspend", .{}),
......@@ -458,7 +459,9 @@ fn varDecl(
458459 const tree = scope.tree();
459460 const name_src = tree.token_locs[node.name_token].start;
460461 const ident_name = try identifierTokenString(mod, scope, node.name_token);
461 const init_node = node.getTrailer("init_node").?;
462 const init_node = node.getTrailer("init_node") orelse
463 return mod.fail(scope, name_src, "variables must be initialized", .{});
464
462465 switch (tree.token_ids[node.mut_token]) {
463466 .Keyword_const => {
464467 // Depending on the type of AST the initialization expression is, we may need an lvalue
......@@ -554,6 +557,26 @@ fn boolNot(mod: *Module, scope: *Scope, node: *ast.Node.SimplePrefixOp) InnerErr
554557 return addZIRUnOp(mod, scope, src, .boolnot, operand);
555558}
556559
560fn bitNot(mod: *Module, scope: *Scope, node: *ast.Node.SimplePrefixOp) InnerError!*zir.Inst {
561 const tree = scope.tree();
562 const src = tree.token_locs[node.op_token].start;
563 const operand = try expr(mod, scope, .none, node.rhs);
564 return addZIRUnOp(mod, scope, src, .bitnot, operand);
565}
566
567fn negation(mod: *Module, scope: *Scope, node: *ast.Node.SimplePrefixOp, op_inst_tag: zir.Inst.Tag) InnerError!*zir.Inst {
568 const tree = scope.tree();
569 const src = tree.token_locs[node.op_token].start;
570
571 const lhs = try addZIRInstConst(mod, scope, src, .{
572 .ty = Type.initTag(.comptime_int),
573 .val = Value.initTag(.zero),
574 });
575 const rhs = try expr(mod, scope, .none, node.rhs);
576
577 return addZIRBinOp(mod, scope, src, op_inst_tag, lhs, rhs);
578}
579
557580fn addressOf(mod: *Module, scope: *Scope, node: *ast.Node.SimplePrefixOp) InnerError!*zir.Inst {
558581 return expr(mod, scope, .ref, node.rhs);
559582}
......@@ -561,11 +584,7 @@ fn addressOf(mod: *Module, scope: *Scope, node: *ast.Node.SimplePrefixOp) InnerE
561584fn optionalType(mod: *Module, scope: *Scope, node: *ast.Node.SimplePrefixOp) InnerError!*zir.Inst {
562585 const tree = scope.tree();
563586 const src = tree.token_locs[node.op_token].start;
564 const meta_type = try addZIRInstConst(mod, scope, src, .{
565 .ty = Type.initTag(.type),
566 .val = Value.initTag(.type_type),
567 });
568 const operand = try expr(mod, scope, .{ .ty = meta_type }, node.rhs);
587 const operand = try typeExpr(mod, scope, node.rhs);
569588 return addZIRUnOp(mod, scope, src, .optional_type, operand);
570589}
571590
......@@ -590,18 +609,13 @@ fn ptrType(mod: *Module, scope: *Scope, node: *ast.Node.PtrType) InnerError!*zir
590609}
591610
592611fn ptrSliceType(mod: *Module, scope: *Scope, src: usize, ptr_info: *ast.PtrInfo, rhs: *ast.Node, size: std.builtin.TypeInfo.Pointer.Size) InnerError!*zir.Inst {
593 const meta_type = try addZIRInstConst(mod, scope, src, .{
594 .ty = Type.initTag(.type),
595 .val = Value.initTag(.type_type),
596 });
597
598612 const simple = ptr_info.allowzero_token == null and
599613 ptr_info.align_info == null and
600614 ptr_info.volatile_token == null and
601615 ptr_info.sentinel == null;
602616
603617 if (simple) {
604 const child_type = try expr(mod, scope, .{ .ty = meta_type }, rhs);
618 const child_type = try typeExpr(mod, scope, rhs);
605619 const mutable = ptr_info.const_token == null;
606620 // TODO stage1 type inference bug
607621 const T = zir.Inst.Tag;
......@@ -629,7 +643,7 @@ fn ptrSliceType(mod: *Module, scope: *Scope, src: usize, ptr_info: *ast.PtrInfo,
629643 kw_args.sentinel = try expr(mod, scope, .none, some);
630644 }
631645
632 const child_type = try expr(mod, scope, .{ .ty = meta_type }, rhs);
646 const child_type = try typeExpr(mod, scope, rhs);
633647 if (kw_args.sentinel) |some| {
634648 kw_args.sentinel = try addZIRBinOp(mod, scope, some.src, .as, child_type, some);
635649 }
......@@ -640,10 +654,6 @@ fn ptrSliceType(mod: *Module, scope: *Scope, src: usize, ptr_info: *ast.PtrInfo,
640654fn arrayType(mod: *Module, scope: *Scope, node: *ast.Node.ArrayType) !*zir.Inst {
641655 const tree = scope.tree();
642656 const src = tree.token_locs[node.op_token].start;
643 const meta_type = try addZIRInstConst(mod, scope, src, .{
644 .ty = Type.initTag(.type),
645 .val = Value.initTag(.type_type),
646 });
647657 const usize_type = try addZIRInstConst(mod, scope, src, .{
648658 .ty = Type.initTag(.type),
649659 .val = Value.initTag(.usize_type),
......@@ -651,18 +661,14 @@ fn arrayType(mod: *Module, scope: *Scope, node: *ast.Node.ArrayType) !*zir.Inst
651661
652662 // TODO check for [_]T
653663 const len = try expr(mod, scope, .{ .ty = usize_type }, node.len_expr);
654 const child_type = try expr(mod, scope, .{ .ty = meta_type }, node.rhs);
664 const elem_type = try typeExpr(mod, scope, node.rhs);
655665
656 return addZIRBinOp(mod, scope, src, .array_type, len, child_type);
666 return addZIRBinOp(mod, scope, src, .array_type, len, elem_type);
657667}
658668
659669fn arrayTypeSentinel(mod: *Module, scope: *Scope, node: *ast.Node.ArrayTypeSentinel) !*zir.Inst {
660670 const tree = scope.tree();
661671 const src = tree.token_locs[node.op_token].start;
662 const meta_type = try addZIRInstConst(mod, scope, src, .{
663 .ty = Type.initTag(.type),
664 .val = Value.initTag(.type_type),
665 });
666672 const usize_type = try addZIRInstConst(mod, scope, src, .{
667673 .ty = Type.initTag(.type),
668674 .val = Value.initTag(.usize_type),
......@@ -671,7 +677,7 @@ fn arrayTypeSentinel(mod: *Module, scope: *Scope, node: *ast.Node.ArrayTypeSenti
671677 // TODO check for [_]T
672678 const len = try expr(mod, scope, .{ .ty = usize_type }, node.len_expr);
673679 const sentinel_uncasted = try expr(mod, scope, .none, node.sentinel);
674 const elem_type = try expr(mod, scope, .{ .ty = meta_type }, node.rhs);
680 const elem_type = try typeExpr(mod, scope, node.rhs);
675681 const sentinel = try addZIRBinOp(mod, scope, src, .as, elem_type, sentinel_uncasted);
676682
677683 return addZIRInst(mod, scope, src, zir.Inst.ArrayTypeSentinel, .{
......@@ -681,6 +687,28 @@ fn arrayTypeSentinel(mod: *Module, scope: *Scope, node: *ast.Node.ArrayTypeSenti
681687 }, .{});
682688}
683689
690fn anyFrameType(mod: *Module, scope: *Scope, node: *ast.Node.AnyFrameType) InnerError!*zir.Inst {
691 const tree = scope.tree();
692 const src = tree.token_locs[node.anyframe_token].start;
693 if (node.result) |some| {
694 const return_type = try typeExpr(mod, scope, some.return_type);
695 return addZIRUnOp(mod, scope, src, .anyframe_type, return_type);
696 } else {
697 return addZIRInstConst(mod, scope, src, .{
698 .ty = Type.initTag(.type),
699 .val = Value.initTag(.anyframe_type),
700 });
701 }
702}
703
704fn typeInixOp(mod: *Module, scope: *Scope, node: *ast.Node.SimpleInfixOp, op_inst_tag: zir.Inst.Tag) InnerError!*zir.Inst {
705 const tree = scope.tree();
706 const src = tree.token_locs[node.op_token].start;
707 const error_set = try typeExpr(mod, scope, node.lhs);
708 const payload = try typeExpr(mod, scope, node.rhs);
709 return addZIRBinOp(mod, scope, src, op_inst_tag, error_set, payload);
710}
711
684712fn enumLiteral(mod: *Module, scope: *Scope, node: *ast.Node.EnumLiteral) !*zir.Inst {
685713 const tree = scope.tree();
686714 const src = tree.token_locs[node.name].start;
......@@ -694,10 +722,31 @@ fn unwrapOptional(mod: *Module, scope: *Scope, rl: ResultLoc, node: *ast.Node.Si
694722 const src = tree.token_locs[node.rtoken].start;
695723
696724 const operand = try expr(mod, scope, .ref, node.lhs);
697 const unwrapped_ptr = try addZIRUnOp(mod, scope, src, .unwrap_optional_safe, operand);
698 if (rl == .lvalue or rl == .ref) return unwrapped_ptr;
725 return rlWrapPtr(mod, scope, rl, try addZIRUnOp(mod, scope, src, .unwrap_optional_safe, operand));
726}
699727
700 return rlWrap(mod, scope, rl, try addZIRUnOp(mod, scope, src, .deref, unwrapped_ptr));
728fn errorSetDecl(mod: *Module, scope: *Scope, rl: ResultLoc, node: *ast.Node.ErrorSetDecl) InnerError!*zir.Inst {
729 const tree = scope.tree();
730 const src = tree.token_locs[node.error_token].start;
731 const decls = node.decls();
732 const fields = try scope.arena().alloc([]const u8, decls.len);
733
734 for (decls) |decl, i| {
735 const tag = decl.castTag(.ErrorTag).?;
736 fields[i] = try identifierTokenString(mod, scope, tag.name_token);
737 }
738
739 // analyzing the error set results in a decl ref, so we might need to dereference it
740 return rlWrapPtr(mod, scope, rl, try addZIRInst(mod, scope, src, zir.Inst.ErrorSet, .{ .fields = fields }, .{}));
741}
742
743fn errorType(mod: *Module, scope: *Scope, node: *ast.Node.OneToken) InnerError!*zir.Inst {
744 const tree = scope.tree();
745 const src = tree.token_locs[node.token].start;
746 return addZIRInstConst(mod, scope, src, .{
747 .ty = Type.initTag(.type),
748 .val = Value.initTag(.anyerror_type),
749 });
701750}
702751
703752/// Return whether the identifier names of two tokens are equal. Resolves @"" tokens without allocating.
......@@ -737,16 +786,16 @@ pub fn identifierStringInst(mod: *Module, scope: *Scope, node: *ast.Node.OneToke
737786 return addZIRInst(mod, scope, src, zir.Inst.Str, .{ .bytes = ident_name }, .{});
738787}
739788
740fn field(mod: *Module, scope: *Scope, node: *ast.Node.SimpleInfixOp) InnerError!*zir.Inst {
741 // TODO introduce lvalues
789fn field(mod: *Module, scope: *Scope, rl: ResultLoc, node: *ast.Node.SimpleInfixOp) InnerError!*zir.Inst {
742790 const tree = scope.tree();
743791 const src = tree.token_locs[node.op_token].start;
744792
745 const lhs = try expr(mod, scope, .none, node.lhs);
793 const lhs = try expr(mod, scope, .ref, node.lhs);
746794 const field_name = try identifierStringInst(mod, scope, node.rhs.castTag(.Identifier).?);
747795
748796 const pointer = try addZIRInst(mod, scope, src, zir.Inst.FieldPtr, .{ .object_ptr = lhs, .field_name = field_name }, .{});
749 return addZIRUnOp(mod, scope, src, .deref, pointer);
797 if (rl == .ref or rl == .lvalue) return pointer;
798 return rlWrap(mod, scope, rl, try addZIRUnOp(mod, scope, src, .deref, pointer));
750799}
751800
752801fn deref(mod: *Module, scope: *Scope, node: *ast.Node.SimpleSuffixOp) InnerError!*zir.Inst {
......@@ -1232,12 +1281,7 @@ fn identifier(mod: *Module, scope: *Scope, rl: ResultLoc, ident: *ast.Node.OneTo
12321281 .local_ptr => {
12331282 const local_ptr = s.cast(Scope.LocalPtr).?;
12341283 if (mem.eql(u8, local_ptr.name, ident_name)) {
1235 if (rl == .lvalue or rl == .ref) {
1236 return local_ptr.ptr;
1237 } else {
1238 const result = try addZIRUnOp(mod, scope, src, .deref, local_ptr.ptr);
1239 return rlWrap(mod, scope, rl, result);
1240 }
1284 return rlWrapPtr(mod, scope, rl, local_ptr.ptr);
12411285 }
12421286 s = local_ptr.parent;
12431287 },
......@@ -1247,10 +1291,7 @@ fn identifier(mod: *Module, scope: *Scope, rl: ResultLoc, ident: *ast.Node.OneTo
12471291 }
12481292
12491293 if (mod.lookupDeclName(scope, ident_name)) |decl| {
1250 const result = try addZIRInst(mod, scope, src, zir.Inst.DeclValInModule, .{ .decl = decl }, .{});
1251 if (rl == .lvalue or rl == .ref)
1252 return result;
1253 return rlWrap(mod, scope, rl, try addZIRUnOp(mod, scope, src, .deref, result));
1294 return rlWrapPtr(mod, scope, rl, try addZIRInst(mod, scope, src, zir.Inst.DeclValInModule, .{ .decl = decl }, .{}));
12541295 }
12551296
12561297 return mod.failNode(scope, &ident.base, "use of undeclared identifier '{}'", .{ident_name});
......@@ -1466,12 +1507,8 @@ fn simpleCast(
14661507 try ensureBuiltinParamCount(mod, scope, call, 2);
14671508 const tree = scope.tree();
14681509 const src = tree.token_locs[call.builtin_token].start;
1469 const type_type = try addZIRInstConst(mod, scope, src, .{
1470 .ty = Type.initTag(.type),
1471 .val = Value.initTag(.type_type),
1472 });
14731510 const params = call.params();
1474 const dest_type = try expr(mod, scope, .{ .ty = type_type }, params[0]);
1511 const dest_type = try typeExpr(mod, scope, params[0]);
14751512 const rhs = try expr(mod, scope, .none, params[1]);
14761513 const result = try addZIRBinOp(mod, scope, src, inst_tag, dest_type, rhs);
14771514 return rlWrap(mod, scope, rl, result);
......@@ -1533,12 +1570,8 @@ fn bitCast(mod: *Module, scope: *Scope, rl: ResultLoc, call: *ast.Node.BuiltinCa
15331570 try ensureBuiltinParamCount(mod, scope, call, 2);
15341571 const tree = scope.tree();
15351572 const src = tree.token_locs[call.builtin_token].start;
1536 const type_type = try addZIRInstConst(mod, scope, src, .{
1537 .ty = Type.initTag(.type),
1538 .val = Value.initTag(.type_type),
1539 });
15401573 const params = call.params();
1541 const dest_type = try expr(mod, scope, .{ .ty = type_type }, params[0]);
1574 const dest_type = try typeExpr(mod, scope, params[0]);
15421575 switch (rl) {
15431576 .none => {
15441577 const operand = try expr(mod, scope, .none, params[1]);
......@@ -1852,6 +1885,12 @@ fn rlWrapVoid(mod: *Module, scope: *Scope, rl: ResultLoc, node: *ast.Node, resul
18521885 return rlWrap(mod, scope, rl, void_inst);
18531886}
18541887
1888fn rlWrapPtr(mod: *Module, scope: *Scope, rl: ResultLoc, ptr: *zir.Inst) InnerError!*zir.Inst {
1889 if (rl == .lvalue or rl == .ref) return ptr;
1890
1891 return rlWrap(mod, scope, rl, try addZIRUnOp(mod, scope, ptr.src, .deref, ptr));
1892}
1893
18551894pub fn addZIRInstSpecial(
18561895 mod: *Module,
18571896 scope: *Scope,
src-self-hosted/type.zig+250-7
......@@ -3,6 +3,7 @@ const Value = @import("value.zig").Value;
33const assert = std.debug.assert;
44const Allocator = std.mem.Allocator;
55const Target = std.Target;
6const Module = @import("Module.zig");
67
78/// This is the raw data, with no bookkeeping, no memory awareness, no de-duplication.
89/// It's important for this type to be small.
......@@ -52,7 +53,7 @@ pub const Type = extern union {
5253 .bool => return .Bool,
5354 .void => return .Void,
5455 .type => return .Type,
55 .anyerror => return .ErrorSet,
56 .error_set, .error_set_single, .anyerror => return .ErrorSet,
5657 .comptime_int => return .ComptimeInt,
5758 .comptime_float => return .ComptimeFloat,
5859 .noreturn => return .NoReturn,
......@@ -84,6 +85,10 @@ pub const Type = extern union {
8485 .optional_single_mut_pointer,
8586 => return .Optional,
8687 .enum_literal => return .EnumLiteral,
88
89 .anyerror_void_error_union, .error_union => return .ErrorUnion,
90
91 .anyframe_T, .@"anyframe" => return .AnyFrame,
8792 }
8893 }
8994
......@@ -151,6 +156,9 @@ pub const Type = extern union {
151156 .ComptimeInt => return true,
152157 .Undefined => return true,
153158 .Null => return true,
159 .AnyFrame => {
160 return a.elemType().eql(b.elemType());
161 },
154162 .Pointer => {
155163 // Hot path for common case:
156164 if (a.castPointer()) |a_payload| {
......@@ -225,7 +233,6 @@ pub const Type = extern union {
225233 .BoundFn,
226234 .Opaque,
227235 .Frame,
228 .AnyFrame,
229236 .Vector,
230237 => std.debug.panic("TODO implement Type equality comparison of {} and {}", .{ a, b }),
231238 }
......@@ -343,6 +350,8 @@ pub const Type = extern union {
343350 .single_const_pointer_to_comptime_int,
344351 .const_slice_u8,
345352 .enum_literal,
353 .anyerror_void_error_union,
354 .@"anyframe",
346355 => unreachable,
347356
348357 .array_u8_sentinel_0 => return self.copyPayloadShallow(allocator, Payload.Array_u8_Sentinel0),
......@@ -397,6 +406,7 @@ pub const Type = extern union {
397406 .optional_single_mut_pointer,
398407 .optional_single_const_pointer,
399408 => return self.copyPayloadSingleField(allocator, Payload.PointerSimple, "pointee_type"),
409 .anyframe_T => return self.copyPayloadSingleField(allocator, Payload.AnyFrame, "return_type"),
400410
401411 .pointer => {
402412 const payload = @fieldParentPtr(Payload.Pointer, "base", self.ptr_otherwise);
......@@ -416,6 +426,19 @@ pub const Type = extern union {
416426 };
417427 return Type{ .ptr_otherwise = &new_payload.base };
418428 },
429 .error_union => {
430 const payload = @fieldParentPtr(Payload.ErrorUnion, "base", self.ptr_otherwise);
431 const new_payload = try allocator.create(Payload.ErrorUnion);
432 new_payload.* = .{
433 .base = payload.base,
434
435 .error_set = try payload.error_set.copy(allocator),
436 .payload = try payload.payload.copy(allocator),
437 };
438 return Type{ .ptr_otherwise = &new_payload.base };
439 },
440 .error_set => return self.copyPayloadShallow(allocator, Payload.ErrorSet),
441 .error_set_single => return self.copyPayloadShallow(allocator, Payload.ErrorSetSingle),
419442 }
420443 }
421444
......@@ -482,6 +505,8 @@ pub const Type = extern union {
482505 .@"null" => return out_stream.writeAll("@TypeOf(null)"),
483506 .@"undefined" => return out_stream.writeAll("@TypeOf(undefined)"),
484507
508 .@"anyframe" => return out_stream.writeAll("anyframe"),
509 .anyerror_void_error_union => return out_stream.writeAll("anyerror!void"),
485510 .const_slice_u8 => return out_stream.writeAll("[]const u8"),
486511 .fn_noreturn_no_args => return out_stream.writeAll("fn() noreturn"),
487512 .fn_void_no_args => return out_stream.writeAll("fn() void"),
......@@ -500,6 +525,12 @@ pub const Type = extern union {
500525 continue;
501526 },
502527
528 .anyframe_T => {
529 const payload = @fieldParentPtr(Payload.AnyFrame, "base", ty.ptr_otherwise);
530 try out_stream.print("anyframe->", .{});
531 ty = payload.return_type;
532 continue;
533 },
503534 .array_u8 => {
504535 const payload = @fieldParentPtr(Payload.Array_u8, "base", ty.ptr_otherwise);
505536 return out_stream.print("[{}]u8", .{payload.len});
......@@ -622,6 +653,21 @@ pub const Type = extern union {
622653 ty = payload.pointee_type;
623654 continue;
624655 },
656 .error_union => {
657 const payload = @fieldParentPtr(Payload.ErrorUnion, "base", ty.ptr_otherwise);
658 try payload.error_set.format("", .{}, out_stream);
659 try out_stream.writeAll("!");
660 ty = payload.payload;
661 continue;
662 },
663 .error_set => {
664 const payload = @fieldParentPtr(Payload.ErrorSet, "base", ty.ptr_otherwise);
665 return out_stream.writeAll(std.mem.spanZ(payload.decl.name));
666 },
667 .error_set_single => {
668 const payload = @fieldParentPtr(Payload.ErrorSetSingle, "base", ty.ptr_otherwise);
669 return out_stream.print("error{{{}}}", .{payload.name});
670 },
625671 }
626672 unreachable;
627673 }
......@@ -715,6 +761,11 @@ pub const Type = extern union {
715761 .optional,
716762 .optional_single_mut_pointer,
717763 .optional_single_const_pointer,
764 .@"anyframe",
765 .anyframe_T,
766 .anyerror_void_error_union,
767 .error_set,
768 .error_set_single,
718769 => true,
719770 // TODO lazy types
720771 .array => self.elemType().hasCodeGenBits() and self.arrayLen() != 0,
......@@ -723,6 +774,11 @@ pub const Type = extern union {
723774 .int_signed => self.cast(Payload.IntSigned).?.bits == 0,
724775 .int_unsigned => self.cast(Payload.IntUnsigned).?.bits == 0,
725776
777 .error_union => {
778 const payload = self.cast(Payload.ErrorUnion).?;
779 return payload.error_set.hasCodeGenBits() or payload.payload.hasCodeGenBits();
780 },
781
726782 .c_void,
727783 .void,
728784 .type,
......@@ -779,6 +835,8 @@ pub const Type = extern union {
779835 .mut_slice,
780836 .optional_single_const_pointer,
781837 .optional_single_mut_pointer,
838 .@"anyframe",
839 .anyframe_T,
782840 => return @divExact(target.cpu.arch.ptrBitWidth(), 8),
783841
784842 .pointer => {
......@@ -803,7 +861,11 @@ pub const Type = extern union {
803861 .f128 => return 16,
804862 .c_longdouble => return 16,
805863
806 .anyerror => return 2, // TODO revisit this when we have the concept of the error tag type
864 .error_set,
865 .error_set_single,
866 .anyerror_void_error_union,
867 .anyerror,
868 => return 2, // TODO revisit this when we have the concept of the error tag type
807869
808870 .array, .array_sentinel => return self.elemType().abiAlignment(target),
809871
......@@ -829,6 +891,16 @@ pub const Type = extern union {
829891 return child_type.abiAlignment(target);
830892 },
831893
894 .error_union => {
895 const payload = self.cast(Payload.ErrorUnion).?;
896 if (!payload.error_set.hasCodeGenBits()) {
897 return payload.payload.abiAlignment(target);
898 } else if (!payload.payload.hasCodeGenBits()) {
899 return payload.error_set.abiAlignment(target);
900 }
901 @panic("TODO abiAlignment error union");
902 },
903
832904 .c_void,
833905 .void,
834906 .type,
......@@ -882,12 +954,15 @@ pub const Type = extern union {
882954 .i32, .u32 => return 4,
883955 .i64, .u64 => return 8,
884956
885 .isize, .usize => return @divExact(target.cpu.arch.ptrBitWidth(), 8),
957 .@"anyframe", .anyframe_T, .isize, .usize => return @divExact(target.cpu.arch.ptrBitWidth(), 8),
886958
887959 .const_slice,
888960 .mut_slice,
889 .const_slice_u8,
890 => return @divExact(target.cpu.arch.ptrBitWidth(), 8) * 2,
961 => {
962 if (self.elemType().hasCodeGenBits()) return @divExact(target.cpu.arch.ptrBitWidth(), 8) * 2;
963 return @divExact(target.cpu.arch.ptrBitWidth(), 8);
964 },
965 .const_slice_u8 => return @divExact(target.cpu.arch.ptrBitWidth(), 8) * 2,
891966
892967 .optional_single_const_pointer,
893968 .optional_single_mut_pointer,
......@@ -923,7 +998,11 @@ pub const Type = extern union {
923998 .f128 => return 16,
924999 .c_longdouble => return 16,
9251000
926 .anyerror => return 2, // TODO revisit this when we have the concept of the error tag type
1001 .error_set,
1002 .error_set_single,
1003 .anyerror_void_error_union,
1004 .anyerror,
1005 => return 2, // TODO revisit this when we have the concept of the error tag type
9271006
9281007 .int_signed, .int_unsigned => {
9291008 const bits: u16 = if (self.cast(Payload.IntSigned)) |pl|
......@@ -950,6 +1029,18 @@ pub const Type = extern union {
9501029 // to the child type's ABI alignment.
9511030 return child_type.abiAlignment(target) + child_type.abiSize(target);
9521031 },
1032
1033 .error_union => {
1034 const payload = self.cast(Payload.ErrorUnion).?;
1035 if (!payload.error_set.hasCodeGenBits() and !payload.payload.hasCodeGenBits()) {
1036 return 0;
1037 } else if (!payload.error_set.hasCodeGenBits()) {
1038 return payload.payload.abiSize(target);
1039 } else if (!payload.payload.hasCodeGenBits()) {
1040 return payload.error_set.abiSize(target);
1041 }
1042 @panic("TODO abiSize error union");
1043 },
9531044 };
9541045 }
9551046
......@@ -1010,6 +1101,12 @@ pub const Type = extern union {
10101101 .c_mut_pointer,
10111102 .const_slice,
10121103 .mut_slice,
1104 .error_union,
1105 .@"anyframe",
1106 .anyframe_T,
1107 .anyerror_void_error_union,
1108 .error_set,
1109 .error_set_single,
10131110 => false,
10141111
10151112 .single_const_pointer,
......@@ -1078,6 +1175,12 @@ pub const Type = extern union {
10781175 .optional_single_mut_pointer,
10791176 .optional_single_const_pointer,
10801177 .enum_literal,
1178 .error_union,
1179 .@"anyframe",
1180 .anyframe_T,
1181 .anyerror_void_error_union,
1182 .error_set,
1183 .error_set_single,
10811184 => false,
10821185
10831186 .const_slice,
......@@ -1143,6 +1246,12 @@ pub const Type = extern union {
11431246 .optional_single_const_pointer,
11441247 .enum_literal,
11451248 .mut_slice,
1249 .error_union,
1250 .@"anyframe",
1251 .anyframe_T,
1252 .anyerror_void_error_union,
1253 .error_set,
1254 .error_set_single,
11461255 => false,
11471256
11481257 .single_const_pointer,
......@@ -1217,6 +1326,12 @@ pub const Type = extern union {
12171326 .optional_single_mut_pointer,
12181327 .optional_single_const_pointer,
12191328 .enum_literal,
1329 .error_union,
1330 .@"anyframe",
1331 .anyframe_T,
1332 .anyerror_void_error_union,
1333 .error_set,
1334 .error_set_single,
12201335 => false,
12211336
12221337 .pointer => {
......@@ -1328,6 +1443,12 @@ pub const Type = extern union {
13281443 .optional_single_const_pointer,
13291444 .optional_single_mut_pointer,
13301445 .enum_literal,
1446 .error_union,
1447 .@"anyframe",
1448 .anyframe_T,
1449 .anyerror_void_error_union,
1450 .error_set,
1451 .error_set_single,
13311452 => unreachable,
13321453
13331454 .array => self.cast(Payload.Array).?.elem_type,
......@@ -1449,6 +1570,12 @@ pub const Type = extern union {
14491570 .optional_single_mut_pointer,
14501571 .optional_single_const_pointer,
14511572 .enum_literal,
1573 .error_union,
1574 .@"anyframe",
1575 .anyframe_T,
1576 .anyerror_void_error_union,
1577 .error_set,
1578 .error_set_single,
14521579 => unreachable,
14531580
14541581 .array => self.cast(Payload.Array).?.len,
......@@ -1516,6 +1643,12 @@ pub const Type = extern union {
15161643 .optional_single_mut_pointer,
15171644 .optional_single_const_pointer,
15181645 .enum_literal,
1646 .error_union,
1647 .@"anyframe",
1648 .anyframe_T,
1649 .anyerror_void_error_union,
1650 .error_set,
1651 .error_set_single,
15191652 => unreachable,
15201653
15211654 .array, .array_u8 => return null,
......@@ -1581,6 +1714,12 @@ pub const Type = extern union {
15811714 .optional_single_mut_pointer,
15821715 .optional_single_const_pointer,
15831716 .enum_literal,
1717 .error_union,
1718 .@"anyframe",
1719 .anyframe_T,
1720 .anyerror_void_error_union,
1721 .error_set,
1722 .error_set_single,
15841723 => false,
15851724
15861725 .int_signed,
......@@ -1649,6 +1788,12 @@ pub const Type = extern union {
16491788 .optional_single_mut_pointer,
16501789 .optional_single_const_pointer,
16511790 .enum_literal,
1791 .error_union,
1792 .@"anyframe",
1793 .anyframe_T,
1794 .anyerror_void_error_union,
1795 .error_set,
1796 .error_set_single,
16521797 => false,
16531798
16541799 .int_unsigned,
......@@ -1707,6 +1852,12 @@ pub const Type = extern union {
17071852 .optional_single_mut_pointer,
17081853 .optional_single_const_pointer,
17091854 .enum_literal,
1855 .error_union,
1856 .@"anyframe",
1857 .anyframe_T,
1858 .anyerror_void_error_union,
1859 .error_set,
1860 .error_set_single,
17101861 => unreachable,
17111862
17121863 .int_unsigned => .{ .signed = false, .bits = self.cast(Payload.IntUnsigned).?.bits },
......@@ -1783,6 +1934,12 @@ pub const Type = extern union {
17831934 .optional_single_mut_pointer,
17841935 .optional_single_const_pointer,
17851936 .enum_literal,
1937 .error_union,
1938 .@"anyframe",
1939 .anyframe_T,
1940 .anyerror_void_error_union,
1941 .error_set,
1942 .error_set_single,
17861943 => false,
17871944
17881945 .usize,
......@@ -1888,6 +2045,12 @@ pub const Type = extern union {
18882045 .optional_single_mut_pointer,
18892046 .optional_single_const_pointer,
18902047 .enum_literal,
2048 .error_union,
2049 .@"anyframe",
2050 .anyframe_T,
2051 .anyerror_void_error_union,
2052 .error_set,
2053 .error_set_single,
18912054 => unreachable,
18922055 };
18932056 }
......@@ -1959,6 +2122,12 @@ pub const Type = extern union {
19592122 .optional_single_mut_pointer,
19602123 .optional_single_const_pointer,
19612124 .enum_literal,
2125 .error_union,
2126 .@"anyframe",
2127 .anyframe_T,
2128 .anyerror_void_error_union,
2129 .error_set,
2130 .error_set_single,
19622131 => unreachable,
19632132 }
19642133 }
......@@ -2029,6 +2198,12 @@ pub const Type = extern union {
20292198 .optional_single_mut_pointer,
20302199 .optional_single_const_pointer,
20312200 .enum_literal,
2201 .error_union,
2202 .@"anyframe",
2203 .anyframe_T,
2204 .anyerror_void_error_union,
2205 .error_set,
2206 .error_set_single,
20322207 => unreachable,
20332208 }
20342209 }
......@@ -2099,6 +2274,12 @@ pub const Type = extern union {
20992274 .optional_single_mut_pointer,
21002275 .optional_single_const_pointer,
21012276 .enum_literal,
2277 .error_union,
2278 .@"anyframe",
2279 .anyframe_T,
2280 .anyerror_void_error_union,
2281 .error_set,
2282 .error_set_single,
21022283 => unreachable,
21032284 };
21042285 }
......@@ -2166,6 +2347,12 @@ pub const Type = extern union {
21662347 .optional_single_mut_pointer,
21672348 .optional_single_const_pointer,
21682349 .enum_literal,
2350 .error_union,
2351 .@"anyframe",
2352 .anyframe_T,
2353 .anyerror_void_error_union,
2354 .error_set,
2355 .error_set_single,
21692356 => unreachable,
21702357 };
21712358 }
......@@ -2233,6 +2420,12 @@ pub const Type = extern union {
22332420 .optional_single_mut_pointer,
22342421 .optional_single_const_pointer,
22352422 .enum_literal,
2423 .error_union,
2424 .@"anyframe",
2425 .anyframe_T,
2426 .anyerror_void_error_union,
2427 .error_set,
2428 .error_set_single,
22362429 => unreachable,
22372430 };
22382431 }
......@@ -2300,6 +2493,12 @@ pub const Type = extern union {
23002493 .optional_single_mut_pointer,
23012494 .optional_single_const_pointer,
23022495 .enum_literal,
2496 .error_union,
2497 .@"anyframe",
2498 .anyframe_T,
2499 .anyerror_void_error_union,
2500 .error_set,
2501 .error_set_single,
23032502 => false,
23042503 };
23052504 }
......@@ -2351,6 +2550,12 @@ pub const Type = extern union {
23512550 .optional_single_mut_pointer,
23522551 .optional_single_const_pointer,
23532552 .enum_literal,
2553 .anyerror_void_error_union,
2554 .anyframe_T,
2555 .@"anyframe",
2556 .error_union,
2557 .error_set,
2558 .error_set_single,
23542559 => return null,
23552560
23562561 .void => return Value.initTag(.void_value),
......@@ -2454,6 +2659,12 @@ pub const Type = extern union {
24542659 .optional_single_mut_pointer,
24552660 .optional_single_const_pointer,
24562661 .enum_literal,
2662 .error_union,
2663 .@"anyframe",
2664 .anyframe_T,
2665 .anyerror_void_error_union,
2666 .error_set,
2667 .error_set_single,
24572668 => return false,
24582669
24592670 .c_const_pointer,
......@@ -2511,6 +2722,8 @@ pub const Type = extern union {
25112722 fn_naked_noreturn_no_args,
25122723 fn_ccc_void_no_args,
25132724 single_const_pointer_to_comptime_int,
2725 anyerror_void_error_union,
2726 @"anyframe",
25142727 const_slice_u8, // See last_no_payload_tag below.
25152728 // After this, the tag requires a payload.
25162729
......@@ -2533,6 +2746,10 @@ pub const Type = extern union {
25332746 optional,
25342747 optional_single_mut_pointer,
25352748 optional_single_const_pointer,
2749 error_union,
2750 anyframe_T,
2751 error_set,
2752 error_set_single,
25362753
25372754 pub const last_no_payload_tag = Tag.const_slice_u8;
25382755 pub const no_payload_count = @enumToInt(last_no_payload_tag) + 1;
......@@ -2614,6 +2831,32 @@ pub const Type = extern union {
26142831 @"volatile": bool,
26152832 size: std.builtin.TypeInfo.Pointer.Size,
26162833 };
2834
2835 pub const ErrorUnion = struct {
2836 base: Payload = .{ .tag = .error_union },
2837
2838 error_set: Type,
2839 payload: Type,
2840 };
2841
2842 pub const AnyFrame = struct {
2843 base: Payload = .{ .tag = .anyframe_T },
2844
2845 return_type: Type,
2846 };
2847
2848 pub const ErrorSet = struct {
2849 base: Payload = .{ .tag = .error_set },
2850
2851 decl: *Module.Decl,
2852 };
2853
2854 pub const ErrorSetSingle = struct {
2855 base: Payload = .{ .tag = .error_set_single },
2856
2857 /// memory is owned by `Module`
2858 name: []const u8,
2859 };
26172860 };
26182861};
26192862
src-self-hosted/value.zig+88-3
......@@ -61,6 +61,7 @@ pub const Value = extern union {
6161 single_const_pointer_to_comptime_int_type,
6262 const_slice_u8_type,
6363 enum_literal_type,
64 anyframe_type,
6465
6566 undef,
6667 zero,
......@@ -90,6 +91,8 @@ pub const Value = extern union {
9091 float_64,
9192 float_128,
9293 enum_literal,
94 error_set,
95 @"error",
9396
9497 pub const last_no_payload_tag = Tag.bool_false;
9598 pub const no_payload_count = @enumToInt(last_no_payload_tag) + 1;
......@@ -168,6 +171,7 @@ pub const Value = extern union {
168171 .single_const_pointer_to_comptime_int_type,
169172 .const_slice_u8_type,
170173 .enum_literal_type,
174 .anyframe_type,
171175 .undef,
172176 .zero,
173177 .void_value,
......@@ -241,6 +245,10 @@ pub const Value = extern union {
241245 };
242246 return Value{ .ptr_otherwise = &new_payload.base };
243247 },
248 .@"error" => return self.copyPayloadShallow(allocator, Payload.Error),
249
250 // memory is managed by the declaration
251 .error_set => return self.copyPayloadShallow(allocator, Payload.ErrorSet),
244252 }
245253 }
246254
......@@ -300,6 +308,7 @@ pub const Value = extern union {
300308 .single_const_pointer_to_comptime_int_type => return out_stream.writeAll("*const comptime_int"),
301309 .const_slice_u8_type => return out_stream.writeAll("[]const u8"),
302310 .enum_literal_type => return out_stream.writeAll("@TypeOf(.EnumLiteral)"),
311 .anyframe_type => return out_stream.writeAll("anyframe"),
303312
304313 .null_value => return out_stream.writeAll("null"),
305314 .undef => return out_stream.writeAll("undefined"),
......@@ -343,6 +352,15 @@ pub const Value = extern union {
343352 .float_32 => return out_stream.print("{}", .{val.cast(Payload.Float_32).?.val}),
344353 .float_64 => return out_stream.print("{}", .{val.cast(Payload.Float_64).?.val}),
345354 .float_128 => return out_stream.print("{}", .{val.cast(Payload.Float_128).?.val}),
355 .error_set => {
356 const error_set = val.cast(Payload.ErrorSet).?;
357 try out_stream.writeAll("error{");
358 for (error_set.fields.items()) |entry| {
359 try out_stream.print("{},", .{entry.value});
360 }
361 return out_stream.writeAll("}");
362 },
363 .@"error" => return out_stream.print("error.{}", .{val.cast(Payload.Error).?.name}),
346364 };
347365 }
348366
......@@ -363,11 +381,9 @@ pub const Value = extern union {
363381 }
364382
365383 /// Asserts that the value is representable as a type.
366 pub fn toType(self: Value) Type {
384 pub fn toType(self: Value, allocator: *Allocator) !Type {
367385 return switch (self.tag()) {
368386 .ty => self.cast(Payload.Ty).?.ty,
369 .int_type => @panic("TODO int type to type"),
370
371387 .u8_type => Type.initTag(.u8),
372388 .i8_type => Type.initTag(.i8),
373389 .u16_type => Type.initTag(.u16),
......@@ -408,6 +424,26 @@ pub const Value = extern union {
408424 .single_const_pointer_to_comptime_int_type => Type.initTag(.single_const_pointer_to_comptime_int),
409425 .const_slice_u8_type => Type.initTag(.const_slice_u8),
410426 .enum_literal_type => Type.initTag(.enum_literal),
427 .anyframe_type => Type.initTag(.@"anyframe"),
428
429 .int_type => {
430 const payload = self.cast(Payload.IntType).?;
431 if (payload.signed) {
432 const new = try allocator.create(Type.Payload.IntSigned);
433 new.* = .{ .bits = payload.bits };
434 return Type.initPayload(&new.base);
435 } else {
436 const new = try allocator.create(Type.Payload.IntUnsigned);
437 new.* = .{ .bits = payload.bits };
438 return Type.initPayload(&new.base);
439 }
440 },
441 .error_set => {
442 const payload = self.cast(Payload.ErrorSet).?;
443 const new = try allocator.create(Type.Payload.ErrorSet);
444 new.* = .{ .decl = payload.decl };
445 return Type.initPayload(&new.base);
446 },
411447
412448 .undef,
413449 .zero,
......@@ -433,6 +469,7 @@ pub const Value = extern union {
433469 .float_64,
434470 .float_128,
435471 .enum_literal,
472 .@"error",
436473 => unreachable,
437474 };
438475 }
......@@ -482,6 +519,7 @@ pub const Value = extern union {
482519 .single_const_pointer_to_comptime_int_type,
483520 .const_slice_u8_type,
484521 .enum_literal_type,
522 .anyframe_type,
485523 .null_value,
486524 .function,
487525 .variable,
......@@ -498,6 +536,8 @@ pub const Value = extern union {
498536 .unreachable_value,
499537 .empty_array,
500538 .enum_literal,
539 .error_set,
540 .@"error",
501541 => unreachable,
502542
503543 .undef => unreachable,
......@@ -560,6 +600,7 @@ pub const Value = extern union {
560600 .single_const_pointer_to_comptime_int_type,
561601 .const_slice_u8_type,
562602 .enum_literal_type,
603 .anyframe_type,
563604 .null_value,
564605 .function,
565606 .variable,
......@@ -576,6 +617,8 @@ pub const Value = extern union {
576617 .unreachable_value,
577618 .empty_array,
578619 .enum_literal,
620 .error_set,
621 .@"error",
579622 => unreachable,
580623
581624 .undef => unreachable,
......@@ -638,6 +681,7 @@ pub const Value = extern union {
638681 .single_const_pointer_to_comptime_int_type,
639682 .const_slice_u8_type,
640683 .enum_literal_type,
684 .anyframe_type,
641685 .null_value,
642686 .function,
643687 .variable,
......@@ -654,6 +698,8 @@ pub const Value = extern union {
654698 .unreachable_value,
655699 .empty_array,
656700 .enum_literal,
701 .error_set,
702 .@"error",
657703 => unreachable,
658704
659705 .undef => unreachable,
......@@ -742,6 +788,7 @@ pub const Value = extern union {
742788 .single_const_pointer_to_comptime_int_type,
743789 .const_slice_u8_type,
744790 .enum_literal_type,
791 .anyframe_type,
745792 .null_value,
746793 .function,
747794 .variable,
......@@ -759,6 +806,8 @@ pub const Value = extern union {
759806 .unreachable_value,
760807 .empty_array,
761808 .enum_literal,
809 .error_set,
810 .@"error",
762811 => unreachable,
763812
764813 .zero,
......@@ -825,6 +874,7 @@ pub const Value = extern union {
825874 .single_const_pointer_to_comptime_int_type,
826875 .const_slice_u8_type,
827876 .enum_literal_type,
877 .anyframe_type,
828878 .null_value,
829879 .function,
830880 .variable,
......@@ -841,6 +891,8 @@ pub const Value = extern union {
841891 .unreachable_value,
842892 .empty_array,
843893 .enum_literal,
894 .error_set,
895 .@"error",
844896 => unreachable,
845897
846898 .zero,
......@@ -988,6 +1040,7 @@ pub const Value = extern union {
9881040 .single_const_pointer_to_comptime_int_type,
9891041 .const_slice_u8_type,
9901042 .enum_literal_type,
1043 .anyframe_type,
9911044 .bool_true,
9921045 .bool_false,
9931046 .null_value,
......@@ -1007,6 +1060,8 @@ pub const Value = extern union {
10071060 .void_value,
10081061 .unreachable_value,
10091062 .enum_literal,
1063 .error_set,
1064 .@"error",
10101065 => unreachable,
10111066
10121067 .zero => false,
......@@ -1063,6 +1118,7 @@ pub const Value = extern union {
10631118 .single_const_pointer_to_comptime_int_type,
10641119 .const_slice_u8_type,
10651120 .enum_literal_type,
1121 .anyframe_type,
10661122 .null_value,
10671123 .function,
10681124 .variable,
......@@ -1076,6 +1132,8 @@ pub const Value = extern union {
10761132 .unreachable_value,
10771133 .empty_array,
10781134 .enum_literal,
1135 .error_set,
1136 .@"error",
10791137 => unreachable,
10801138
10811139 .zero,
......@@ -1197,6 +1255,7 @@ pub const Value = extern union {
11971255 .single_const_pointer_to_comptime_int_type,
11981256 .const_slice_u8_type,
11991257 .enum_literal_type,
1258 .anyframe_type,
12001259 .zero,
12011260 .bool_true,
12021261 .bool_false,
......@@ -1218,6 +1277,8 @@ pub const Value = extern union {
12181277 .unreachable_value,
12191278 .empty_array,
12201279 .enum_literal,
1280 .error_set,
1281 .@"error",
12211282 => unreachable,
12221283
12231284 .ref_val => self.cast(Payload.RefVal).?.val,
......@@ -1276,6 +1337,7 @@ pub const Value = extern union {
12761337 .single_const_pointer_to_comptime_int_type,
12771338 .const_slice_u8_type,
12781339 .enum_literal_type,
1340 .anyframe_type,
12791341 .zero,
12801342 .bool_true,
12811343 .bool_false,
......@@ -1297,6 +1359,8 @@ pub const Value = extern union {
12971359 .void_value,
12981360 .unreachable_value,
12991361 .enum_literal,
1362 .error_set,
1363 .@"error",
13001364 => unreachable,
13011365
13021366 .empty_array => unreachable, // out of bounds array index
......@@ -1372,6 +1436,7 @@ pub const Value = extern union {
13721436 .single_const_pointer_to_comptime_int_type,
13731437 .const_slice_u8_type,
13741438 .enum_literal_type,
1439 .anyframe_type,
13751440 .zero,
13761441 .empty_array,
13771442 .bool_true,
......@@ -1393,6 +1458,8 @@ pub const Value = extern union {
13931458 .float_128,
13941459 .void_value,
13951460 .enum_literal,
1461 .error_set,
1462 .@"error",
13961463 => false,
13971464
13981465 .undef => unreachable,
......@@ -1522,6 +1589,24 @@ pub const Value = extern union {
15221589 base: Payload = .{ .tag = .float_128 },
15231590 val: f128,
15241591 };
1592
1593 pub const ErrorSet = struct {
1594 base: Payload = .{ .tag = .error_set },
1595
1596 // TODO revisit this when we have the concept of the error tag type
1597 fields: std.StringHashMapUnmanaged(u16),
1598 decl: *Module.Decl,
1599 };
1600
1601 pub const Error = struct {
1602 base: Payload = .{ .tag = .@"error" },
1603
1604 // TODO revisit this when we have the concept of the error tag type
1605 /// `name` is owned by `Module` and will be valid for the entire
1606 /// duration of the compilation.
1607 name: []const u8,
1608 value: u16,
1609 };
15251610 };
15261611
15271612 /// Big enough to fit any non-BigInt value
src-self-hosted/zir.zig+56-1
......@@ -43,6 +43,8 @@ pub const Inst = struct {
4343 alloc,
4444 /// Same as `alloc` except the type is inferred.
4545 alloc_inferred,
46 /// Create an `anyframe->T`.
47 anyframe_type,
4648 /// Array concatenation. `a ++ b`
4749 array_cat,
4850 /// Array multiplication `a ** b`
......@@ -70,6 +72,8 @@ pub const Inst = struct {
7072 /// A typed result location pointer is bitcasted to a new result location pointer.
7173 /// The new result location pointer has an inferred type.
7274 bitcast_result_ptr,
75 /// Bitwise NOT. `~`
76 bitnot,
7377 /// Bitwise OR. `|`
7478 bitor,
7579 /// A labeled block of code, which can return a value.
......@@ -133,6 +137,10 @@ pub const Inst = struct {
133137 ensure_result_used,
134138 /// Emits a compile error if an error is ignored.
135139 ensure_result_non_error,
140 /// Create a `E!T` type.
141 error_union_type,
142 /// Create an error set.
143 error_set,
136144 /// Export the provided Decl as the provided name in the compilation's output object file.
137145 @"export",
138146 /// Given a pointer to a struct or object that contains virtual fields, returns a pointer
......@@ -160,6 +168,8 @@ pub const Inst = struct {
160168 /// A labeled block of code that loops forever. At the end of the body it is implied
161169 /// to repeat; no explicit "repeat" instruction terminates loop bodies.
162170 loop,
171 /// Merge two error sets into one, `E1 || E2`.
172 merge_error_sets,
163173 /// Ambiguously remainder division or modulus. If the computation would possibly have
164174 /// a different value depending on whether the operation is remainder division or modulus,
165175 /// a compile error is emitted. Otherwise the computation is performed.
......@@ -286,6 +296,8 @@ pub const Inst = struct {
286296 .unwrap_err_safe,
287297 .unwrap_err_unsafe,
288298 .ensure_err_payload_void,
299 .anyframe_type,
300 .bitnot,
289301 => UnOp,
290302
291303 .add,
......@@ -316,6 +328,8 @@ pub const Inst = struct {
316328 .bitcast,
317329 .coerce_result_ptr,
318330 .xor,
331 .error_union_type,
332 .merge_error_sets,
319333 => BinOp,
320334
321335 .arg => Arg,
......@@ -347,6 +361,7 @@ pub const Inst = struct {
347361 .condbr => CondBr,
348362 .ptr_type => PtrType,
349363 .enum_literal => EnumLiteral,
364 .error_set => ErrorSet,
350365 };
351366 }
352367
......@@ -438,6 +453,11 @@ pub const Inst = struct {
438453 .ptr_type,
439454 .ensure_err_payload_void,
440455 .enum_literal,
456 .merge_error_sets,
457 .anyframe_type,
458 .error_union_type,
459 .bitnot,
460 .error_set,
441461 => false,
442462
443463 .@"break",
......@@ -908,6 +928,16 @@ pub const Inst = struct {
908928 },
909929 kw_args: struct {},
910930 };
931
932 pub const ErrorSet = struct {
933 pub const base_tag = Tag.error_set;
934 base: Inst,
935
936 positionals: struct {
937 fields: [][]const u8,
938 },
939 kw_args: struct {},
940 };
911941};
912942
913943pub const ErrorMsg = struct {
......@@ -1142,6 +1172,16 @@ const Writer = struct {
11421172 const name = self.loop_table.get(param).?;
11431173 return std.zig.renderStringLiteral(name, stream);
11441174 },
1175 [][]const u8 => {
1176 try stream.writeByte('[');
1177 for (param) |str, i| {
1178 if (i != 0) {
1179 try stream.writeAll(", ");
1180 }
1181 try std.zig.renderStringLiteral(str, stream);
1182 }
1183 try stream.writeByte(']');
1184 },
11451185 else => |T| @compileError("unimplemented: rendering parameter of type " ++ @typeName(T)),
11461186 }
11471187 }
......@@ -1539,6 +1579,21 @@ const Parser = struct {
15391579 const name = try self.parseStringLiteral();
15401580 return self.loop_table.get(name).?;
15411581 },
1582 [][]const u8 => {
1583 try requireEatBytes(self, "[");
1584 skipSpace(self);
1585 if (eatByte(self, ']')) return &[0][]const u8{};
1586
1587 var strings = std.ArrayList([]const u8).init(&self.arena.allocator);
1588 while (true) {
1589 skipSpace(self);
1590 try strings.append(try self.parseStringLiteral());
1591 skipSpace(self);
1592 if (!eatByte(self, ',')) break;
1593 }
1594 try requireEatBytes(self, "]");
1595 return strings.toOwnedSlice();
1596 },
15421597 else => @compileError("Unimplemented: ir parseParameterGeneric for type " ++ @typeName(T)),
15431598 }
15441599 return self.fail("TODO parse parameter {}", .{@typeName(T)});
......@@ -1961,7 +2016,7 @@ const EmitZIR = struct {
19612016 return self.emitUnnamedDecl(&as_inst.base);
19622017 },
19632018 .Type => {
1964 const ty = typed_value.val.toType();
2019 const ty = try typed_value.val.toType(&self.arena.allocator);
19652020 return self.emitType(src, ty);
19662021 },
19672022 .Fn => {
src-self-hosted/zir_sema.zig+126-4
......@@ -97,6 +97,7 @@ pub fn analyzeInst(mod: *Module, scope: *Scope, old_inst: *zir.Inst) InnerError!
9797 .array_cat => return analyzeInstArrayCat(mod, scope, old_inst.castTag(.array_cat).?),
9898 .array_mul => return analyzeInstArrayMul(mod, scope, old_inst.castTag(.array_mul).?),
9999 .bitand => return analyzeInstBitwise(mod, scope, old_inst.castTag(.bitand).?),
100 .bitnot => return analyzeInstBitNot(mod, scope, old_inst.castTag(.bitnot).?),
100101 .bitor => return analyzeInstBitwise(mod, scope, old_inst.castTag(.bitor).?),
101102 .xor => return analyzeInstBitwise(mod, scope, old_inst.castTag(.xor).?),
102103 .shl => return analyzeInstShl(mod, scope, old_inst.castTag(.shl).?),
......@@ -122,6 +123,10 @@ pub fn analyzeInst(mod: *Module, scope: *Scope, old_inst: *zir.Inst) InnerError!
122123 .array_type => return analyzeInstArrayType(mod, scope, old_inst.castTag(.array_type).?),
123124 .array_type_sentinel => return analyzeInstArrayTypeSentinel(mod, scope, old_inst.castTag(.array_type_sentinel).?),
124125 .enum_literal => return analyzeInstEnumLiteral(mod, scope, old_inst.castTag(.enum_literal).?),
126 .merge_error_sets => return analyzeInstMergeErrorSets(mod, scope, old_inst.castTag(.merge_error_sets).?),
127 .error_union_type => return analyzeInstErrorUnionType(mod, scope, old_inst.castTag(.error_union_type).?),
128 .anyframe_type => return analyzeInstAnyframeType(mod, scope, old_inst.castTag(.anyframe_type).?),
129 .error_set => return analyzeInstErrorSet(mod, scope, old_inst.castTag(.error_set).?),
125130 }
126131}
127132
......@@ -145,7 +150,7 @@ pub fn analyzeBodyValueAsType(mod: *Module, block_scope: *Scope.Block, body: zir
145150 for (block_scope.instructions.items) |inst| {
146151 if (inst.castTag(.ret)) |ret| {
147152 const val = try mod.resolveConstValue(&block_scope.base, ret.operand);
148 return val.toType();
153 return val.toType(block_scope.base.arena());
149154 } else {
150155 return mod.fail(&block_scope.base, inst.src, "unable to resolve comptime value", .{});
151156 }
......@@ -270,7 +275,7 @@ fn resolveType(mod: *Module, scope: *Scope, old_inst: *zir.Inst) !Type {
270275 const wanted_type = Type.initTag(.@"type");
271276 const coerced_inst = try mod.coerce(scope, wanted_type, new_inst);
272277 const val = try mod.resolveConstValue(scope, coerced_inst);
273 return val.toType();
278 return val.toType(scope.arena());
274279}
275280
276281fn resolveInt(mod: *Module, scope: *Scope, old_inst: *zir.Inst, dest_type: Type) !u64 {
......@@ -431,6 +436,7 @@ fn analyzeInstStr(mod: *Module, scope: *Scope, str_inst: *zir.Inst.Str) InnerErr
431436 // The bytes references memory inside the ZIR module, which can get deallocated
432437 // after semantic analysis is complete. We need the memory to be in the new anonymous Decl's arena.
433438 var new_decl_arena = std.heap.ArenaAllocator.init(mod.gpa);
439 errdefer new_decl_arena.deinit();
434440 const arena_bytes = try new_decl_arena.allocator.dupe(u8, str_inst.positionals.bytes);
435441
436442 const ty_payload = try scope.arena().create(Type.Payload.Array_u8_Sentinel0);
......@@ -716,6 +722,54 @@ fn analyzeInstArrayTypeSentinel(mod: *Module, scope: *Scope, array: *zir.Inst.Ar
716722 return mod.constType(scope, array.base.src, try mod.arrayType(scope, len.val.toUnsignedInt(), sentinel.val, elem_type));
717723}
718724
725fn analyzeInstErrorUnionType(mod: *Module, scope: *Scope, inst: *zir.Inst.BinOp) InnerError!*Inst {
726 const error_union = try resolveType(mod, scope, inst.positionals.lhs);
727 const payload = try resolveType(mod, scope, inst.positionals.rhs);
728
729 if (error_union.zigTypeTag() != .ErrorSet) {
730 return mod.fail(scope, inst.base.src, "expected error set type, found {}", .{error_union.elemType()});
731 }
732
733 return mod.constType(scope, inst.base.src, try mod.errorUnionType(scope, error_union, payload));
734}
735
736fn analyzeInstAnyframeType(mod: *Module, scope: *Scope, inst: *zir.Inst.UnOp) InnerError!*Inst {
737 const return_type = try resolveType(mod, scope, inst.positionals.operand);
738
739 return mod.constType(scope, inst.base.src, try mod.anyframeType(scope, return_type));
740}
741
742fn analyzeInstErrorSet(mod: *Module, scope: *Scope, inst: *zir.Inst.ErrorSet) InnerError!*Inst {
743 // The declarations arena will store the hashmap.
744 var new_decl_arena = std.heap.ArenaAllocator.init(mod.gpa);
745 errdefer new_decl_arena.deinit();
746
747 const payload = try scope.arena().create(Value.Payload.ErrorSet);
748 payload.* = .{
749 .fields = .{},
750 .decl = undefined, // populated below
751 };
752 try payload.fields.ensureCapacity(&new_decl_arena.allocator, inst.positionals.fields.len);
753
754 for (inst.positionals.fields) |field_name| {
755 const entry = try mod.getErrorValue(field_name);
756 if (payload.fields.fetchPutAssumeCapacity(entry.key, entry.value)) |prev| {
757 return mod.fail(scope, inst.base.src, "duplicate error: '{}'", .{field_name});
758 }
759 }
760 // TODO create name in format "error:line:column"
761 const new_decl = try mod.createAnonymousDecl(scope, &new_decl_arena, .{
762 .ty = Type.initTag(.type),
763 .val = Value.initPayload(&payload.base),
764 });
765 payload.decl = new_decl;
766 return mod.analyzeDeclRef(scope, inst.base.src, new_decl);
767}
768
769fn analyzeInstMergeErrorSets(mod: *Module, scope: *Scope, inst: *zir.Inst.BinOp) InnerError!*Inst {
770 return mod.fail(scope, inst.base.src, "TODO implement merge_error_sets", .{});
771}
772
719773fn analyzeInstEnumLiteral(mod: *Module, scope: *Scope, inst: *zir.Inst.EnumLiteral) InnerError!*Inst {
720774 const payload = try scope.arena().create(Value.Payload.Bytes);
721775 payload.* = .{
......@@ -858,8 +912,72 @@ fn analyzeInstFieldPtr(mod: *Module, scope: *Scope, fieldptr: *zir.Inst.FieldPtr
858912 );
859913 }
860914 },
861 else => return mod.fail(scope, fieldptr.base.src, "type '{}' does not support field access", .{elem_ty}),
915 .Pointer => {
916 const ptr_child = elem_ty.elemType();
917 switch (ptr_child.zigTypeTag()) {
918 .Array => {
919 if (mem.eql(u8, field_name, "len")) {
920 const len_payload = try scope.arena().create(Value.Payload.Int_u64);
921 len_payload.* = .{ .int = ptr_child.arrayLen() };
922
923 const ref_payload = try scope.arena().create(Value.Payload.RefVal);
924 ref_payload.* = .{ .val = Value.initPayload(&len_payload.base) };
925
926 return mod.constInst(scope, fieldptr.base.src, .{
927 .ty = Type.initTag(.single_const_pointer_to_comptime_int),
928 .val = Value.initPayload(&ref_payload.base),
929 });
930 } else {
931 return mod.fail(
932 scope,
933 fieldptr.positionals.field_name.src,
934 "no member named '{}' in '{}'",
935 .{ field_name, elem_ty },
936 );
937 }
938 },
939 else => {},
940 }
941 },
942 .Type => {
943 _ = try mod.resolveConstValue(scope, object_ptr);
944 const result = try mod.analyzeDeref(scope, fieldptr.base.src, object_ptr, object_ptr.src);
945 const val = result.value().?;
946 const child_type = try val.toType(scope.arena());
947 switch (child_type.zigTypeTag()) {
948 .ErrorSet => {
949 // TODO resolve inferred error sets
950 const entry = if (val.cast(Value.Payload.ErrorSet)) |payload|
951 (payload.fields.getEntry(field_name) orelse
952 return mod.fail(scope, fieldptr.base.src, "no error named '{}' in '{}'", .{ field_name, child_type })).*
953 else try mod.getErrorValue(field_name);
954
955 const error_payload = try scope.arena().create(Value.Payload.Error);
956 error_payload.* = .{
957 .name = entry.key,
958 .value = entry.value,
959 };
960
961 const ref_payload = try scope.arena().create(Value.Payload.RefVal);
962 ref_payload.* = .{ .val = Value.initPayload(&error_payload.base) };
963
964 const result_type = if (child_type.tag() == .anyerror) blk: {
965 const result_payload = try scope.arena().create(Type.Payload.ErrorSetSingle);
966 result_payload.* = .{ .name = entry.key };
967 break :blk Type.initPayload(&result_payload.base);
968 } else child_type;
969
970 return mod.constInst(scope, fieldptr.base.src, .{
971 .ty = try mod.simplePtrType(scope, fieldptr.base.src, result_type, false, .One),
972 .val = Value.initPayload(&ref_payload.base),
973 });
974 },
975 else => return mod.fail(scope, fieldptr.base.src, "type '{}' does not support field access", .{child_type}),
976 }
977 },
978 else => {},
862979 }
980 return mod.fail(scope, fieldptr.base.src, "type '{}' does not support field access", .{elem_ty});
863981}
864982
865983fn analyzeInstIntCast(mod: *Module, scope: *Scope, inst: *zir.Inst.BinOp) InnerError!*Inst {
......@@ -983,6 +1101,10 @@ fn analyzeInstBitwise(mod: *Module, scope: *Scope, inst: *zir.Inst.BinOp) InnerE
9831101 return mod.fail(scope, inst.base.src, "TODO implement analyzeInstBitwise", .{});
9841102}
9851103
1104fn analyzeInstBitNot(mod: *Module, scope: *Scope, inst: *zir.Inst.UnOp) InnerError!*Inst {
1105 return mod.fail(scope, inst.base.src, "TODO implement analyzeInstBitNot", .{});
1106}
1107
9861108fn analyzeInstArrayCat(mod: *Module, scope: *Scope, inst: *zir.Inst.BinOp) InnerError!*Inst {
9871109 return mod.fail(scope, inst.base.src, "TODO implement analyzeInstArrayCat", .{});
9881110}
......@@ -1348,7 +1470,7 @@ fn analyzeInstPtrType(mod: *Module, scope: *Scope, inst: *zir.Inst.PtrType) Inne
13481470
13491471 if (host_size != 0 and bit_offset >= host_size * 8)
13501472 return mod.fail(scope, inst.base.src, "bit offset starts after end of host integer", .{});
1351
1473
13521474 const sentinel = if (inst.kw_args.sentinel) |some|
13531475 (try resolveInstConst(mod, scope, some)).val
13541476 else