authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-11-17 23:06:28-05:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-11-21 20:43:41-05:00
log21f344b3b903b41fd4793faa82a4ac26ad2544aa
tree713437712564e80b512629fa657da5f7cb56730b
parent1aa978f32e88b4c83fde95f62938c97c7c22164c
signaturelock-open Commit is signed but in an unrecognized format.

add null terminated pointers and arrays to self-hosted

as well as `@typeInfo` and `@Type`

14 files changed, 240 insertions(+), 123 deletions(-)

lib/std/builtin.zig+1
...@@ -161,6 +161,7 @@ pub const TypeInfo = union(enum) {...@@ -161,6 +161,7 @@ pub const TypeInfo = union(enum) {
161 pub const Array = struct {161 pub const Array = struct {
162 len: comptime_int,162 len: comptime_int,
163 child: type,163 child: type,
164 is_null_terminated: bool,
164 };165 };
165166
166 /// This data structure is used by the Zig language code generation and167 /// This data structure is used by the Zig language code generation and
lib/std/zig/ast.zig+13-3
...@@ -137,6 +137,7 @@ pub const Error = union(enum) {...@@ -137,6 +137,7 @@ pub const Error = union(enum) {
137 ExpectedCallOrFnProto: ExpectedCallOrFnProto,137 ExpectedCallOrFnProto: ExpectedCallOrFnProto,
138 ExpectedSliceOrRBracket: ExpectedSliceOrRBracket,138 ExpectedSliceOrRBracket: ExpectedSliceOrRBracket,
139 ExtraAlignQualifier: ExtraAlignQualifier,139 ExtraAlignQualifier: ExtraAlignQualifier,
140 ExtraNullQualifier: ExtraNullQualifier,
140 ExtraConstQualifier: ExtraConstQualifier,141 ExtraConstQualifier: ExtraConstQualifier,
141 ExtraVolatileQualifier: ExtraVolatileQualifier,142 ExtraVolatileQualifier: ExtraVolatileQualifier,
142 ExtraAllowZeroQualifier: ExtraAllowZeroQualifier,143 ExtraAllowZeroQualifier: ExtraAllowZeroQualifier,
...@@ -184,6 +185,7 @@ pub const Error = union(enum) {...@@ -184,6 +185,7 @@ pub const Error = union(enum) {
184 .ExpectedCallOrFnProto => |*x| return x.render(tokens, stream),185 .ExpectedCallOrFnProto => |*x| return x.render(tokens, stream),
185 .ExpectedSliceOrRBracket => |*x| return x.render(tokens, stream),186 .ExpectedSliceOrRBracket => |*x| return x.render(tokens, stream),
186 .ExtraAlignQualifier => |*x| return x.render(tokens, stream),187 .ExtraAlignQualifier => |*x| return x.render(tokens, stream),
188 .ExtraNullQualifier => |*x| return x.render(tokens, stream),
187 .ExtraConstQualifier => |*x| return x.render(tokens, stream),189 .ExtraConstQualifier => |*x| return x.render(tokens, stream),
188 .ExtraVolatileQualifier => |*x| return x.render(tokens, stream),190 .ExtraVolatileQualifier => |*x| return x.render(tokens, stream),
189 .ExtraAllowZeroQualifier => |*x| return x.render(tokens, stream),191 .ExtraAllowZeroQualifier => |*x| return x.render(tokens, stream),
...@@ -233,6 +235,7 @@ pub const Error = union(enum) {...@@ -233,6 +235,7 @@ pub const Error = union(enum) {
233 .ExpectedCallOrFnProto => |x| return x.node.firstToken(),235 .ExpectedCallOrFnProto => |x| return x.node.firstToken(),
234 .ExpectedSliceOrRBracket => |x| return x.token,236 .ExpectedSliceOrRBracket => |x| return x.token,
235 .ExtraAlignQualifier => |x| return x.token,237 .ExtraAlignQualifier => |x| return x.token,
238 .ExtraNullQualifier => |x| return x.token,
236 .ExtraConstQualifier => |x| return x.token,239 .ExtraConstQualifier => |x| return x.token,
237 .ExtraVolatileQualifier => |x| return x.token,240 .ExtraVolatileQualifier => |x| return x.token,
238 .ExtraAllowZeroQualifier => |x| return x.token,241 .ExtraAllowZeroQualifier => |x| return x.token,
...@@ -293,6 +296,7 @@ pub const Error = union(enum) {...@@ -293,6 +296,7 @@ pub const Error = union(enum) {
293 pub const ExpectedPubItem = SimpleError("Expected function or variable declaration after pub");296 pub const ExpectedPubItem = SimpleError("Expected function or variable declaration after pub");
294 pub const UnattachedDocComment = SimpleError("Unattached documentation comment");297 pub const UnattachedDocComment = SimpleError("Unattached documentation comment");
295 pub const ExtraAlignQualifier = SimpleError("Extra align qualifier");298 pub const ExtraAlignQualifier = SimpleError("Extra align qualifier");
299 pub const ExtraNullQualifier = SimpleError("Extra null qualifier");
296 pub const ExtraConstQualifier = SimpleError("Extra const qualifier");300 pub const ExtraConstQualifier = SimpleError("Extra const qualifier");
297 pub const ExtraVolatileQualifier = SimpleError("Extra volatile qualifier");301 pub const ExtraVolatileQualifier = SimpleError("Extra volatile qualifier");
298 pub const ExtraAllowZeroQualifier = SimpleError("Extra allowzero qualifier");302 pub const ExtraAllowZeroQualifier = SimpleError("Extra allowzero qualifier");
...@@ -1538,7 +1542,7 @@ pub const Node = struct {...@@ -1538,7 +1542,7 @@ pub const Node = struct {
15381542
1539 pub const Op = union(enum) {1543 pub const Op = union(enum) {
1540 AddressOf,1544 AddressOf,
1541 ArrayType: *Node,1545 ArrayType: ArrayInfo,
1542 Await,1546 Await,
1543 BitNot,1547 BitNot,
1544 BoolNot,1548 BoolNot,
...@@ -1552,11 +1556,17 @@ pub const Node = struct {...@@ -1552,11 +1556,17 @@ pub const Node = struct {
1552 Try,1556 Try,
1553 };1557 };
15541558
1559 pub const ArrayInfo = struct {
1560 len_expr: *Node,
1561 null_token: ?TokenIndex,
1562 };
1563
1555 pub const PtrInfo = struct {1564 pub const PtrInfo = struct {
1556 allowzero_token: ?TokenIndex,1565 allowzero_token: ?TokenIndex,
1557 align_info: ?Align,1566 align_info: ?Align,
1558 const_token: ?TokenIndex,1567 const_token: ?TokenIndex,
1559 volatile_token: ?TokenIndex,1568 volatile_token: ?TokenIndex,
1569 null_token: ?TokenIndex,
15601570
1561 pub const Align = struct {1571 pub const Align = struct {
1562 node: *Node,1572 node: *Node,
...@@ -1588,8 +1598,8 @@ pub const Node = struct {...@@ -1588,8 +1598,8 @@ pub const Node = struct {
1588 }1598 }
1589 },1599 },
15901600
1591 Op.ArrayType => |size_expr| {1601 Op.ArrayType => |array_info| {
1592 if (i < 1) return size_expr;1602 if (i < 1) return array_info.len_expr;
1593 i -= 1;1603 i -= 1;
1594 },1604 },
15951605
lib/std/zig/parse.zig+31-8
...@@ -1085,7 +1085,7 @@ fn parseInitList(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node.Suf...@@ -1085,7 +1085,7 @@ fn parseInitList(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node.Suf
1085 const node = try arena.create(Node.SuffixOp);1085 const node = try arena.create(Node.SuffixOp);
1086 node.* = Node.SuffixOp{1086 node.* = Node.SuffixOp{
1087 .base = Node{ .id = .SuffixOp },1087 .base = Node{ .id = .SuffixOp },
1088 .lhs = .{.node = undefined}, // set by caller1088 .lhs = .{ .node = undefined }, // set by caller
1089 .op = op,1089 .op = op,
1090 .rtoken = try expectToken(it, tree, .RBrace),1090 .rtoken = try expectToken(it, tree, .RBrace),
1091 };1091 };
...@@ -1138,7 +1138,7 @@ fn parseSuffixExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {...@@ -1138,7 +1138,7 @@ fn parseSuffixExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
11381138
1139 while (try parseSuffixOp(arena, it, tree)) |node| {1139 while (try parseSuffixOp(arena, it, tree)) |node| {
1140 switch (node.id) {1140 switch (node.id) {
1141 .SuffixOp => node.cast(Node.SuffixOp).?.lhs = .{.node = res},1141 .SuffixOp => node.cast(Node.SuffixOp).?.lhs = .{ .node = res },
1142 .InfixOp => node.cast(Node.InfixOp).?.lhs = res,1142 .InfixOp => node.cast(Node.InfixOp).?.lhs = res,
1143 else => unreachable,1143 else => unreachable,
1144 }1144 }
...@@ -1154,7 +1154,7 @@ fn parseSuffixExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {...@@ -1154,7 +1154,7 @@ fn parseSuffixExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
1154 const node = try arena.create(Node.SuffixOp);1154 const node = try arena.create(Node.SuffixOp);
1155 node.* = Node.SuffixOp{1155 node.* = Node.SuffixOp{
1156 .base = Node{ .id = .SuffixOp },1156 .base = Node{ .id = .SuffixOp },
1157 .lhs = .{.node = res},1157 .lhs = .{ .node = res },
1158 .op = Node.SuffixOp.Op{1158 .op = Node.SuffixOp.Op{
1159 .Call = Node.SuffixOp.Op.Call{1159 .Call = Node.SuffixOp.Op.Call{
1160 .params = params.list,1160 .params = params.list,
...@@ -1171,7 +1171,7 @@ fn parseSuffixExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {...@@ -1171,7 +1171,7 @@ fn parseSuffixExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
1171 while (true) {1171 while (true) {
1172 if (try parseSuffixOp(arena, it, tree)) |node| {1172 if (try parseSuffixOp(arena, it, tree)) |node| {
1173 switch (node.id) {1173 switch (node.id) {
1174 .SuffixOp => node.cast(Node.SuffixOp).?.lhs = .{.node = res},1174 .SuffixOp => node.cast(Node.SuffixOp).?.lhs = .{ .node = res },
1175 .InfixOp => node.cast(Node.InfixOp).?.lhs = res,1175 .InfixOp => node.cast(Node.InfixOp).?.lhs = res,
1176 else => unreachable,1176 else => unreachable,
1177 }1177 }
...@@ -1182,7 +1182,7 @@ fn parseSuffixExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {...@@ -1182,7 +1182,7 @@ fn parseSuffixExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
1182 const call = try arena.create(Node.SuffixOp);1182 const call = try arena.create(Node.SuffixOp);
1183 call.* = Node.SuffixOp{1183 call.* = Node.SuffixOp{
1184 .base = Node{ .id = .SuffixOp },1184 .base = Node{ .id = .SuffixOp },
1185 .lhs = .{.node = res},1185 .lhs = .{ .node = res },
1186 .op = Node.SuffixOp.Op{1186 .op = Node.SuffixOp.Op{
1187 .Call = Node.SuffixOp.Op.Call{1187 .Call = Node.SuffixOp.Op.Call{
1188 .params = params.list,1188 .params = params.list,
...@@ -1531,7 +1531,7 @@ fn parseAnonLiteral(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node...@@ -1531,7 +1531,7 @@ fn parseAnonLiteral(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node
15311531
1532 // anon container literal1532 // anon container literal
1533 if (try parseInitList(arena, it, tree)) |node| {1533 if (try parseInitList(arena, it, tree)) |node| {
1534 node.lhs = .{.dot = dot};1534 node.lhs = .{ .dot = dot };
1535 return &node.base;1535 return &node.base;
1536 }1536 }
15371537
...@@ -2252,6 +2252,16 @@ fn parsePrefixTypeOp(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node...@@ -2252,6 +2252,16 @@ fn parsePrefixTypeOp(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node
2252 .SliceType => |*slice_type| {2252 .SliceType => |*slice_type| {
2253 // Collect pointer qualifiers in any order, but disallow duplicates2253 // Collect pointer qualifiers in any order, but disallow duplicates
2254 while (true) {2254 while (true) {
2255 if (eatToken(it, .Keyword_null)) |null_token| {
2256 if (slice_type.null_token != null) {
2257 try tree.errors.push(AstError{
2258 .ExtraNullQualifier = AstError.ExtraNullQualifier{ .token = it.index },
2259 });
2260 return error.ParseError;
2261 }
2262 slice_type.null_token = null_token;
2263 continue;
2264 }
2255 if (try parseByteAlign(arena, it, tree)) |align_expr| {2265 if (try parseByteAlign(arena, it, tree)) |align_expr| {
2256 if (slice_type.align_info != null) {2266 if (slice_type.align_info != null) {
2257 try tree.errors.push(AstError{2267 try tree.errors.push(AstError{
...@@ -2313,6 +2323,10 @@ fn parsePrefixTypeOp(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node...@@ -2313,6 +2323,10 @@ fn parsePrefixTypeOp(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node
2313 &prefix_op.op.PtrType;2323 &prefix_op.op.PtrType;
23142324
2315 while (true) {2325 while (true) {
2326 if (eatToken(it, .Keyword_null)) |null_token| {
2327 ptr_info.null_token = null_token;
2328 continue;
2329 }
2316 if (eatToken(it, .Keyword_align)) |align_token| {2330 if (eatToken(it, .Keyword_align)) |align_token| {
2317 const lparen = try expectToken(it, tree, .LParen);2331 const lparen = try expectToken(it, tree, .LParen);
2318 const expr_node = try expectNode(arena, it, tree, parseExpr, AstError{2332 const expr_node = try expectNode(arena, it, tree, parseExpr, AstError{
...@@ -2460,9 +2474,15 @@ fn parseArrayTypeStart(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*No...@@ -2460,9 +2474,15 @@ fn parseArrayTypeStart(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*No
2460 const lbracket = eatToken(it, .LBracket) orelse return null;2474 const lbracket = eatToken(it, .LBracket) orelse return null;
2461 const expr = try parseExpr(arena, it, tree);2475 const expr = try parseExpr(arena, it, tree);
2462 const rbracket = try expectToken(it, tree, .RBracket);2476 const rbracket = try expectToken(it, tree, .RBracket);
2477 const null_token = eatToken(it, .Keyword_null);
24632478
2464 const op = if (expr) |element_type|2479 const op = if (expr) |len_expr|
2465 Node.PrefixOp.Op{ .ArrayType = element_type }2480 Node.PrefixOp.Op{
2481 .ArrayType = .{
2482 .len_expr = len_expr,
2483 .null_token = null_token,
2484 },
2485 }
2466 else2486 else
2467 Node.PrefixOp.Op{2487 Node.PrefixOp.Op{
2468 .SliceType = Node.PrefixOp.PtrInfo{2488 .SliceType = Node.PrefixOp.PtrInfo{
...@@ -2470,6 +2490,7 @@ fn parseArrayTypeStart(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*No...@@ -2470,6 +2490,7 @@ fn parseArrayTypeStart(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*No
2470 .align_info = null,2490 .align_info = null,
2471 .const_token = null,2491 .const_token = null,
2472 .volatile_token = null,2492 .volatile_token = null,
2493 .null_token = null,
2473 },2494 },
2474 };2495 };
24752496
...@@ -2505,6 +2526,7 @@ fn parsePtrTypeStart(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node...@@ -2505,6 +2526,7 @@ fn parsePtrTypeStart(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node
2505 .align_info = null,2526 .align_info = null,
2506 .const_token = null,2527 .const_token = null,
2507 .volatile_token = null,2528 .volatile_token = null,
2529 .null_token = null,
2508 },2530 },
2509 },2531 },
2510 .rhs = undefined, // set by caller2532 .rhs = undefined, // set by caller
...@@ -2522,6 +2544,7 @@ fn parsePtrTypeStart(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node...@@ -2522,6 +2544,7 @@ fn parsePtrTypeStart(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node
2522 .align_info = null,2544 .align_info = null,
2523 .const_token = null,2545 .const_token = null,
2524 .volatile_token = null,2546 .volatile_token = null,
2547 .null_token = null,
2525 },2548 },
2526 },2549 },
2527 .rhs = undefined, // set by caller2550 .rhs = undefined, // set by caller
lib/std/zig/parser_test.zig+3
...@@ -1552,6 +1552,7 @@ test "zig fmt: pointer attributes" {...@@ -1552,6 +1552,7 @@ test "zig fmt: pointer attributes" {
1552 \\extern fn f2(s: **align(1) *const *volatile u8) c_int;1552 \\extern fn f2(s: **align(1) *const *volatile u8) c_int;
1553 \\extern fn f3(s: *align(1) const *align(1) volatile *const volatile u8) c_int;1553 \\extern fn f3(s: *align(1) const *align(1) volatile *const volatile u8) c_int;
1554 \\extern fn f4(s: *align(1) const volatile u8) c_int;1554 \\extern fn f4(s: *align(1) const volatile u8) c_int;
1555 \\extern fn f5(s: [*]null align(1) const volatile u8) c_int;
1555 \\1556 \\
1556 );1557 );
1557}1558}
...@@ -1562,6 +1563,7 @@ test "zig fmt: slice attributes" {...@@ -1562,6 +1563,7 @@ test "zig fmt: slice attributes" {
1562 \\extern fn f2(s: **align(1) *const *volatile u8) c_int;1563 \\extern fn f2(s: **align(1) *const *volatile u8) c_int;
1563 \\extern fn f3(s: *align(1) const *align(1) volatile *const volatile u8) c_int;1564 \\extern fn f3(s: *align(1) const *align(1) volatile *const volatile u8) c_int;
1564 \\extern fn f4(s: *align(1) const volatile u8) c_int;1565 \\extern fn f4(s: *align(1) const volatile u8) c_int;
1566 \\extern fn f5(s: [*]null align(1) const volatile u8) c_int;
1565 \\1567 \\
1566 );1568 );
1567}1569}
...@@ -1889,6 +1891,7 @@ test "zig fmt: arrays" {...@@ -1889,6 +1891,7 @@ test "zig fmt: arrays" {
1889 \\ 2,1891 \\ 2,
1890 \\ };1892 \\ };
1891 \\ const a: [0]u8 = []u8{};1893 \\ const a: [0]u8 = []u8{};
1894 \\ const x: [4]null u8 = undefined;
1892 \\}1895 \\}
1893 \\1896 \\
1894 );1897 );
lib/std/zig/render.zig+9-3
...@@ -423,6 +423,9 @@ fn renderExpression(...@@ -423,6 +423,9 @@ fn renderExpression(
423 else => @as(usize, 0),423 else => @as(usize, 0),
424 };424 };
425 try renderTokenOffset(tree, stream, prefix_op_node.op_token, indent, start_col, Space.None, star_offset); // *425 try renderTokenOffset(tree, stream, prefix_op_node.op_token, indent, start_col, Space.None, star_offset); // *
426 if (ptr_info.null_token) |null_token| {
427 try renderToken(tree, stream, null_token, indent, start_col, Space.Space); // null
428 }
426 if (ptr_info.allowzero_token) |allowzero_token| {429 if (ptr_info.allowzero_token) |allowzero_token| {
427 try renderToken(tree, stream, allowzero_token, indent, start_col, Space.Space); // allowzero430 try renderToken(tree, stream, allowzero_token, indent, start_col, Space.Space); // allowzero
428 }431 }
...@@ -499,9 +502,9 @@ fn renderExpression(...@@ -499,9 +502,9 @@ fn renderExpression(
499 }502 }
500 },503 },
501504
502 ast.Node.PrefixOp.Op.ArrayType => |array_index| {505 ast.Node.PrefixOp.Op.ArrayType => |array_info| {
503 const lbracket = prefix_op_node.op_token;506 const lbracket = prefix_op_node.op_token;
504 const rbracket = tree.nextToken(array_index.lastToken());507 const rbracket = tree.nextToken(array_info.len_expr.lastToken());
505508
506 try renderToken(tree, stream, lbracket, indent, start_col, Space.None); // [509 try renderToken(tree, stream, lbracket, indent, start_col, Space.None); // [
507510
...@@ -509,7 +512,7 @@ fn renderExpression(...@@ -509,7 +512,7 @@ fn renderExpression(
509 const ends_with_comment = tree.tokens.at(rbracket - 1).id == .LineComment;512 const ends_with_comment = tree.tokens.at(rbracket - 1).id == .LineComment;
510 const new_indent = if (ends_with_comment) indent + indent_delta else indent;513 const new_indent = if (ends_with_comment) indent + indent_delta else indent;
511 const new_space = if (ends_with_comment) Space.Newline else Space.None;514 const new_space = if (ends_with_comment) Space.Newline else Space.None;
512 try renderExpression(allocator, stream, tree, new_indent, start_col, array_index, new_space);515 try renderExpression(allocator, stream, tree, new_indent, start_col, array_info.len_expr, new_space);
513 if (starts_with_comment) {516 if (starts_with_comment) {
514 try stream.writeByte('\n');517 try stream.writeByte('\n');
515 }518 }
...@@ -517,6 +520,9 @@ fn renderExpression(...@@ -517,6 +520,9 @@ fn renderExpression(
517 try stream.writeByteNTimes(' ', indent);520 try stream.writeByteNTimes(' ', indent);
518 }521 }
519 try renderToken(tree, stream, rbracket, indent, start_col, Space.None); // ]522 try renderToken(tree, stream, rbracket, indent, start_col, Space.None); // ]
523 if (array_info.null_token) |null_token| {
524 try renderToken(tree, stream, null_token, indent, start_col, Space.Space); // null
525 }
520 },526 },
521 ast.Node.PrefixOp.Op.BitNot,527 ast.Node.PrefixOp.Op.BitNot,
522 ast.Node.PrefixOp.Op.BoolNot,528 ast.Node.PrefixOp.Op.BoolNot,
src-self-hosted/translate_c.zig+1
...@@ -1118,6 +1118,7 @@ fn transCreateNodePtrType(...@@ -1118,6 +1118,7 @@ fn transCreateNodePtrType(
1118 .align_info = null,1118 .align_info = null,
1119 .const_token = if (is_const) try appendToken(c, .Keyword_const, "const") else null,1119 .const_token = if (is_const) try appendToken(c, .Keyword_const, "const") else null,
1120 .volatile_token = if (is_volatile) try appendToken(c, .Keyword_volatile, "volatile") else null,1120 .volatile_token = if (is_volatile) try appendToken(c, .Keyword_volatile, "volatile") else null,
1121 .null_token = null,
1121 },1122 },
1122 },1123 },
1123 .rhs = undefined, // translate and set afterward1124 .rhs = undefined, // translate and set afterward
src/all_types.hpp+5
...@@ -358,6 +358,7 @@ struct LazyValueSliceType {...@@ -358,6 +358,7 @@ struct LazyValueSliceType {
358 bool is_const;358 bool is_const;
359 bool is_volatile;359 bool is_volatile;
360 bool is_allowzero;360 bool is_allowzero;
361 bool is_null_terminated;
361};362};
362363
363struct LazyValuePtrType {364struct LazyValuePtrType {
...@@ -1234,6 +1235,7 @@ struct ZigTypeFloat {...@@ -1234,6 +1235,7 @@ struct ZigTypeFloat {
1234struct ZigTypeArray {1235struct ZigTypeArray {
1235 ZigType *child_type;1236 ZigType *child_type;
1236 uint64_t len;1237 uint64_t len;
1238 bool is_null_terminated;
1237};1239};
12381240
1239struct TypeStructField {1241struct TypeStructField {
...@@ -1775,6 +1777,7 @@ struct TypeId {...@@ -1775,6 +1777,7 @@ struct TypeId {
1775 struct {1777 struct {
1776 ZigType *child_type;1778 ZigType *child_type;
1777 uint64_t size;1779 uint64_t size;
1780 bool is_null_terminated;
1778 } array;1781 } array;
1779 struct {1782 struct {
1780 bool is_signed;1783 bool is_signed;
...@@ -2986,6 +2989,7 @@ struct IrInstructionArrayType {...@@ -2986,6 +2989,7 @@ struct IrInstructionArrayType {
29862989
2987 IrInstruction *size;2990 IrInstruction *size;
2988 IrInstruction *child_type;2991 IrInstruction *child_type;
2992 bool is_null_terminated;
2989};2993};
29902994
2991struct IrInstructionPtrType {2995struct IrInstructionPtrType {
...@@ -3015,6 +3019,7 @@ struct IrInstructionSliceType {...@@ -3015,6 +3019,7 @@ struct IrInstructionSliceType {
3015 bool is_const;3019 bool is_const;
3016 bool is_volatile;3020 bool is_volatile;
3017 bool is_allow_zero;3021 bool is_allow_zero;
3022 bool is_null_terminated;
3018};3023};
30193024
3020struct IrInstructionGlobalAsm {3025struct IrInstructionGlobalAsm {
src/analyze.cpp+18-13
...@@ -752,11 +752,12 @@ ZigType *get_error_union_type(CodeGen *g, ZigType *err_set_type, ZigType *payloa...@@ -752,11 +752,12 @@ ZigType *get_error_union_type(CodeGen *g, ZigType *err_set_type, ZigType *payloa
752 return entry;752 return entry;
753}753}
754754
755ZigType *get_array_type(CodeGen *g, ZigType *child_type, uint64_t array_size) {755ZigType *get_array_type(CodeGen *g, ZigType *child_type, uint64_t array_size, bool is_null_terminated) {
756 TypeId type_id = {};756 TypeId type_id = {};
757 type_id.id = ZigTypeIdArray;757 type_id.id = ZigTypeIdArray;
758 type_id.data.array.child_type = child_type;758 type_id.data.array.child_type = child_type;
759 type_id.data.array.size = array_size;759 type_id.data.array.size = array_size;
760 type_id.data.array.is_null_terminated = is_null_terminated;
760 auto existing_entry = g->type_table.maybe_get(type_id);761 auto existing_entry = g->type_table.maybe_get(type_id);
761 if (existing_entry) {762 if (existing_entry) {
762 return existing_entry->value;763 return existing_entry->value;
...@@ -769,12 +770,14 @@ ZigType *get_array_type(CodeGen *g, ZigType *child_type, uint64_t array_size) {...@@ -769,12 +770,14 @@ ZigType *get_array_type(CodeGen *g, ZigType *child_type, uint64_t array_size) {
769 buf_resize(&entry->name, 0);770 buf_resize(&entry->name, 0);
770 buf_appendf(&entry->name, "[%" ZIG_PRI_u64 "]%s", array_size, buf_ptr(&child_type->name));771 buf_appendf(&entry->name, "[%" ZIG_PRI_u64 "]%s", array_size, buf_ptr(&child_type->name));
771772
772 entry->size_in_bits = child_type->size_in_bits * array_size;773 size_t full_array_size = array_size + (is_null_terminated ? 1 : 0);
774 entry->size_in_bits = child_type->size_in_bits * full_array_size;
773 entry->abi_align = child_type->abi_align;775 entry->abi_align = child_type->abi_align;
774 entry->abi_size = child_type->abi_size * array_size;776 entry->abi_size = child_type->abi_size * full_array_size;
775777
776 entry->data.array.child_type = child_type;778 entry->data.array.child_type = child_type;
777 entry->data.array.len = array_size;779 entry->data.array.len = array_size;
780 entry->data.array.is_null_terminated = is_null_terminated;
778781
779 g->type_table.put(type_id, entry);782 g->type_table.put(type_id, entry);
780 return entry;783 return entry;
...@@ -782,7 +785,7 @@ ZigType *get_array_type(CodeGen *g, ZigType *child_type, uint64_t array_size) {...@@ -782,7 +785,7 @@ ZigType *get_array_type(CodeGen *g, ZigType *child_type, uint64_t array_size) {
782785
783ZigType *get_slice_type(CodeGen *g, ZigType *ptr_type) {786ZigType *get_slice_type(CodeGen *g, ZigType *ptr_type) {
784 assert(ptr_type->id == ZigTypeIdPointer);787 assert(ptr_type->id == ZigTypeIdPointer);
785 assert(ptr_type->data.pointer.ptr_len == PtrLenUnknown);788 assert(ptr_type->data.pointer.ptr_len == PtrLenUnknown || ptr_type->data.pointer.ptr_len == PtrLenNull);
786789
787 ZigType **parent_pointer = &ptr_type->data.pointer.slice_parent;790 ZigType **parent_pointer = &ptr_type->data.pointer.slice_parent;
788 if (*parent_pointer) {791 if (*parent_pointer) {
...@@ -5615,7 +5618,7 @@ void init_const_str_lit(CodeGen *g, ConstExprValue *const_val, Buf *str) {...@@ -5615,7 +5618,7 @@ void init_const_str_lit(CodeGen *g, ConstExprValue *const_val, Buf *str) {
5615 }5618 }
56165619
5617 const_val->special = ConstValSpecialStatic;5620 const_val->special = ConstValSpecialStatic;
5618 const_val->type = get_array_type(g, g->builtin_types.entry_u8, buf_len(str));5621 const_val->type = get_array_type(g, g->builtin_types.entry_u8, buf_len(str), false);
5619 const_val->data.x_array.special = ConstArraySpecialBuf;5622 const_val->data.x_array.special = ConstArraySpecialBuf;
5620 const_val->data.x_array.data.s_buf = str;5623 const_val->data.x_array.data.s_buf = str;
56215624
...@@ -5633,7 +5636,7 @@ void init_const_c_str_lit(CodeGen *g, ConstExprValue *const_val, Buf *str) {...@@ -5633,7 +5636,7 @@ void init_const_c_str_lit(CodeGen *g, ConstExprValue *const_val, Buf *str) {
5633 size_t len_with_null = buf_len(str) + 1;5636 size_t len_with_null = buf_len(str) + 1;
5634 ConstExprValue *array_val = create_const_vals(1);5637 ConstExprValue *array_val = create_const_vals(1);
5635 array_val->special = ConstValSpecialStatic;5638 array_val->special = ConstValSpecialStatic;
5636 array_val->type = get_array_type(g, g->builtin_types.entry_u8, len_with_null);5639 array_val->type = get_array_type(g, g->builtin_types.entry_u8, len_with_null, false);
5637 // TODO buf optimization5640 // TODO buf optimization
5638 array_val->data.x_array.data.s_none.elements = create_const_vals(len_with_null);5641 array_val->data.x_array.data.s_none.elements = create_const_vals(len_with_null);
5639 for (size_t i = 0; i < buf_len(str); i += 1) {5642 for (size_t i = 0; i < buf_len(str); i += 1) {
...@@ -6071,7 +6074,7 @@ static Error resolve_async_frame(CodeGen *g, ZigType *frame_type) {...@@ -6071,7 +6074,7 @@ static Error resolve_async_frame(CodeGen *g, ZigType *frame_type) {
60716074
6072 fields.append({"@stack_trace", get_stack_trace_type(g), 0});6075 fields.append({"@stack_trace", get_stack_trace_type(g), 0});
6073 fields.append({"@instruction_addresses",6076 fields.append({"@instruction_addresses",
6074 get_array_type(g, g->builtin_types.entry_usize, stack_trace_ptr_count), 0});6077 get_array_type(g, g->builtin_types.entry_usize, stack_trace_ptr_count, false), 0});
6075 }6078 }
60766079
6077 frame_type->data.frame.locals_struct = get_struct_type(g, buf_ptr(&frame_type->name),6080 frame_type->data.frame.locals_struct = get_struct_type(g, buf_ptr(&frame_type->name),
...@@ -6279,7 +6282,7 @@ static Error resolve_async_frame(CodeGen *g, ZigType *frame_type) {...@@ -6279,7 +6282,7 @@ static Error resolve_async_frame(CodeGen *g, ZigType *frame_type) {
6279 if (codegen_fn_has_err_ret_tracing_stack(g, fn, true)) {6282 if (codegen_fn_has_err_ret_tracing_stack(g, fn, true)) {
6280 fields.append({"@stack_trace", get_stack_trace_type(g), 0});6283 fields.append({"@stack_trace", get_stack_trace_type(g), 0});
6281 fields.append({"@instruction_addresses",6284 fields.append({"@instruction_addresses",
6282 get_array_type(g, g->builtin_types.entry_usize, stack_trace_ptr_count), 0});6285 get_array_type(g, g->builtin_types.entry_usize, stack_trace_ptr_count, false), 0});
6283 }6286 }
62846287
6285 for (size_t alloca_i = 0; alloca_i < fn->alloca_gen_list.length; alloca_i += 1) {6288 for (size_t alloca_i = 0; alloca_i < fn->alloca_gen_list.length; alloca_i += 1) {
...@@ -7043,8 +7046,9 @@ uint32_t type_id_hash(TypeId x) {...@@ -7043,8 +7046,9 @@ uint32_t type_id_hash(TypeId x) {
7043 (((uint32_t)x.data.pointer.vector_index) ^ (uint32_t)0x19199716) +7046 (((uint32_t)x.data.pointer.vector_index) ^ (uint32_t)0x19199716) +
7044 (((uint32_t)x.data.pointer.host_int_bytes) ^ (uint32_t)529908881);7047 (((uint32_t)x.data.pointer.host_int_bytes) ^ (uint32_t)529908881);
7045 case ZigTypeIdArray:7048 case ZigTypeIdArray:
7046 return hash_ptr(x.data.array.child_type) +7049 return hash_ptr(x.data.array.child_type) *
7047 ((uint32_t)x.data.array.size ^ (uint32_t)2122979968);7050 ((uint32_t)x.data.array.size ^ (uint32_t)2122979968) *
7051 ((uint32_t)x.data.array.is_null_terminated ^ (uint32_t)2048352596);
7048 case ZigTypeIdInt:7052 case ZigTypeIdInt:
7049 return (x.data.integer.is_signed ? (uint32_t)2652528194 : (uint32_t)163929201) +7053 return (x.data.integer.is_signed ? (uint32_t)2652528194 : (uint32_t)163929201) +
7050 (((uint32_t)x.data.integer.bit_count) ^ (uint32_t)2998081557);7054 (((uint32_t)x.data.integer.bit_count) ^ (uint32_t)2998081557);
...@@ -7106,7 +7110,8 @@ bool type_id_eql(TypeId a, TypeId b) {...@@ -7106,7 +7110,8 @@ bool type_id_eql(TypeId a, TypeId b) {
7106 );7110 );
7107 case ZigTypeIdArray:7111 case ZigTypeIdArray:
7108 return a.data.array.child_type == b.data.array.child_type &&7112 return a.data.array.child_type == b.data.array.child_type &&
7109 a.data.array.size == b.data.array.size;7113 a.data.array.size == b.data.array.size &&
7114 a.data.array.is_null_terminated == b.data.array.is_null_terminated;
7110 case ZigTypeIdInt:7115 case ZigTypeIdInt:
7111 return a.data.integer.is_signed == b.data.integer.is_signed &&7116 return a.data.integer.is_signed == b.data.integer.is_signed &&
7112 a.data.integer.bit_count == b.data.integer.bit_count;7117 a.data.integer.bit_count == b.data.integer.bit_count;
...@@ -8292,7 +8297,7 @@ static void resolve_llvm_types_union(CodeGen *g, ZigType *union_type, ResolveSta...@@ -8292,7 +8297,7 @@ static void resolve_llvm_types_union(CodeGen *g, ZigType *union_type, ResolveSta
8292 size_t padding_bytes = union_type->data.unionation.union_abi_size - most_aligned_union_member->type_entry->abi_size;8297 size_t padding_bytes = union_type->data.unionation.union_abi_size - most_aligned_union_member->type_entry->abi_size;
8293 if (padding_bytes > 0) {8298 if (padding_bytes > 0) {
8294 ZigType *u8_type = get_int_type(g, false, 8);8299 ZigType *u8_type = get_int_type(g, false, 8);
8295 ZigType *padding_array = get_array_type(g, u8_type, padding_bytes);8300 ZigType *padding_array = get_array_type(g, u8_type, padding_bytes, false);
8296 LLVMTypeRef union_element_types[] = {8301 LLVMTypeRef union_element_types[] = {
8297 most_aligned_union_member->type_entry->llvm_type,8302 most_aligned_union_member->type_entry->llvm_type,
8298 get_llvm_type(g, padding_array),8303 get_llvm_type(g, padding_array),
...@@ -8326,7 +8331,7 @@ static void resolve_llvm_types_union(CodeGen *g, ZigType *union_type, ResolveSta...@@ -8326,7 +8331,7 @@ static void resolve_llvm_types_union(CodeGen *g, ZigType *union_type, ResolveSta
8326 union_type_ref = get_llvm_type(g, most_aligned_union_member->type_entry);8331 union_type_ref = get_llvm_type(g, most_aligned_union_member->type_entry);
8327 } else {8332 } else {
8328 ZigType *u8_type = get_int_type(g, false, 8);8333 ZigType *u8_type = get_int_type(g, false, 8);
8329 ZigType *padding_array = get_array_type(g, u8_type, padding_bytes);8334 ZigType *padding_array = get_array_type(g, u8_type, padding_bytes, false);
8330 LLVMTypeRef union_element_types[] = {8335 LLVMTypeRef union_element_types[] = {
8331 get_llvm_type(g, most_aligned_union_member->type_entry),8336 get_llvm_type(g, most_aligned_union_member->type_entry),
8332 get_llvm_type(g, padding_array),8337 get_llvm_type(g, padding_array),
src/analyze.hpp+1-1
...@@ -33,7 +33,7 @@ ZigType **get_c_int_type_ptr(CodeGen *g, CIntType c_int_type);...@@ -33,7 +33,7 @@ ZigType **get_c_int_type_ptr(CodeGen *g, CIntType c_int_type);
33ZigType *get_c_int_type(CodeGen *g, CIntType c_int_type);33ZigType *get_c_int_type(CodeGen *g, CIntType c_int_type);
34ZigType *get_fn_type(CodeGen *g, FnTypeId *fn_type_id);34ZigType *get_fn_type(CodeGen *g, FnTypeId *fn_type_id);
35ZigType *get_optional_type(CodeGen *g, ZigType *child_type);35ZigType *get_optional_type(CodeGen *g, ZigType *child_type);
36ZigType *get_array_type(CodeGen *g, ZigType *child_type, uint64_t array_size);36ZigType *get_array_type(CodeGen *g, ZigType *child_type, uint64_t array_size, bool is_null_terminated);
37ZigType *get_slice_type(CodeGen *g, ZigType *ptr_type);37ZigType *get_slice_type(CodeGen *g, ZigType *ptr_type);
38ZigType *get_partial_container_type(CodeGen *g, Scope *scope, ContainerKind kind,38ZigType *get_partial_container_type(CodeGen *g, Scope *scope, ContainerKind kind,
39 AstNode *decl_node, const char *full_name, Buf *bare_name, ContainerLayout layout);39 AstNode *decl_node, const char *full_name, Buf *bare_name, ContainerLayout layout);
src/codegen.cpp+2-2
...@@ -7465,7 +7465,7 @@ static void do_code_gen(CodeGen *g) {...@@ -7465,7 +7465,7 @@ static void do_code_gen(CodeGen *g) {
7465 !is_async && !have_err_ret_trace_arg;7465 !is_async && !have_err_ret_trace_arg;
7466 LLVMValueRef err_ret_array_val = nullptr;7466 LLVMValueRef err_ret_array_val = nullptr;
7467 if (have_err_ret_trace_stack) {7467 if (have_err_ret_trace_stack) {
7468 ZigType *array_type = get_array_type(g, g->builtin_types.entry_usize, stack_trace_ptr_count);7468 ZigType *array_type = get_array_type(g, g->builtin_types.entry_usize, stack_trace_ptr_count, false);
7469 err_ret_array_val = build_alloca(g, array_type, "error_return_trace_addresses", get_abi_alignment(g, array_type));7469 err_ret_array_val = build_alloca(g, array_type, "error_return_trace_addresses", get_abi_alignment(g, array_type));
74707470
7471 (void)get_llvm_type(g, get_stack_trace_type(g));7471 (void)get_llvm_type(g, get_stack_trace_type(g));
...@@ -9067,7 +9067,7 @@ static void create_test_compile_var_and_add_test_runner(CodeGen *g) {...@@ -9067,7 +9067,7 @@ static void create_test_compile_var_and_add_test_runner(CodeGen *g) {
9067 zig_unreachable();9067 zig_unreachable();
90689068
9069 ConstExprValue *test_fn_array = create_const_vals(1);9069 ConstExprValue *test_fn_array = create_const_vals(1);
9070 test_fn_array->type = get_array_type(g, struct_type, g->test_fns.length);9070 test_fn_array->type = get_array_type(g, struct_type, g->test_fns.length, false);
9071 test_fn_array->special = ConstValSpecialStatic;9071 test_fn_array->special = ConstValSpecialStatic;
9072 test_fn_array->data.x_array.data.s_none.elements = create_const_vals(g->test_fns.length);9072 test_fn_array->data.x_array.data.s_none.elements = create_const_vals(g->test_fns.length);
90739073
src/ir.cpp+43-24
...@@ -1772,11 +1772,12 @@ static IrInstruction *ir_build_set_float_mode(IrBuilder *irb, Scope *scope, AstN...@@ -1772,11 +1772,12 @@ static IrInstruction *ir_build_set_float_mode(IrBuilder *irb, Scope *scope, AstN
1772}1772}
17731773
1774static IrInstruction *ir_build_array_type(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *size,1774static IrInstruction *ir_build_array_type(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *size,
1775 IrInstruction *child_type)1775 IrInstruction *child_type, bool is_null_terminated)
1776{1776{
1777 IrInstructionArrayType *instruction = ir_build_instruction<IrInstructionArrayType>(irb, scope, source_node);1777 IrInstructionArrayType *instruction = ir_build_instruction<IrInstructionArrayType>(irb, scope, source_node);
1778 instruction->size = size;1778 instruction->size = size;
1779 instruction->child_type = child_type;1779 instruction->child_type = child_type;
1780 instruction->is_null_terminated = is_null_terminated;
17801781
1781 ir_ref_instruction(size, irb->current_basic_block);1782 ir_ref_instruction(size, irb->current_basic_block);
1782 ir_ref_instruction(child_type, irb->current_basic_block);1783 ir_ref_instruction(child_type, irb->current_basic_block);
...@@ -1795,7 +1796,8 @@ static IrInstruction *ir_build_anyframe_type(IrBuilder *irb, Scope *scope, AstNo...@@ -1795,7 +1796,8 @@ static IrInstruction *ir_build_anyframe_type(IrBuilder *irb, Scope *scope, AstNo
1795 return &instruction->base;1796 return &instruction->base;
1796}1797}
1797static IrInstruction *ir_build_slice_type(IrBuilder *irb, Scope *scope, AstNode *source_node,1798static IrInstruction *ir_build_slice_type(IrBuilder *irb, Scope *scope, AstNode *source_node,
1798 IrInstruction *child_type, bool is_const, bool is_volatile, IrInstruction *align_value, bool is_allow_zero)1799 IrInstruction *child_type, bool is_const, bool is_volatile, IrInstruction *align_value, bool is_allow_zero,
1800 bool is_null_terminated)
1799{1801{
1800 IrInstructionSliceType *instruction = ir_build_instruction<IrInstructionSliceType>(irb, scope, source_node);1802 IrInstructionSliceType *instruction = ir_build_instruction<IrInstructionSliceType>(irb, scope, source_node);
1801 instruction->is_const = is_const;1803 instruction->is_const = is_const;
...@@ -1803,6 +1805,7 @@ static IrInstruction *ir_build_slice_type(IrBuilder *irb, Scope *scope, AstNode...@@ -1803,6 +1805,7 @@ static IrInstruction *ir_build_slice_type(IrBuilder *irb, Scope *scope, AstNode
1803 instruction->child_type = child_type;1805 instruction->child_type = child_type;
1804 instruction->align_value = align_value;1806 instruction->align_value = align_value;
1805 instruction->is_allow_zero = is_allow_zero;1807 instruction->is_allow_zero = is_allow_zero;
1808 instruction->is_null_terminated = is_null_terminated;
18061809
1807 ir_ref_instruction(child_type, irb->current_basic_block);1810 ir_ref_instruction(child_type, irb->current_basic_block);
1808 if (align_value) ir_ref_instruction(align_value, irb->current_basic_block);1811 if (align_value) ir_ref_instruction(align_value, irb->current_basic_block);
...@@ -6216,7 +6219,7 @@ static IrInstruction *ir_gen_container_init_expr(IrBuilder *irb, Scope *scope, A...@@ -6216,7 +6219,7 @@ static IrInstruction *ir_gen_container_init_expr(IrBuilder *irb, Scope *scope, A
6216 return elem_type;6219 return elem_type;
6217 size_t item_count = container_init_expr->entries.length;6220 size_t item_count = container_init_expr->entries.length;
6218 IrInstruction *item_count_inst = ir_build_const_usize(irb, scope, node, item_count);6221 IrInstruction *item_count_inst = ir_build_const_usize(irb, scope, node, item_count);
6219 container_type = ir_build_array_type(irb, scope, node, item_count_inst, elem_type);6222 container_type = ir_build_array_type(irb, scope, node, item_count_inst, elem_type, false);
6220 } else {6223 } else {
6221 container_type = ir_gen_node(irb, container_init_expr->type, scope);6224 container_type = ir_gen_node(irb, container_init_expr->type, scope);
6222 if (container_type == irb->codegen->invalid_instruction)6225 if (container_type == irb->codegen->invalid_instruction)
...@@ -6944,6 +6947,7 @@ static IrInstruction *ir_gen_array_type(IrBuilder *irb, Scope *scope, AstNode *n...@@ -6944,6 +6947,7 @@ static IrInstruction *ir_gen_array_type(IrBuilder *irb, Scope *scope, AstNode *n
6944 bool is_const = node->data.array_type.is_const;6947 bool is_const = node->data.array_type.is_const;
6945 bool is_volatile = node->data.array_type.is_volatile;6948 bool is_volatile = node->data.array_type.is_volatile;
6946 bool is_allow_zero = node->data.array_type.allow_zero_token != nullptr;6949 bool is_allow_zero = node->data.array_type.allow_zero_token != nullptr;
6950 bool is_null_terminated = node->data.array_type.is_null_terminated;
6947 AstNode *align_expr = node->data.array_type.align_expr;6951 AstNode *align_expr = node->data.array_type.align_expr;
69486952
6949 Scope *comptime_scope = create_comptime_scope(irb->codegen, node, scope);6953 Scope *comptime_scope = create_comptime_scope(irb->codegen, node, scope);
...@@ -6973,7 +6977,7 @@ static IrInstruction *ir_gen_array_type(IrBuilder *irb, Scope *scope, AstNode *n...@@ -6973,7 +6977,7 @@ static IrInstruction *ir_gen_array_type(IrBuilder *irb, Scope *scope, AstNode *n
6973 if (child_type == irb->codegen->invalid_instruction)6977 if (child_type == irb->codegen->invalid_instruction)
6974 return child_type;6978 return child_type;
69756979
6976 return ir_build_array_type(irb, scope, node, size_value, child_type);6980 return ir_build_array_type(irb, scope, node, size_value, child_type, is_null_terminated);
6977 } else {6981 } else {
6978 IrInstruction *align_value;6982 IrInstruction *align_value;
6979 if (align_expr != nullptr) {6983 if (align_expr != nullptr) {
...@@ -6988,7 +6992,8 @@ static IrInstruction *ir_gen_array_type(IrBuilder *irb, Scope *scope, AstNode *n...@@ -6988,7 +6992,8 @@ static IrInstruction *ir_gen_array_type(IrBuilder *irb, Scope *scope, AstNode *n
6988 if (child_type == irb->codegen->invalid_instruction)6992 if (child_type == irb->codegen->invalid_instruction)
6989 return child_type;6993 return child_type;
69906994
6991 return ir_build_slice_type(irb, scope, node, child_type, is_const, is_volatile, align_value, is_allow_zero);6995 return ir_build_slice_type(irb, scope, node, child_type, is_const, is_volatile, align_value, is_allow_zero,
6996 is_null_terminated);
6992 }6997 }
6993}6998}
69946999
...@@ -10631,6 +10636,7 @@ static ZigType *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, ZigT...@@ -10631,6 +10636,7 @@ static ZigType *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, ZigT
10631 // *[N]T to []T10636 // *[N]T to []T
10632 // *[N]T to E![]T10637 // *[N]T to E![]T
10633 if (cur_type->id == ZigTypeIdPointer &&10638 if (cur_type->id == ZigTypeIdPointer &&
10639 cur_type->data.pointer.ptr_len == PtrLenSingle &&
10634 cur_type->data.pointer.child_type->id == ZigTypeIdArray &&10640 cur_type->data.pointer.child_type->id == ZigTypeIdArray &&
10635 ((prev_type->id == ZigTypeIdErrorUnion && is_slice(prev_type->data.error_union.payload_type)) ||10641 ((prev_type->id == ZigTypeIdErrorUnion && is_slice(prev_type->data.error_union.payload_type)) ||
10636 is_slice(prev_type)))10642 is_slice(prev_type)))
...@@ -10639,7 +10645,8 @@ static ZigType *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, ZigT...@@ -10639,7 +10645,8 @@ static ZigType *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, ZigT
10639 ZigType *slice_type = (prev_type->id == ZigTypeIdErrorUnion) ?10645 ZigType *slice_type = (prev_type->id == ZigTypeIdErrorUnion) ?
10640 prev_type->data.error_union.payload_type : prev_type;10646 prev_type->data.error_union.payload_type : prev_type;
10641 ZigType *slice_ptr_type = slice_type->data.structure.fields[slice_ptr_index]->type_entry;10647 ZigType *slice_ptr_type = slice_type->data.structure.fields[slice_ptr_index]->type_entry;
10642 if ((slice_ptr_type->data.pointer.is_const || array_type->data.array.len == 0) &&10648 if ((slice_ptr_type->data.pointer.is_const || array_type->data.array.len == 0 ||
10649 !cur_type->data.pointer.is_const) &&
10643 types_match_const_cast_only(ira,10650 types_match_const_cast_only(ira,
10644 slice_ptr_type->data.pointer.child_type,10651 slice_ptr_type->data.pointer.child_type,
10645 array_type->data.array.child_type, source_node, false).id == ConstCastResultIdOk)10652 array_type->data.array.child_type, source_node, false).id == ConstCastResultIdOk)
...@@ -10653,6 +10660,7 @@ static ZigType *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, ZigT...@@ -10653,6 +10660,7 @@ static ZigType *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, ZigT
10653 // *[N]T to E![]T10660 // *[N]T to E![]T
10654 if (prev_type->id == ZigTypeIdPointer &&10661 if (prev_type->id == ZigTypeIdPointer &&
10655 prev_type->data.pointer.child_type->id == ZigTypeIdArray &&10662 prev_type->data.pointer.child_type->id == ZigTypeIdArray &&
10663 prev_type->data.pointer.ptr_len == PtrLenSingle &&
10656 ((cur_type->id == ZigTypeIdErrorUnion && is_slice(cur_type->data.error_union.payload_type)) ||10664 ((cur_type->id == ZigTypeIdErrorUnion && is_slice(cur_type->data.error_union.payload_type)) ||
10657 is_slice(cur_type)))10665 is_slice(cur_type)))
10658 {10666 {
...@@ -10660,7 +10668,8 @@ static ZigType *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, ZigT...@@ -10660,7 +10668,8 @@ static ZigType *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, ZigT
10660 ZigType *slice_type = (cur_type->id == ZigTypeIdErrorUnion) ?10668 ZigType *slice_type = (cur_type->id == ZigTypeIdErrorUnion) ?
10661 cur_type->data.error_union.payload_type : cur_type;10669 cur_type->data.error_union.payload_type : cur_type;
10662 ZigType *slice_ptr_type = slice_type->data.structure.fields[slice_ptr_index]->type_entry;10670 ZigType *slice_ptr_type = slice_type->data.structure.fields[slice_ptr_index]->type_entry;
10663 if ((slice_ptr_type->data.pointer.is_const || array_type->data.array.len == 0) &&10671 if ((slice_ptr_type->data.pointer.is_const || array_type->data.array.len == 0 ||
10672 !prev_type->data.pointer.is_const) &&
10664 types_match_const_cast_only(ira,10673 types_match_const_cast_only(ira,
10665 slice_ptr_type->data.pointer.child_type,10674 slice_ptr_type->data.pointer.child_type,
10666 array_type->data.array.child_type, source_node, false).id == ConstCastResultIdOk)10675 array_type->data.array.child_type, source_node, false).id == ConstCastResultIdOk)
...@@ -14893,7 +14902,7 @@ static IrInstruction *ir_analyze_array_cat(IrAnalyze *ira, IrInstructionBinOp *i...@@ -14893,7 +14902,7 @@ static IrInstruction *ir_analyze_array_cat(IrAnalyze *ira, IrInstructionBinOp *i
14893 ConstExprValue *out_array_val;14902 ConstExprValue *out_array_val;
14894 size_t new_len = (op1_array_end - op1_array_index) + (op2_array_end - op2_array_index);14903 size_t new_len = (op1_array_end - op1_array_index) + (op2_array_end - op2_array_index);
14895 if (op1_type->id == ZigTypeIdArray || op2_type->id == ZigTypeIdArray) {14904 if (op1_type->id == ZigTypeIdArray || op2_type->id == ZigTypeIdArray) {
14896 result->value.type = get_array_type(ira->codegen, child_type, new_len);14905 result->value.type = get_array_type(ira->codegen, child_type, new_len, false);
1489714906
14898 out_array_val = out_val;14907 out_array_val = out_val;
14899 } else if (is_slice(op1_type) || is_slice(op2_type)) {14908 } else if (is_slice(op1_type) || is_slice(op2_type)) {
...@@ -14902,7 +14911,7 @@ static IrInstruction *ir_analyze_array_cat(IrAnalyze *ira, IrInstructionBinOp *i...@@ -14902,7 +14911,7 @@ static IrInstruction *ir_analyze_array_cat(IrAnalyze *ira, IrInstructionBinOp *i
14902 result->value.type = get_slice_type(ira->codegen, ptr_type);14911 result->value.type = get_slice_type(ira->codegen, ptr_type);
14903 out_array_val = create_const_vals(1);14912 out_array_val = create_const_vals(1);
14904 out_array_val->special = ConstValSpecialStatic;14913 out_array_val->special = ConstValSpecialStatic;
14905 out_array_val->type = get_array_type(ira->codegen, child_type, new_len);14914 out_array_val->type = get_array_type(ira->codegen, child_type, new_len, false);
1490614915
14907 out_val->data.x_struct.fields = alloc_const_vals_ptrs(2);14916 out_val->data.x_struct.fields = alloc_const_vals_ptrs(2);
1490814917
...@@ -14923,7 +14932,7 @@ static IrInstruction *ir_analyze_array_cat(IrAnalyze *ira, IrInstructionBinOp *i...@@ -14923,7 +14932,7 @@ static IrInstruction *ir_analyze_array_cat(IrAnalyze *ira, IrInstructionBinOp *i
1492314932
14924 out_array_val = create_const_vals(1);14933 out_array_val = create_const_vals(1);
14925 out_array_val->special = ConstValSpecialStatic;14934 out_array_val->special = ConstValSpecialStatic;
14926 out_array_val->type = get_array_type(ira->codegen, child_type, new_len);14935 out_array_val->type = get_array_type(ira->codegen, child_type, new_len, false);
14927 out_val->data.x_ptr.special = ConstPtrSpecialBaseArray;14936 out_val->data.x_ptr.special = ConstPtrSpecialBaseArray;
14928 out_val->data.x_ptr.data.base_array.is_cstr = true;14937 out_val->data.x_ptr.data.base_array.is_cstr = true;
14929 out_val->data.x_ptr.data.base_array.array_val = out_array_val;14938 out_val->data.x_ptr.data.base_array.array_val = out_array_val;
...@@ -14994,7 +15003,7 @@ static IrInstruction *ir_analyze_array_mult(IrAnalyze *ira, IrInstructionBinOp *...@@ -14994,7 +15003,7 @@ static IrInstruction *ir_analyze_array_mult(IrAnalyze *ira, IrInstructionBinOp *
14994 ZigType *child_type = array_type->data.array.child_type;15003 ZigType *child_type = array_type->data.array.child_type;
1499515004
14996 IrInstruction *result = ir_const(ira, &instruction->base,15005 IrInstruction *result = ir_const(ira, &instruction->base,
14997 get_array_type(ira->codegen, child_type, new_array_len));15006 get_array_type(ira->codegen, child_type, new_array_len, false));
14998 ConstExprValue *out_val = &result->value;15007 ConstExprValue *out_val = &result->value;
14999 if (array_val->data.x_array.special == ConstArraySpecialUndef) {15008 if (array_val->data.x_array.special == ConstArraySpecialUndef) {
15000 out_val->data.x_array.special = ConstArraySpecialUndef;15009 out_val->data.x_array.special = ConstArraySpecialUndef;
...@@ -19311,6 +19320,7 @@ static IrInstruction *ir_analyze_instruction_slice_type(IrAnalyze *ira,...@@ -19311,6 +19320,7 @@ static IrInstruction *ir_analyze_instruction_slice_type(IrAnalyze *ira,
19311 lazy_slice_type->is_const = slice_type_instruction->is_const;19320 lazy_slice_type->is_const = slice_type_instruction->is_const;
19312 lazy_slice_type->is_volatile = slice_type_instruction->is_volatile;19321 lazy_slice_type->is_volatile = slice_type_instruction->is_volatile;
19313 lazy_slice_type->is_allowzero = slice_type_instruction->is_allow_zero;19322 lazy_slice_type->is_allowzero = slice_type_instruction->is_allow_zero;
19323 lazy_slice_type->is_null_terminated = slice_type_instruction->is_null_terminated;
1931419324
19315 return result;19325 return result;
19316}19326}
...@@ -19420,7 +19430,8 @@ static IrInstruction *ir_analyze_instruction_array_type(IrAnalyze *ira,...@@ -19420,7 +19430,8 @@ static IrInstruction *ir_analyze_instruction_array_type(IrAnalyze *ira,
19420 {19430 {
19421 if ((err = type_resolve(ira->codegen, child_type, ResolveStatusSizeKnown)))19431 if ((err = type_resolve(ira->codegen, child_type, ResolveStatusSizeKnown)))
19422 return ira->codegen->invalid_instruction;19432 return ira->codegen->invalid_instruction;
19423 ZigType *result_type = get_array_type(ira->codegen, child_type, size);19433 ZigType *result_type = get_array_type(ira->codegen, child_type, size,
19434 array_type_instruction->is_null_terminated);
19424 return ir_const_type(ira, &array_type_instruction->base, result_type);19435 return ir_const_type(ira, &array_type_instruction->base, result_type);
19425 }19436 }
19426 }19437 }
...@@ -20496,7 +20507,7 @@ static IrInstruction *ir_analyze_instruction_container_init_list(IrAnalyze *ira,...@@ -20496,7 +20507,7 @@ static IrInstruction *ir_analyze_instruction_container_init_list(IrAnalyze *ira,
20496 if (container_type->id == ZigTypeIdArray) {20507 if (container_type->id == ZigTypeIdArray) {
20497 ZigType *child_type = container_type->data.array.child_type;20508 ZigType *child_type = container_type->data.array.child_type;
20498 if (container_type->data.array.len != elem_count) {20509 if (container_type->data.array.len != elem_count) {
20499 ZigType *literal_type = get_array_type(ira->codegen, child_type, elem_count);20510 ZigType *literal_type = get_array_type(ira->codegen, child_type, elem_count, false);
2050020511
20501 ir_add_error(ira, &instruction->base,20512 ir_add_error(ira, &instruction->base,
20502 buf_sprintf("expected %s literal, found %s literal",20513 buf_sprintf("expected %s literal, found %s literal",
...@@ -20983,7 +20994,7 @@ static Error ir_make_type_info_decls(IrAnalyze *ira, IrInstruction *source_instr...@@ -20983,7 +20994,7 @@ static Error ir_make_type_info_decls(IrAnalyze *ira, IrInstruction *source_instr
2098320994
20984 ConstExprValue *declaration_array = create_const_vals(1);20995 ConstExprValue *declaration_array = create_const_vals(1);
20985 declaration_array->special = ConstValSpecialStatic;20996 declaration_array->special = ConstValSpecialStatic;
20986 declaration_array->type = get_array_type(ira->codegen, type_info_declaration_type, declaration_count);20997 declaration_array->type = get_array_type(ira->codegen, type_info_declaration_type, declaration_count, false);
20987 declaration_array->data.x_array.special = ConstArraySpecialNone;20998 declaration_array->data.x_array.special = ConstArraySpecialNone;
20988 declaration_array->data.x_array.data.s_none.elements = create_const_vals(declaration_count);20999 declaration_array->data.x_array.data.s_none.elements = create_const_vals(declaration_count);
20989 init_const_slice(ira->codegen, out_val, declaration_array, 0, declaration_count, false);21000 init_const_slice(ira->codegen, out_val, declaration_array, 0, declaration_count, false);
...@@ -21128,7 +21139,7 @@ static Error ir_make_type_info_decls(IrAnalyze *ira, IrInstruction *source_instr...@@ -21128,7 +21139,7 @@ static Error ir_make_type_info_decls(IrAnalyze *ira, IrInstruction *source_instr
21128 ConstExprValue *fn_arg_name_array = create_const_vals(1);21139 ConstExprValue *fn_arg_name_array = create_const_vals(1);
21129 fn_arg_name_array->special = ConstValSpecialStatic;21140 fn_arg_name_array->special = ConstValSpecialStatic;
21130 fn_arg_name_array->type = get_array_type(ira->codegen,21141 fn_arg_name_array->type = get_array_type(ira->codegen,
21131 get_slice_type(ira->codegen, u8_ptr), fn_arg_count);21142 get_slice_type(ira->codegen, u8_ptr), fn_arg_count, false);
21132 fn_arg_name_array->data.x_array.special = ConstArraySpecialNone;21143 fn_arg_name_array->data.x_array.special = ConstArraySpecialNone;
21133 fn_arg_name_array->data.x_array.data.s_none.elements = create_const_vals(fn_arg_count);21144 fn_arg_name_array->data.x_array.data.s_none.elements = create_const_vals(fn_arg_count);
2113421145
...@@ -21376,7 +21387,7 @@ static Error ir_make_type_info_value(IrAnalyze *ira, IrInstruction *source_instr...@@ -21376,7 +21387,7 @@ static Error ir_make_type_info_value(IrAnalyze *ira, IrInstruction *source_instr
21376 result->special = ConstValSpecialStatic;21387 result->special = ConstValSpecialStatic;
21377 result->type = ir_type_info_get_type(ira, "Array", nullptr);21388 result->type = ir_type_info_get_type(ira, "Array", nullptr);
2137821389
21379 ConstExprValue **fields = alloc_const_vals_ptrs(2);21390 ConstExprValue **fields = alloc_const_vals_ptrs(3);
21380 result->data.x_struct.fields = fields;21391 result->data.x_struct.fields = fields;
2138121392
21382 // len: usize21393 // len: usize
...@@ -21389,6 +21400,11 @@ static Error ir_make_type_info_value(IrAnalyze *ira, IrInstruction *source_instr...@@ -21389,6 +21400,11 @@ static Error ir_make_type_info_value(IrAnalyze *ira, IrInstruction *source_instr
21389 fields[1]->special = ConstValSpecialStatic;21400 fields[1]->special = ConstValSpecialStatic;
21390 fields[1]->type = ira->codegen->builtin_types.entry_type;21401 fields[1]->type = ira->codegen->builtin_types.entry_type;
21391 fields[1]->data.x_type = type_entry->data.array.child_type;21402 fields[1]->data.x_type = type_entry->data.array.child_type;
21403 // is_null_terminated: bool
21404 ensure_field_index(result->type, "is_null_terminated", 2);
21405 fields[2]->special = ConstValSpecialStatic;
21406 fields[2]->type = ira->codegen->builtin_types.entry_bool;
21407 fields[2]->data.x_bool = type_entry->data.array.is_null_terminated;
2139221408
21393 break;21409 break;
21394 }21410 }
...@@ -21476,7 +21492,7 @@ static Error ir_make_type_info_value(IrAnalyze *ira, IrInstruction *source_instr...@@ -21476,7 +21492,7 @@ static Error ir_make_type_info_value(IrAnalyze *ira, IrInstruction *source_instr
2147621492
21477 ConstExprValue *enum_field_array = create_const_vals(1);21493 ConstExprValue *enum_field_array = create_const_vals(1);
21478 enum_field_array->special = ConstValSpecialStatic;21494 enum_field_array->special = ConstValSpecialStatic;
21479 enum_field_array->type = get_array_type(ira->codegen, type_info_enum_field_type, enum_field_count);21495 enum_field_array->type = get_array_type(ira->codegen, type_info_enum_field_type, enum_field_count, false);
21480 enum_field_array->data.x_array.special = ConstArraySpecialNone;21496 enum_field_array->data.x_array.special = ConstArraySpecialNone;
21481 enum_field_array->data.x_array.data.s_none.elements = create_const_vals(enum_field_count);21497 enum_field_array->data.x_array.data.s_none.elements = create_const_vals(enum_field_count);
2148221498
...@@ -21524,7 +21540,7 @@ static Error ir_make_type_info_value(IrAnalyze *ira, IrInstruction *source_instr...@@ -21524,7 +21540,7 @@ static Error ir_make_type_info_value(IrAnalyze *ira, IrInstruction *source_instr
21524 uint32_t error_count = type_entry->data.error_set.err_count;21540 uint32_t error_count = type_entry->data.error_set.err_count;
21525 ConstExprValue *error_array = create_const_vals(1);21541 ConstExprValue *error_array = create_const_vals(1);
21526 error_array->special = ConstValSpecialStatic;21542 error_array->special = ConstValSpecialStatic;
21527 error_array->type = get_array_type(ira->codegen, type_info_error_type, error_count);21543 error_array->type = get_array_type(ira->codegen, type_info_error_type, error_count, false);
21528 error_array->data.x_array.special = ConstArraySpecialNone;21544 error_array->data.x_array.special = ConstArraySpecialNone;
21529 error_array->data.x_array.data.s_none.elements = create_const_vals(error_count);21545 error_array->data.x_array.data.s_none.elements = create_const_vals(error_count);
2153021546
...@@ -21620,7 +21636,7 @@ static Error ir_make_type_info_value(IrAnalyze *ira, IrInstruction *source_instr...@@ -21620,7 +21636,7 @@ static Error ir_make_type_info_value(IrAnalyze *ira, IrInstruction *source_instr
2162021636
21621 ConstExprValue *union_field_array = create_const_vals(1);21637 ConstExprValue *union_field_array = create_const_vals(1);
21622 union_field_array->special = ConstValSpecialStatic;21638 union_field_array->special = ConstValSpecialStatic;
21623 union_field_array->type = get_array_type(ira->codegen, type_info_union_field_type, union_field_count);21639 union_field_array->type = get_array_type(ira->codegen, type_info_union_field_type, union_field_count, false);
21624 union_field_array->data.x_array.special = ConstArraySpecialNone;21640 union_field_array->data.x_array.special = ConstArraySpecialNone;
21625 union_field_array->data.x_array.data.s_none.elements = create_const_vals(union_field_count);21641 union_field_array->data.x_array.data.s_none.elements = create_const_vals(union_field_count);
2162621642
...@@ -21700,7 +21716,7 @@ static Error ir_make_type_info_value(IrAnalyze *ira, IrInstruction *source_instr...@@ -21700,7 +21716,7 @@ static Error ir_make_type_info_value(IrAnalyze *ira, IrInstruction *source_instr
2170021716
21701 ConstExprValue *struct_field_array = create_const_vals(1);21717 ConstExprValue *struct_field_array = create_const_vals(1);
21702 struct_field_array->special = ConstValSpecialStatic;21718 struct_field_array->special = ConstValSpecialStatic;
21703 struct_field_array->type = get_array_type(ira->codegen, type_info_struct_field_type, struct_field_count);21719 struct_field_array->type = get_array_type(ira->codegen, type_info_struct_field_type, struct_field_count, false);
21704 struct_field_array->data.x_array.special = ConstArraySpecialNone;21720 struct_field_array->data.x_array.special = ConstArraySpecialNone;
21705 struct_field_array->data.x_array.data.s_none.elements = create_const_vals(struct_field_count);21721 struct_field_array->data.x_array.data.s_none.elements = create_const_vals(struct_field_count);
2170621722
...@@ -21803,7 +21819,7 @@ static Error ir_make_type_info_value(IrAnalyze *ira, IrInstruction *source_instr...@@ -21803,7 +21819,7 @@ static Error ir_make_type_info_value(IrAnalyze *ira, IrInstruction *source_instr
2180321819
21804 ConstExprValue *fn_arg_array = create_const_vals(1);21820 ConstExprValue *fn_arg_array = create_const_vals(1);
21805 fn_arg_array->special = ConstValSpecialStatic;21821 fn_arg_array->special = ConstValSpecialStatic;
21806 fn_arg_array->type = get_array_type(ira->codegen, type_info_fn_arg_type, fn_arg_count);21822 fn_arg_array->type = get_array_type(ira->codegen, type_info_fn_arg_type, fn_arg_count, false);
21807 fn_arg_array->data.x_array.special = ConstArraySpecialNone;21823 fn_arg_array->data.x_array.special = ConstArraySpecialNone;
21808 fn_arg_array->data.x_array.data.s_none.elements = create_const_vals(fn_arg_count);21824 fn_arg_array->data.x_array.data.s_none.elements = create_const_vals(fn_arg_count);
2180921825
...@@ -21983,7 +21999,8 @@ static ZigType *type_info_to_type(IrAnalyze *ira, IrInstruction *instruction, Zi...@@ -21983,7 +21999,8 @@ static ZigType *type_info_to_type(IrAnalyze *ira, IrInstruction *instruction, Zi
21983 assert(payload->type == ir_type_info_get_type(ira, "Array", nullptr));21999 assert(payload->type == ir_type_info_get_type(ira, "Array", nullptr));
21984 return get_array_type(ira->codegen,22000 return get_array_type(ira->codegen,
21985 get_const_field_meta_type(ira, payload, "child", 1),22001 get_const_field_meta_type(ira, payload, "child", 1),
21986 bigint_as_u64(get_const_field_lit_int(ira, payload, "len", 0))22002 bigint_as_u64(get_const_field_lit_int(ira, payload, "len", 0)),
22003 get_const_field_bool(ira, payload, "is_null_terminated", 2)
21987 );22004 );
21988 case ZigTypeIdComptimeFloat:22005 case ZigTypeIdComptimeFloat:
21989 return ira->codegen->builtin_types.entry_num_lit_float;22006 return ira->codegen->builtin_types.entry_num_lit_float;
...@@ -22366,7 +22383,7 @@ static IrInstruction *ir_analyze_instruction_embed_file(IrAnalyze *ira, IrInstru...@@ -22366,7 +22383,7 @@ static IrInstruction *ir_analyze_instruction_embed_file(IrAnalyze *ira, IrInstru
22366 }22383 }
2236722384
22368 ZigType *result_type = get_array_type(ira->codegen,22385 ZigType *result_type = get_array_type(ira->codegen,
22369 ira->codegen->builtin_types.entry_u8, buf_len(file_contents));22386 ira->codegen->builtin_types.entry_u8, buf_len(file_contents), false);
22370 IrInstruction *result = ir_const(ira, &instruction->base, result_type);22387 IrInstruction *result = ir_const(ira, &instruction->base, result_type);
22371 init_const_str_lit(ira->codegen, &result->value, file_contents);22388 init_const_str_lit(ira->codegen, &result->value, file_contents);
22372 return result;22389 return result;
...@@ -27581,7 +27598,9 @@ static Error ir_resolve_lazy_raw(AstNode *source_node, ConstExprValue *val) {...@@ -27581,7 +27598,9 @@ static Error ir_resolve_lazy_raw(AstNode *source_node, ConstExprValue *val) {
27581 if ((err = type_resolve(ira->codegen, elem_type, needed_status)))27598 if ((err = type_resolve(ira->codegen, elem_type, needed_status)))
27582 return err;27599 return err;
27583 ZigType *slice_ptr_type = get_pointer_to_type_extra(ira->codegen, elem_type,27600 ZigType *slice_ptr_type = get_pointer_to_type_extra(ira->codegen, elem_type,
27584 lazy_slice_type->is_const, lazy_slice_type->is_volatile, PtrLenUnknown, align_bytes,27601 lazy_slice_type->is_const, lazy_slice_type->is_volatile,
27602 lazy_slice_type->is_null_terminated ? PtrLenNull : PtrLenUnknown,
27603 align_bytes,
27585 0, 0, lazy_slice_type->is_allowzero);27604 0, 0, lazy_slice_type->is_allowzero);
27586 val->special = ConstValSpecialStatic;27605 val->special = ConstValSpecialStatic;
27587 assert(val->type->id == ZigTypeIdMetaType);27606 assert(val->type->id == ZigTypeIdMetaType);
test/stage1/behavior/if.zig+4
...@@ -81,6 +81,10 @@ test "if prongs cast to expected type instead of peer type resolution" {...@@ -81,6 +81,10 @@ test "if prongs cast to expected type instead of peer type resolution" {
81 var x: i32 = 0;81 var x: i32 = 0;
82 x = if (f) 1 else 2;82 x = if (f) 1 else 2;
83 expect(x == 2);83 expect(x == 2);
84
85 var b = true;
86 const y: i32 = if (b) 1 else 2;
87 expect(y == 1);
84 }88 }
85 };89 };
86 S.doTheTest(false);90 S.doTheTest(false);
test/stage1/behavior/type.zig+83-64
...@@ -11,103 +11,122 @@ fn testTypes(comptime types: []const type) void {...@@ -11,103 +11,122 @@ fn testTypes(comptime types: []const type) void {
11}11}
1212
13test "Type.MetaType" {13test "Type.MetaType" {
14 testing.expect(type == @Type(TypeInfo { .Type = undefined }));14 testing.expect(type == @Type(TypeInfo{ .Type = undefined }));
15 testTypes([_]type {type});15 testTypes([_]type{type});
16}16}
1717
18test "Type.Void" {18test "Type.Void" {
19 testing.expect(void == @Type(TypeInfo { .Void = undefined }));19 testing.expect(void == @Type(TypeInfo{ .Void = undefined }));
20 testTypes([_]type {void});20 testTypes([_]type{void});
21}21}
2222
23test "Type.Bool" {23test "Type.Bool" {
24 testing.expect(bool == @Type(TypeInfo { .Bool = undefined }));24 testing.expect(bool == @Type(TypeInfo{ .Bool = undefined }));
25 testTypes([_]type {bool});25 testTypes([_]type{bool});
26}26}
2727
28test "Type.NoReturn" {28test "Type.NoReturn" {
29 testing.expect(noreturn == @Type(TypeInfo { .NoReturn = undefined }));29 testing.expect(noreturn == @Type(TypeInfo{ .NoReturn = undefined }));
30 testTypes([_]type {noreturn});30 testTypes([_]type{noreturn});
31}31}
3232
33test "Type.Int" {33test "Type.Int" {
34 testing.expect(u1 == @Type(TypeInfo { .Int = TypeInfo.Int { .is_signed = false, .bits = 1 } }));34 testing.expect(u1 == @Type(TypeInfo{ .Int = TypeInfo.Int{ .is_signed = false, .bits = 1 } }));
35 testing.expect(i1 == @Type(TypeInfo { .Int = TypeInfo.Int { .is_signed = true, .bits = 1 } }));35 testing.expect(i1 == @Type(TypeInfo{ .Int = TypeInfo.Int{ .is_signed = true, .bits = 1 } }));
36 testing.expect(u8 == @Type(TypeInfo { .Int = TypeInfo.Int { .is_signed = false, .bits = 8 } }));36 testing.expect(u8 == @Type(TypeInfo{ .Int = TypeInfo.Int{ .is_signed = false, .bits = 8 } }));
37 testing.expect(i8 == @Type(TypeInfo { .Int = TypeInfo.Int { .is_signed = true, .bits = 8 } }));37 testing.expect(i8 == @Type(TypeInfo{ .Int = TypeInfo.Int{ .is_signed = true, .bits = 8 } }));
38 testing.expect(u64 == @Type(TypeInfo { .Int = TypeInfo.Int { .is_signed = false, .bits = 64 } }));38 testing.expect(u64 == @Type(TypeInfo{ .Int = TypeInfo.Int{ .is_signed = false, .bits = 64 } }));
39 testing.expect(i64 == @Type(TypeInfo { .Int = TypeInfo.Int { .is_signed = true, .bits = 64 } }));39 testing.expect(i64 == @Type(TypeInfo{ .Int = TypeInfo.Int{ .is_signed = true, .bits = 64 } }));
40 testTypes([_]type {u8,u32,i64});40 testTypes([_]type{ u8, u32, i64 });
41}41}
4242
43test "Type.Float" {43test "Type.Float" {
44 testing.expect(f16 == @Type(TypeInfo { .Float = TypeInfo.Float { .bits = 16 } }));44 testing.expect(f16 == @Type(TypeInfo{ .Float = TypeInfo.Float{ .bits = 16 } }));
45 testing.expect(f32 == @Type(TypeInfo { .Float = TypeInfo.Float { .bits = 32 } }));45 testing.expect(f32 == @Type(TypeInfo{ .Float = TypeInfo.Float{ .bits = 32 } }));
46 testing.expect(f64 == @Type(TypeInfo { .Float = TypeInfo.Float { .bits = 64 } }));46 testing.expect(f64 == @Type(TypeInfo{ .Float = TypeInfo.Float{ .bits = 64 } }));
47 testing.expect(f128 == @Type(TypeInfo { .Float = TypeInfo.Float { .bits = 128 } }));47 testing.expect(f128 == @Type(TypeInfo{ .Float = TypeInfo.Float{ .bits = 128 } }));
48 testTypes([_]type {f16, f32, f64, f128});48 testTypes([_]type{ f16, f32, f64, f128 });
49}49}
5050
51test "Type.Pointer" {51test "Type.Pointer" {
52 testTypes([_]type {52 testTypes([_]type{
53 // One Value Pointer Types53 // One Value Pointer Types
54 *u8, *const u8,54 *u8, *const u8,
55 *volatile u8, *const volatile u8,55 *volatile u8, *const volatile u8,
56 *align(4) u8, *const align(4) u8,56 *align(4) u8, *align(4) const u8,
57 *volatile align(4) u8, *const volatile align(4) u8,57 *align(4) volatile u8, *align(4) const volatile u8,
58 *align(8) u8, *const align(8) u8,58 *align(8) u8, *align(8) const u8,
59 *volatile align(8) u8, *const volatile align(8) u8,59 *align(8) volatile u8, *align(8) const volatile u8,
60 *allowzero u8, *const allowzero u8,60 *allowzero u8, *allowzero const u8,
61 *volatile allowzero u8, *const volatile allowzero u8,61 *allowzero volatile u8, *allowzero const volatile u8,
62 *align(4) allowzero u8, *const align(4) allowzero u8,62 *allowzero align(4) u8, *allowzero align(4) const u8,
63 *volatile align(4) allowzero u8, *const volatile align(4) allowzero u8,63 *allowzero align(4) volatile u8, *allowzero align(4) const volatile u8,
64 // Many Values Pointer Types64 // Many Values Pointer Types
65 [*]u8, [*]const u8,65 [*]u8, [*]const u8,
66 [*]volatile u8, [*]const volatile u8,66 [*]volatile u8, [*]const volatile u8,
67 [*]align(4) u8, [*]const align(4) u8,67 [*]align(4) u8, [*]align(4) const u8,
68 [*]volatile align(4) u8, [*]const volatile align(4) u8,68 [*]align(4) volatile u8, [*]align(4) const volatile u8,
69 [*]align(8) u8, [*]const align(8) u8,69 [*]align(8) u8, [*]align(8) const u8,
70 [*]volatile align(8) u8, [*]const volatile align(8) u8,70 [*]align(8) volatile u8, [*]align(8) const volatile u8,
71 [*]allowzero u8, [*]const allowzero u8,71 [*]allowzero u8, [*]allowzero const u8,
72 [*]volatile allowzero u8, [*]const volatile allowzero u8,72 [*]allowzero volatile u8, [*]allowzero const volatile u8,
73 [*]align(4) allowzero u8, [*]const align(4) allowzero u8,73 [*]allowzero align(4) u8, [*]allowzero align(4) const u8,
74 [*]volatile align(4) allowzero u8, [*]const volatile align(4) allowzero u8,74 [*]allowzero align(4) volatile u8, [*]allowzero align(4) const volatile u8,
75 // Slice Types75 // Slice Types
76 []u8, []const u8,76 []u8, []const u8,
77 []volatile u8, []const volatile u8,77 []volatile u8, []const volatile u8,
78 []align(4) u8, []const align(4) u8,78 []align(4) u8, []align(4) const u8,
79 []volatile align(4) u8, []const volatile align(4) u8,79 []align(4) volatile u8, []align(4) const volatile u8,
80 []align(8) u8, []const align(8) u8,80 []align(8) u8, []align(8) const u8,
81 []volatile align(8) u8, []const volatile align(8) u8,81 []align(8) volatile u8, []align(8) const volatile u8,
82 []allowzero u8, []const allowzero u8,82 []allowzero u8, []allowzero const u8,
83 []volatile allowzero u8, []const volatile allowzero u8,83 []allowzero volatile u8, []allowzero const volatile u8,
84 []align(4) allowzero u8, []const align(4) allowzero u8,84 []allowzero align(4) u8, []allowzero align(4) const u8,
85 []volatile align(4) allowzero u8, []const volatile align(4) allowzero u8,85 []allowzero align(4) volatile u8, []allowzero align(4) const volatile u8,
86 // C Pointer Types86 // C Pointer Types
87 [*c]u8, [*c]const u8,87 [*c]u8, [*c]const u8,
88 [*c]volatile u8, [*c]const volatile u8,88 [*c]volatile u8, [*c]const volatile u8,
89 [*c]align(4) u8, [*c]const align(4) u8,89 [*c]align(4) u8, [*c]align(4) const u8,
90 [*c]volatile align(4) u8, [*c]const volatile align(4) u8,90 [*c]align(4) volatile u8, [*c]align(4) const volatile u8,
91 [*c]align(8) u8, [*c]const align(8) u8,91 [*c]align(8) u8, [*c]align(8) const u8,
92 [*c]volatile align(8) u8, [*c]const volatile align(8) u8,92 [*c]align(8) volatile u8, [*c]align(8) const volatile u8,
93 });93 });
94}94}
9595
96test "Type.Array" {96test "Type.Array" {
97 testing.expect([123]u8 == @Type(TypeInfo { .Array = TypeInfo.Array { .len = 123, .child = u8 } }));97 testing.expect([123]u8 == @Type(TypeInfo{
98 testing.expect([2]u32 == @Type(TypeInfo { .Array = TypeInfo.Array { .len = 2, .child = u32 } }));98 .Array = TypeInfo.Array{
99 testTypes([_]type {[1]u8, [30]usize, [7]bool});99 .len = 123,
100 .child = u8,
101 .is_null_terminated = false,
102 },
103 }));
104 testing.expect([2]u32 == @Type(TypeInfo{
105 .Array = TypeInfo.Array{
106 .len = 2,
107 .child = u32,
108 .is_null_terminated = false,
109 },
110 }));
111 testing.expect([2]null u32 == @Type(TypeInfo{
112 .Array = TypeInfo.Array{
113 .len = 2,
114 .child = u32,
115 .is_null_terminated = true,
116 },
117 }));
118 testTypes([_]type{ [1]u8, [30]usize, [7]bool });
100}119}
101120
102test "Type.ComptimeFloat" {121test "Type.ComptimeFloat" {
103 testTypes([_]type {comptime_float});122 testTypes([_]type{comptime_float});
104}123}
105test "Type.ComptimeInt" {124test "Type.ComptimeInt" {
106 testTypes([_]type {comptime_int});125 testTypes([_]type{comptime_int});
107}126}
108test "Type.Undefined" {127test "Type.Undefined" {
109 testTypes([_]type {@typeOf(undefined)});128 testTypes([_]type{@typeOf(undefined)});
110}129}
111test "Type.Null" {130test "Type.Null" {
112 testTypes([_]type {@typeOf(null)});131 testTypes([_]type{@typeOf(null)});
113}132}
test/stage1/behavior/type_info.zig+26-5
...@@ -46,6 +46,7 @@ fn testPointer() void {...@@ -46,6 +46,7 @@ fn testPointer() void {
46 expect(u32_ptr_info.Pointer.is_volatile == false);46 expect(u32_ptr_info.Pointer.is_volatile == false);
47 expect(u32_ptr_info.Pointer.alignment == @alignOf(u32));47 expect(u32_ptr_info.Pointer.alignment == @alignOf(u32));
48 expect(u32_ptr_info.Pointer.child == u32);48 expect(u32_ptr_info.Pointer.child == u32);
49 expect(u32_ptr_info.Pointer.is_null_terminated == false);
49}50}
5051
51test "type info: unknown length pointer type info" {52test "type info: unknown length pointer type info" {
...@@ -55,14 +56,34 @@ test "type info: unknown length pointer type info" {...@@ -55,14 +56,34 @@ test "type info: unknown length pointer type info" {
5556
56fn testUnknownLenPtr() void {57fn testUnknownLenPtr() void {
57 const u32_ptr_info = @typeInfo([*]const volatile f64);58 const u32_ptr_info = @typeInfo([*]const volatile f64);
58 expect(@as(TypeId,u32_ptr_info) == TypeId.Pointer);59 expect(@as(TypeId, u32_ptr_info) == TypeId.Pointer);
59 expect(u32_ptr_info.Pointer.size == TypeInfo.Pointer.Size.Many);60 expect(u32_ptr_info.Pointer.size == TypeInfo.Pointer.Size.Many);
60 expect(u32_ptr_info.Pointer.is_const == true);61 expect(u32_ptr_info.Pointer.is_const == true);
61 expect(u32_ptr_info.Pointer.is_volatile == true);62 expect(u32_ptr_info.Pointer.is_volatile == true);
63 expect(u32_ptr_info.Pointer.is_null_terminated == false);
62 expect(u32_ptr_info.Pointer.alignment == @alignOf(f64));64 expect(u32_ptr_info.Pointer.alignment == @alignOf(f64));
63 expect(u32_ptr_info.Pointer.child == f64);65 expect(u32_ptr_info.Pointer.child == f64);
64}66}
6567
68test "type info: null terminated pointer type info" {
69 testNullTerminatedPtr();
70 comptime testNullTerminatedPtr();
71}
72
73fn testNullTerminatedPtr() void {
74 const ptr_info = @typeInfo([*]null u8);
75 expect(@as(TypeId, ptr_info) == TypeId.Pointer);
76 expect(ptr_info.Pointer.size == TypeInfo.Pointer.Size.Many);
77 expect(ptr_info.Pointer.is_const == false);
78 expect(ptr_info.Pointer.is_volatile == false);
79 expect(ptr_info.Pointer.is_null_terminated == true);
80
81 expect(@typeInfo([]null u8).Pointer.is_null_terminated == true);
82 expect(@typeInfo([10]null u8).Array.is_null_terminated == true);
83 expect(@typeInfo([10]null u8).Array.len == 10);
84 expect(@sizeOf([10]null u8) == 11);
85}
86
66test "type info: C pointer type info" {87test "type info: C pointer type info" {
67 testCPtr();88 testCPtr();
68 comptime testCPtr();89 comptime testCPtr();
...@@ -70,7 +91,7 @@ test "type info: C pointer type info" {...@@ -70,7 +91,7 @@ test "type info: C pointer type info" {
7091
71fn testCPtr() void {92fn testCPtr() void {
72 const ptr_info = @typeInfo([*c]align(4) const i8);93 const ptr_info = @typeInfo([*c]align(4) const i8);
73 expect(@as(TypeId,ptr_info) == TypeId.Pointer);94 expect(@as(TypeId, ptr_info) == TypeId.Pointer);
74 expect(ptr_info.Pointer.size == TypeInfo.Pointer.Size.C);95 expect(ptr_info.Pointer.size == TypeInfo.Pointer.Size.C);
75 expect(ptr_info.Pointer.is_const);96 expect(ptr_info.Pointer.is_const);
76 expect(!ptr_info.Pointer.is_volatile);97 expect(!ptr_info.Pointer.is_volatile);
...@@ -288,13 +309,13 @@ test "type info: anyframe and anyframe->T" {...@@ -288,13 +309,13 @@ test "type info: anyframe and anyframe->T" {
288fn testAnyFrame() void {309fn testAnyFrame() void {
289 {310 {
290 const anyframe_info = @typeInfo(anyframe->i32);311 const anyframe_info = @typeInfo(anyframe->i32);
291 expect(@as(TypeId,anyframe_info) == .AnyFrame);312 expect(@as(TypeId, anyframe_info) == .AnyFrame);
292 expect(anyframe_info.AnyFrame.child.? == i32);313 expect(anyframe_info.AnyFrame.child.? == i32);
293 }314 }
294315
295 {316 {
296 const anyframe_info = @typeInfo(anyframe);317 const anyframe_info = @typeInfo(anyframe);
297 expect(@as(TypeId,anyframe_info) == .AnyFrame);318 expect(@as(TypeId, anyframe_info) == .AnyFrame);
298 expect(anyframe_info.AnyFrame.child == null);319 expect(anyframe_info.AnyFrame.child == null);
299 }320 }
300}321}
...@@ -334,7 +355,7 @@ test "type info: extern fns with and without lib names" {...@@ -334,7 +355,7 @@ test "type info: extern fns with and without lib names" {
334 if (std.mem.eql(u8, decl.name, "bar1")) {355 if (std.mem.eql(u8, decl.name, "bar1")) {
335 expect(decl.data.Fn.lib_name == null);356 expect(decl.data.Fn.lib_name == null);
336 } else {357 } else {
337 std.testing.expectEqual(@as([]const u8,"cool"), decl.data.Fn.lib_name.?);358 std.testing.expectEqual(@as([]const u8, "cool"), decl.data.Fn.lib_name.?);
338 }359 }
339 }360 }
340 }361 }