authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-08-20 17:26:05-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-08-20 17:26:05-07:00
log6bbb168f6667520dc106bc93c6e3761d5611fccb
treec12be20be24223f37ab9a3c6cfdb9db8e7d263b4
parenteef111fe78d7b246b634a07561082a6fcf947e09
parent73d16d015e09c05aecba8a58881cbc429e8126fa

Merge branch 'Vexu-stage2'

closes #6107

9 files changed, 1295 insertions(+), 928 deletions(-)

src-self-hosted/Module.zig+100-10
...@@ -1485,6 +1485,7 @@ fn astGenAndAnalyzeDecl(self: *Module, decl: *Decl) !bool {...@@ -1485,6 +1485,7 @@ fn astGenAndAnalyzeDecl(self: *Module, decl: *Decl) !bool {
1485 const type_node = var_decl.getTrailer("type_node") orelse1485 const type_node = var_decl.getTrailer("type_node") orelse
1486 break :blk null;1486 break :blk null;
14871487
1488 // Temporary arena for the zir instructions.
1488 var type_scope_arena = std.heap.ArenaAllocator.init(self.gpa);1489 var type_scope_arena = std.heap.ArenaAllocator.init(self.gpa);
1489 defer type_scope_arena.deinit();1490 defer type_scope_arena.deinit();
1490 var type_scope: Scope.GenZIR = .{1491 var type_scope: Scope.GenZIR = .{
...@@ -1539,7 +1540,8 @@ fn astGenAndAnalyzeDecl(self: *Module, decl: *Decl) !bool {...@@ -1539,7 +1540,8 @@ fn astGenAndAnalyzeDecl(self: *Module, decl: *Decl) !bool {
1539 try self.coerce(&inner_block.base, some, ret.operand)1540 try self.coerce(&inner_block.base, some, ret.operand)
1540 else1541 else
1541 ret.operand;1542 ret.operand;
1542 const val = try self.resolveConstValue(&inner_block.base, coerced);1543 const val = coerced.value() orelse
1544 return self.fail(&block_scope.base, inst.src, "unable to resolve comptime value", .{});
15431545
1544 var_type = explicit_type orelse try ret.operand.ty.copy(block_scope.arena);1546 var_type = explicit_type orelse try ret.operand.ty.copy(block_scope.arena);
1545 break :blk try val.copy(block_scope.arena);1547 break :blk try val.copy(block_scope.arena);
...@@ -1603,7 +1605,41 @@ fn astGenAndAnalyzeDecl(self: *Module, decl: *Decl) !bool {...@@ -1603,7 +1605,41 @@ fn astGenAndAnalyzeDecl(self: *Module, decl: *Decl) !bool {
1603 }1605 }
1604 return type_changed;1606 return type_changed;
1605 },1607 },
1606 .Comptime => @panic("TODO comptime decl"),1608 .Comptime => {
1609 const comptime_decl = @fieldParentPtr(ast.Node.Comptime, "base", ast_node);
1610
1611 decl.analysis = .in_progress;
1612
1613 // A comptime decl does not store any value so we can just deinit this arena after analysis is done.
1614 var analysis_arena = std.heap.ArenaAllocator.init(self.gpa);
1615 defer analysis_arena.deinit();
1616 var gen_scope: Scope.GenZIR = .{
1617 .decl = decl,
1618 .arena = &analysis_arena.allocator,
1619 .parent = decl.scope,
1620 };
1621 defer gen_scope.instructions.deinit(self.gpa);
1622
1623 // TODO comptime scope here
1624 _ = try astgen.expr(self, &gen_scope.base, .none, comptime_decl.expr);
1625
1626 var block_scope: Scope.Block = .{
1627 .parent = null,
1628 .func = null,
1629 .decl = decl,
1630 .instructions = .{},
1631 .arena = &analysis_arena.allocator,
1632 };
1633 defer block_scope.instructions.deinit(self.gpa);
1634
1635 _ = try zir_sema.analyzeBody(self, &block_scope.base, .{
1636 .instructions = gen_scope.instructions.items,
1637 });
1638
1639 decl.analysis = .complete;
1640 decl.generation = self.generation;
1641 return true;
1642 },
1607 .Use => @panic("TODO usingnamespace decl"),1643 .Use => @panic("TODO usingnamespace decl"),
1608 else => unreachable,1644 else => unreachable,
1609 }1645 }
...@@ -1794,7 +1830,16 @@ fn analyzeRootSrcFile(self: *Module, root_scope: *Scope.File) !void {...@@ -1794,7 +1830,16 @@ fn analyzeRootSrcFile(self: *Module, root_scope: *Scope.File) !void {
1794 }1830 }
1795 }1831 }
1796 } else if (src_decl.castTag(.Comptime)) |comptime_node| {1832 } else if (src_decl.castTag(.Comptime)) |comptime_node| {
1797 log.err("TODO: analyze comptime decl", .{});1833 const name_index = self.getNextAnonNameIndex();
1834 const name = try std.fmt.allocPrint(self.gpa, "__comptime_{}", .{name_index});
1835 defer self.gpa.free(name);
1836
1837 const name_hash = root_scope.fullyQualifiedNameHash(name);
1838 const contents_hash = std.zig.hashSrc(tree.getNodeSource(src_decl));
1839
1840 const new_decl = try self.createNewDecl(&root_scope.base, name, decl_i, name_hash, contents_hash);
1841 root_scope.decls.appendAssumeCapacity(new_decl);
1842 self.work_queue.writeItemAssumeCapacity(.{ .analyze_decl = new_decl });
1798 } else if (src_decl.castTag(.ContainerField)) |container_field| {1843 } else if (src_decl.castTag(.ContainerField)) |container_field| {
1799 log.err("TODO: analyze container field", .{});1844 log.err("TODO: analyze container field", .{});
1800 } else if (src_decl.castTag(.TestDecl)) |test_decl| {1845 } else if (src_decl.castTag(.TestDecl)) |test_decl| {
...@@ -2429,7 +2474,7 @@ pub fn analyzeDeclRef(self: *Module, scope: *Scope, src: usize, decl: *Decl) Inn...@@ -2429,7 +2474,7 @@ pub fn analyzeDeclRef(self: *Module, scope: *Scope, src: usize, decl: *Decl) Inn
2429 if (decl_tv.val.tag() == .variable) {2474 if (decl_tv.val.tag() == .variable) {
2430 return self.analyzeVarRef(scope, src, decl_tv);2475 return self.analyzeVarRef(scope, src, decl_tv);
2431 }2476 }
2432 const ty = try self.singlePtrType(scope, src, false, decl_tv.ty);2477 const ty = try self.simplePtrType(scope, src, decl_tv.ty, false, .One);
2433 const val_payload = try scope.arena().create(Value.Payload.DeclRef);2478 const val_payload = try scope.arena().create(Value.Payload.DeclRef);
2434 val_payload.* = .{ .decl = decl };2479 val_payload.* = .{ .decl = decl };
24352480
...@@ -2442,7 +2487,7 @@ pub fn analyzeDeclRef(self: *Module, scope: *Scope, src: usize, decl: *Decl) Inn...@@ -2442,7 +2487,7 @@ pub fn analyzeDeclRef(self: *Module, scope: *Scope, src: usize, decl: *Decl) Inn
2442fn analyzeVarRef(self: *Module, scope: *Scope, src: usize, tv: TypedValue) InnerError!*Inst {2487fn analyzeVarRef(self: *Module, scope: *Scope, src: usize, tv: TypedValue) InnerError!*Inst {
2443 const variable = tv.val.cast(Value.Payload.Variable).?.variable;2488 const variable = tv.val.cast(Value.Payload.Variable).?.variable;
24442489
2445 const ty = try self.singlePtrType(scope, src, variable.is_mutable, tv.ty);2490 const ty = try self.simplePtrType(scope, src, tv.ty, variable.is_mutable, .One);
2446 if (!variable.is_mutable and !variable.is_extern) {2491 if (!variable.is_mutable and !variable.is_extern) {
2447 const val_payload = try scope.arena().create(Value.Payload.RefVal);2492 const val_payload = try scope.arena().create(Value.Payload.RefVal);
2448 val_payload.* = .{ .val = variable.init };2493 val_payload.* = .{ .val = variable.init };
...@@ -2766,7 +2811,7 @@ pub fn coerce(self: *Module, scope: *Scope, dest_type: Type, inst: *Inst) !*Inst...@@ -2766,7 +2811,7 @@ pub fn coerce(self: *Module, scope: *Scope, dest_type: Type, inst: *Inst) !*Inst
27662811
2767 // T to ?T2812 // T to ?T
2768 if (dest_type.zigTypeTag() == .Optional) {2813 if (dest_type.zigTypeTag() == .Optional) {
2769 var buf: Type.Payload.Pointer = undefined;2814 var buf: Type.Payload.PointerSimple = undefined;
2770 const child_type = dest_type.optionalChild(&buf);2815 const child_type = dest_type.optionalChild(&buf);
2771 if (child_type.eql(inst.ty)) {2816 if (child_type.eql(inst.ty)) {
2772 return self.wrapOptional(scope, dest_type, inst);2817 return self.wrapOptional(scope, dest_type, inst);
...@@ -3145,11 +3190,56 @@ pub fn floatSub(self: *Module, scope: *Scope, float_type: Type, src: usize, lhs:...@@ -3145,11 +3190,56 @@ pub fn floatSub(self: *Module, scope: *Scope, float_type: Type, src: usize, lhs:
3145 return Value.initPayload(val_payload);3190 return Value.initPayload(val_payload);
3146}3191}
31473192
3148pub fn singlePtrType(self: *Module, scope: *Scope, src: usize, mutable: bool, elem_ty: Type) Allocator.Error!Type {3193pub fn simplePtrType(self: *Module, scope: *Scope, src: usize, elem_ty: Type, mutable: bool, size: std.builtin.TypeInfo.Pointer.Size) Allocator.Error!Type {
3194 if (!mutable and size == .Slice and elem_ty.eql(Type.initTag(.u8))) {
3195 return Type.initTag(.const_slice_u8);
3196 }
3197 // TODO stage1 type inference bug
3198 const T = Type.Tag;
3199
3200 const type_payload = try scope.arena().create(Type.Payload.PointerSimple);
3201 type_payload.* = .{
3202 .base = .{
3203 .tag = switch (size) {
3204 .One => if (mutable) T.single_mut_pointer else T.single_const_pointer,
3205 .Many => if (mutable) T.many_mut_pointer else T.many_const_pointer,
3206 .C => if (mutable) T.c_mut_pointer else T.c_const_pointer,
3207 .Slice => if (mutable) T.mut_slice else T.const_slice,
3208 },
3209 },
3210 .pointee_type = elem_ty,
3211 };
3212 return Type.initPayload(&type_payload.base);
3213}
3214
3215pub fn ptrType(
3216 self: *Module,
3217 scope: *Scope,
3218 src: usize,
3219 elem_ty: Type,
3220 sentinel: ?Value,
3221 @"align": u32,
3222 bit_offset: u16,
3223 host_size: u16,
3224 mutable: bool,
3225 @"allowzero": bool,
3226 @"volatile": bool,
3227 size: std.builtin.TypeInfo.Pointer.Size,
3228) Allocator.Error!Type {
3229 assert(host_size == 0 or bit_offset < host_size * 8);
3230
3231 // TODO check if type can be represented by simplePtrType
3149 const type_payload = try scope.arena().create(Type.Payload.Pointer);3232 const type_payload = try scope.arena().create(Type.Payload.Pointer);
3150 type_payload.* = .{3233 type_payload.* = .{
3151 .base = .{ .tag = if (mutable) .single_mut_pointer else .single_const_pointer },
3152 .pointee_type = elem_ty,3234 .pointee_type = elem_ty,
3235 .sentinel = sentinel,
3236 .@"align" = @"align",
3237 .bit_offset = bit_offset,
3238 .host_size = host_size,
3239 .@"allowzero" = @"allowzero",
3240 .mutable = mutable,
3241 .@"volatile" = @"volatile",
3242 .size = size,
3153 };3243 };
3154 return Type.initPayload(&type_payload.base);3244 return Type.initPayload(&type_payload.base);
3155}3245}
...@@ -3157,7 +3247,7 @@ pub fn singlePtrType(self: *Module, scope: *Scope, src: usize, mutable: bool, el...@@ -3157,7 +3247,7 @@ pub fn singlePtrType(self: *Module, scope: *Scope, src: usize, mutable: bool, el
3157pub fn optionalType(self: *Module, scope: *Scope, child_type: Type) Allocator.Error!Type {3247pub fn optionalType(self: *Module, scope: *Scope, child_type: Type) Allocator.Error!Type {
3158 return Type.initPayload(switch (child_type.tag()) {3248 return Type.initPayload(switch (child_type.tag()) {
3159 .single_const_pointer => blk: {3249 .single_const_pointer => blk: {
3160 const payload = try scope.arena().create(Type.Payload.Pointer);3250 const payload = try scope.arena().create(Type.Payload.PointerSimple);
3161 payload.* = .{3251 payload.* = .{
3162 .base = .{ .tag = .optional_single_const_pointer },3252 .base = .{ .tag = .optional_single_const_pointer },
3163 .pointee_type = child_type.elemType(),3253 .pointee_type = child_type.elemType(),
...@@ -3165,7 +3255,7 @@ pub fn optionalType(self: *Module, scope: *Scope, child_type: Type) Allocator.Er...@@ -3165,7 +3255,7 @@ pub fn optionalType(self: *Module, scope: *Scope, child_type: Type) Allocator.Er
3165 break :blk &payload.base;3255 break :blk &payload.base;
3166 },3256 },
3167 .single_mut_pointer => blk: {3257 .single_mut_pointer => blk: {
3168 const payload = try scope.arena().create(Type.Payload.Pointer);3258 const payload = try scope.arena().create(Type.Payload.PointerSimple);
3169 payload.* = .{3259 payload.* = .{
3170 .base = .{ .tag = .optional_single_mut_pointer },3260 .base = .{ .tag = .optional_single_mut_pointer },
3171 .pointee_type = child_type.elemType(),3261 .pointee_type = child_type.elemType(),
src-self-hosted/astgen.zig+41-17
...@@ -262,6 +262,7 @@ pub fn expr(mod: *Module, scope: *Scope, rl: ResultLoc, node: *ast.Node) InnerEr...@@ -262,6 +262,7 @@ pub fn expr(mod: *Module, scope: *Scope, rl: ResultLoc, node: *ast.Node) InnerEr
262 .EnumLiteral => return rlWrap(mod, scope, rl, try enumLiteral(mod, scope, node.castTag(.EnumLiteral).?)),262 .EnumLiteral => return rlWrap(mod, scope, rl, try enumLiteral(mod, scope, node.castTag(.EnumLiteral).?)),
263 .MultilineStringLiteral => return rlWrap(mod, scope, rl, try multilineStrLiteral(mod, scope, node.castTag(.MultilineStringLiteral).?)),263 .MultilineStringLiteral => return rlWrap(mod, scope, rl, try multilineStrLiteral(mod, scope, node.castTag(.MultilineStringLiteral).?)),
264 .CharLiteral => return rlWrap(mod, scope, rl, try charLiteral(mod, scope, node.castTag(.CharLiteral).?)),264 .CharLiteral => return rlWrap(mod, scope, rl, try charLiteral(mod, scope, node.castTag(.CharLiteral).?)),
265 .SliceType => return rlWrap(mod, scope, rl, try sliceType(mod, scope, node.castTag(.SliceType).?)),
265266
266 .Defer => return mod.failNode(scope, node, "TODO implement astgen.expr for .Defer", .{}),267 .Defer => return mod.failNode(scope, node, "TODO implement astgen.expr for .Defer", .{}),
267 .Catch => return mod.failNode(scope, node, "TODO implement astgen.expr for .Catch", .{}),268 .Catch => return mod.failNode(scope, node, "TODO implement astgen.expr for .Catch", .{}),
...@@ -275,7 +276,6 @@ pub fn expr(mod: *Module, scope: *Scope, rl: ResultLoc, node: *ast.Node) InnerEr...@@ -275,7 +276,6 @@ pub fn expr(mod: *Module, scope: *Scope, rl: ResultLoc, node: *ast.Node) InnerEr
275 .NegationWrap => return mod.failNode(scope, node, "TODO implement astgen.expr for .NegationWrap", .{}),276 .NegationWrap => return mod.failNode(scope, node, "TODO implement astgen.expr for .NegationWrap", .{}),
276 .Resume => return mod.failNode(scope, node, "TODO implement astgen.expr for .Resume", .{}),277 .Resume => return mod.failNode(scope, node, "TODO implement astgen.expr for .Resume", .{}),
277 .Try => return mod.failNode(scope, node, "TODO implement astgen.expr for .Try", .{}),278 .Try => return mod.failNode(scope, node, "TODO implement astgen.expr for .Try", .{}),
278 .SliceType => return mod.failNode(scope, node, "TODO implement astgen.expr for .SliceType", .{}),
279 .Slice => return mod.failNode(scope, node, "TODO implement astgen.expr for .Slice", .{}),279 .Slice => return mod.failNode(scope, node, "TODO implement astgen.expr for .Slice", .{}),
280 .ArrayAccess => return mod.failNode(scope, node, "TODO implement astgen.expr for .ArrayAccess", .{}),280 .ArrayAccess => return mod.failNode(scope, node, "TODO implement astgen.expr for .ArrayAccess", .{}),
281 .ArrayInitializer => return mod.failNode(scope, node, "TODO implement astgen.expr for .ArrayInitializer", .{}),281 .ArrayInitializer => return mod.failNode(scope, node, "TODO implement astgen.expr for .ArrayInitializer", .{}),
...@@ -569,43 +569,67 @@ fn optionalType(mod: *Module, scope: *Scope, node: *ast.Node.SimplePrefixOp) Inn...@@ -569,43 +569,67 @@ fn optionalType(mod: *Module, scope: *Scope, node: *ast.Node.SimplePrefixOp) Inn
569 return addZIRUnOp(mod, scope, src, .optional_type, operand);569 return addZIRUnOp(mod, scope, src, .optional_type, operand);
570}570}
571571
572fn sliceType(mod: *Module, scope: *Scope, node: *ast.Node.SliceType) InnerError!*zir.Inst {
573 const tree = scope.tree();
574 const src = tree.token_locs[node.op_token].start;
575 return ptrSliceType(mod, scope, src, &node.ptr_info, node.rhs, .Slice);
576}
577
572fn ptrType(mod: *Module, scope: *Scope, node: *ast.Node.PtrType) InnerError!*zir.Inst {578fn ptrType(mod: *Module, scope: *Scope, node: *ast.Node.PtrType) InnerError!*zir.Inst {
573 const tree = scope.tree();579 const tree = scope.tree();
574 const src = tree.token_locs[node.op_token].start;580 const src = tree.token_locs[node.op_token].start;
581 return ptrSliceType(mod, scope, src, &node.ptr_info, node.rhs, switch (tree.token_ids[node.op_token]) {
582 .Asterisk, .AsteriskAsterisk => .One,
583 // TODO stage1 type inference bug
584 .LBracket => @as(std.builtin.TypeInfo.Pointer.Size, switch (tree.token_ids[node.op_token + 2]) {
585 .Identifier => .C,
586 else => .Many,
587 }),
588 else => unreachable,
589 });
590}
591
592fn ptrSliceType(mod: *Module, scope: *Scope, src: usize, ptr_info: *ast.PtrInfo, rhs: *ast.Node, size: std.builtin.TypeInfo.Pointer.Size) InnerError!*zir.Inst {
575 const meta_type = try addZIRInstConst(mod, scope, src, .{593 const meta_type = try addZIRInstConst(mod, scope, src, .{
576 .ty = Type.initTag(.type),594 .ty = Type.initTag(.type),
577 .val = Value.initTag(.type_type),595 .val = Value.initTag(.type_type),
578 });596 });
579597
580 const simple = node.ptr_info.allowzero_token == null and598 const simple = ptr_info.allowzero_token == null and
581 node.ptr_info.align_info == null and599 ptr_info.align_info == null and
582 node.ptr_info.volatile_token == null and600 ptr_info.volatile_token == null and
583 node.ptr_info.sentinel == null;601 ptr_info.sentinel == null;
584602
585 if (simple) {603 if (simple) {
586 const child_type = try expr(mod, scope, .{ .ty = meta_type }, node.rhs);604 const child_type = try expr(mod, scope, .{ .ty = meta_type }, rhs);
587 return addZIRUnOp(mod, scope, src, if (node.ptr_info.const_token == null)605 const mutable = ptr_info.const_token == null;
588 .single_mut_ptr_type606 // TODO stage1 type inference bug
589 else607 const T = zir.Inst.Tag;
590 .single_const_ptr_type, child_type);608 return addZIRUnOp(mod, scope, src, switch (size) {
609 .One => if (mutable) T.single_mut_ptr_type else T.single_const_ptr_type,
610 .Many => if (mutable) T.many_mut_ptr_type else T.many_const_ptr_type,
611 .C => if (mutable) T.c_mut_ptr_type else T.c_const_ptr_type,
612 .Slice => if (mutable) T.mut_slice_type else T.mut_slice_type,
613 }, child_type);
591 }614 }
592615
593 var kw_args: std.meta.fieldInfo(zir.Inst.PtrType, "kw_args").field_type = .{};616 var kw_args: std.meta.fieldInfo(zir.Inst.PtrType, "kw_args").field_type = .{};
594 kw_args.@"allowzero" = node.ptr_info.allowzero_token != null;617 kw_args.size = size;
595 if (node.ptr_info.align_info) |some| {618 kw_args.@"allowzero" = ptr_info.allowzero_token != null;
619 if (ptr_info.align_info) |some| {
596 kw_args.@"align" = try expr(mod, scope, .none, some.node);620 kw_args.@"align" = try expr(mod, scope, .none, some.node);
597 if (some.bit_range) |bit_range| {621 if (some.bit_range) |bit_range| {
598 kw_args.align_bit_start = try expr(mod, scope, .none, bit_range.start);622 kw_args.align_bit_start = try expr(mod, scope, .none, bit_range.start);
599 kw_args.align_bit_end = try expr(mod, scope, .none, bit_range.end);623 kw_args.align_bit_end = try expr(mod, scope, .none, bit_range.end);
600 }624 }
601 }625 }
602 kw_args.@"const" = node.ptr_info.const_token != null;626 kw_args.mutable = ptr_info.const_token == null;
603 kw_args.@"volatile" = node.ptr_info.volatile_token != null;627 kw_args.@"volatile" = ptr_info.volatile_token != null;
604 if (node.ptr_info.sentinel) |some| {628 if (ptr_info.sentinel) |some| {
605 kw_args.sentinel = try expr(mod, scope, .none, some);629 kw_args.sentinel = try expr(mod, scope, .none, some);
606 }630 }
607631
608 const child_type = try expr(mod, scope, .{ .ty = meta_type }, node.rhs);632 const child_type = try expr(mod, scope, .{ .ty = meta_type }, rhs);
609 if (kw_args.sentinel) |some| {633 if (kw_args.sentinel) |some| {
610 kw_args.sentinel = try addZIRBinOp(mod, scope, some.src, .as, child_type, some);634 kw_args.sentinel = try addZIRBinOp(mod, scope, some.src, .as, child_type, some);
611 }635 }
...@@ -1271,7 +1295,7 @@ fn multilineStrLiteral(mod: *Module, scope: *Scope, node: *ast.Node.MultilineStr...@@ -1271,7 +1295,7 @@ fn multilineStrLiteral(mod: *Module, scope: *Scope, node: *ast.Node.MultilineStr
1271 i += 1;1295 i += 1;
1272 }1296 }
1273 const slice = tree.tokenSlice(line);1297 const slice = tree.tokenSlice(line);
1274 mem.copy(u8, bytes[i..], slice[2..slice.len - 1]);1298 mem.copy(u8, bytes[i..], slice[2 .. slice.len - 1]);
1275 i += slice.len - 3;1299 i += slice.len - 3;
1276 }1300 }
12771301
src-self-hosted/codegen.zig+1-1
...@@ -2060,7 +2060,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {...@@ -2060,7 +2060,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
2060 if (typed_value.val.isNull())2060 if (typed_value.val.isNull())
2061 return MCValue{ .immediate = 0 };2061 return MCValue{ .immediate = 0 };
20622062
2063 var buf: Type.Payload.Pointer = undefined;2063 var buf: Type.Payload.PointerSimple = undefined;
2064 return self.genTypedValue(src, .{2064 return self.genTypedValue(src, .{
2065 .ty = typed_value.ty.optionalChild(&buf),2065 .ty = typed_value.ty.optionalChild(&buf),
2066 .val = typed_value.val,2066 .val = typed_value.val,
src-self-hosted/type.zig+344-34
...@@ -66,10 +66,18 @@ pub const Type = extern union {...@@ -66,10 +66,18 @@ pub const Type = extern union {
66 .function => return .Fn,66 .function => return .Fn,
6767
68 .array, .array_u8_sentinel_0, .array_u8, .array_sentinel => return .Array,68 .array, .array_u8_sentinel_0, .array_u8, .array_sentinel => return .Array,
69 .single_const_pointer => return .Pointer,69 .single_const_pointer_to_comptime_int,
70 .single_mut_pointer => return .Pointer,70 .const_slice_u8,
71 .single_const_pointer_to_comptime_int => return .Pointer,71 .single_const_pointer,
72 .const_slice_u8 => return .Pointer,72 .single_mut_pointer,
73 .many_const_pointer,
74 .many_mut_pointer,
75 .c_const_pointer,
76 .c_mut_pointer,
77 .const_slice,
78 .mut_slice,
79 .pointer,
80 => return .Pointer,
7381
74 .optional,82 .optional,
75 .optional_single_const_pointer,83 .optional_single_const_pointer,
...@@ -108,13 +116,19 @@ pub const Type = extern union {...@@ -108,13 +116,19 @@ pub const Type = extern union {
108 return @fieldParentPtr(T, "base", self.ptr_otherwise);116 return @fieldParentPtr(T, "base", self.ptr_otherwise);
109 }117 }
110118
111 pub fn castPointer(self: Type) ?*Payload.Pointer {119 pub fn castPointer(self: Type) ?*Payload.PointerSimple {
112 return switch (self.tag()) {120 return switch (self.tag()) {
113 .single_const_pointer,121 .single_const_pointer,
114 .single_mut_pointer,122 .single_mut_pointer,
123 .many_const_pointer,
124 .many_mut_pointer,
125 .c_const_pointer,
126 .c_mut_pointer,
127 .const_slice,
128 .mut_slice,
115 .optional_single_const_pointer,129 .optional_single_const_pointer,
116 .optional_single_mut_pointer,130 .optional_single_mut_pointer,
117 => @fieldParentPtr(Payload.Pointer, "base", self.ptr_otherwise),131 => @fieldParentPtr(Payload.PointerSimple, "base", self.ptr_otherwise),
118 else => null,132 else => null,
119 };133 };
120 }134 }
...@@ -198,8 +212,8 @@ pub const Type = extern union {...@@ -198,8 +212,8 @@ pub const Type = extern union {
198 return true;212 return true;
199 },213 },
200 .Optional => {214 .Optional => {
201 var buf_a: Payload.Pointer = undefined;215 var buf_a: Payload.PointerSimple = undefined;
202 var buf_b: Payload.Pointer = undefined;216 var buf_b: Payload.PointerSimple = undefined;
203 return a.optionalChild(&buf_a).eql(b.optionalChild(&buf_b));217 return a.optionalChild(&buf_a).eql(b.optionalChild(&buf_b));
204 },218 },
205 .Float,219 .Float,
...@@ -263,7 +277,7 @@ pub const Type = extern union {...@@ -263,7 +277,7 @@ pub const Type = extern union {
263 }277 }
264 },278 },
265 .Optional => {279 .Optional => {
266 var buf: Payload.Pointer = undefined;280 var buf: Payload.PointerSimple = undefined;
267 std.hash.autoHash(&hasher, self.optionalChild(&buf).hash());281 std.hash.autoHash(&hasher, self.optionalChild(&buf).hash());
268 },282 },
269 .Float,283 .Float,
...@@ -374,9 +388,34 @@ pub const Type = extern union {...@@ -374,9 +388,34 @@ pub const Type = extern union {
374 .optional => return self.copyPayloadSingleField(allocator, Payload.Optional, "child_type"),388 .optional => return self.copyPayloadSingleField(allocator, Payload.Optional, "child_type"),
375 .single_const_pointer,389 .single_const_pointer,
376 .single_mut_pointer,390 .single_mut_pointer,
391 .many_const_pointer,
392 .many_mut_pointer,
393 .c_const_pointer,
394 .c_mut_pointer,
395 .const_slice,
396 .mut_slice,
377 .optional_single_mut_pointer,397 .optional_single_mut_pointer,
378 .optional_single_const_pointer,398 .optional_single_const_pointer,
379 => return self.copyPayloadSingleField(allocator, Payload.Pointer, "pointee_type"),399 => return self.copyPayloadSingleField(allocator, Payload.PointerSimple, "pointee_type"),
400
401 .pointer => {
402 const payload = @fieldParentPtr(Payload.Pointer, "base", self.ptr_otherwise);
403 const new_payload = try allocator.create(Payload.Pointer);
404 new_payload.* = .{
405 .base = payload.base,
406
407 .pointee_type = try payload.pointee_type.copy(allocator),
408 .sentinel = if (payload.sentinel) |some| try some.copy(allocator) else null,
409 .@"align" = payload.@"align",
410 .bit_offset = payload.bit_offset,
411 .host_size = payload.host_size,
412 .@"allowzero" = payload.@"allowzero",
413 .mutable = payload.mutable,
414 .@"volatile" = payload.@"volatile",
415 .size = payload.size,
416 };
417 return Type{ .ptr_otherwise = &new_payload.base };
418 },
380 }419 }
381 }420 }
382421
...@@ -482,17 +521,53 @@ pub const Type = extern union {...@@ -482,17 +521,53 @@ pub const Type = extern union {
482 continue;521 continue;
483 },522 },
484 .single_const_pointer => {523 .single_const_pointer => {
485 const payload = @fieldParentPtr(Payload.Pointer, "base", ty.ptr_otherwise);524 const payload = @fieldParentPtr(Payload.PointerSimple, "base", ty.ptr_otherwise);
486 try out_stream.writeAll("*const ");525 try out_stream.writeAll("*const ");
487 ty = payload.pointee_type;526 ty = payload.pointee_type;
488 continue;527 continue;
489 },528 },
490 .single_mut_pointer => {529 .single_mut_pointer => {
491 const payload = @fieldParentPtr(Payload.Pointer, "base", ty.ptr_otherwise);530 const payload = @fieldParentPtr(Payload.PointerSimple, "base", ty.ptr_otherwise);
492 try out_stream.writeAll("*");531 try out_stream.writeAll("*");
493 ty = payload.pointee_type;532 ty = payload.pointee_type;
494 continue;533 continue;
495 },534 },
535 .many_const_pointer => {
536 const payload = @fieldParentPtr(Payload.PointerSimple, "base", ty.ptr_otherwise);
537 try out_stream.writeAll("[*]const ");
538 ty = payload.pointee_type;
539 continue;
540 },
541 .many_mut_pointer => {
542 const payload = @fieldParentPtr(Payload.PointerSimple, "base", ty.ptr_otherwise);
543 try out_stream.writeAll("[*]");
544 ty = payload.pointee_type;
545 continue;
546 },
547 .c_const_pointer => {
548 const payload = @fieldParentPtr(Payload.PointerSimple, "base", ty.ptr_otherwise);
549 try out_stream.writeAll("[*c]const ");
550 ty = payload.pointee_type;
551 continue;
552 },
553 .c_mut_pointer => {
554 const payload = @fieldParentPtr(Payload.PointerSimple, "base", ty.ptr_otherwise);
555 try out_stream.writeAll("[*c]");
556 ty = payload.pointee_type;
557 continue;
558 },
559 .const_slice => {
560 const payload = @fieldParentPtr(Payload.PointerSimple, "base", ty.ptr_otherwise);
561 try out_stream.writeAll("[]const ");
562 ty = payload.pointee_type;
563 continue;
564 },
565 .mut_slice => {
566 const payload = @fieldParentPtr(Payload.PointerSimple, "base", ty.ptr_otherwise);
567 try out_stream.writeAll("[]");
568 ty = payload.pointee_type;
569 continue;
570 },
496 .int_signed => {571 .int_signed => {
497 const payload = @fieldParentPtr(Payload.IntSigned, "base", ty.ptr_otherwise);572 const payload = @fieldParentPtr(Payload.IntSigned, "base", ty.ptr_otherwise);
498 return out_stream.print("i{}", .{payload.bits});573 return out_stream.print("i{}", .{payload.bits});
...@@ -508,17 +583,45 @@ pub const Type = extern union {...@@ -508,17 +583,45 @@ pub const Type = extern union {
508 continue;583 continue;
509 },584 },
510 .optional_single_const_pointer => {585 .optional_single_const_pointer => {
511 const payload = @fieldParentPtr(Payload.Pointer, "base", ty.ptr_otherwise);586 const payload = @fieldParentPtr(Payload.PointerSimple, "base", ty.ptr_otherwise);
512 try out_stream.writeAll("?*const ");587 try out_stream.writeAll("?*const ");
513 ty = payload.pointee_type;588 ty = payload.pointee_type;
514 continue;589 continue;
515 },590 },
516 .optional_single_mut_pointer => {591 .optional_single_mut_pointer => {
517 const payload = @fieldParentPtr(Payload.Pointer, "base", ty.ptr_otherwise);592 const payload = @fieldParentPtr(Payload.PointerSimple, "base", ty.ptr_otherwise);
518 try out_stream.writeAll("?*");593 try out_stream.writeAll("?*");
519 ty = payload.pointee_type;594 ty = payload.pointee_type;
520 continue;595 continue;
521 },596 },
597
598 .pointer => {
599 const payload = @fieldParentPtr(Payload.Pointer, "base", ty.ptr_otherwise);
600 if (payload.sentinel) |some| switch (payload.size) {
601 .One, .C => unreachable,
602 .Many => try out_stream.writeAll("[*:{}]"),
603 .Slice => try out_stream.writeAll("[:{}]"),
604 } else switch (payload.size) {
605 .One => try out_stream.writeAll("*"),
606 .Many => try out_stream.writeAll("[*]"),
607 .C => try out_stream.writeAll("[*c]"),
608 .Slice => try out_stream.writeAll("[]"),
609 }
610 if (payload.@"align" != 0) {
611 try out_stream.print("align({}", .{payload.@"align"});
612
613 if (payload.bit_offset != 0) {
614 try out_stream.print(":{}:{}", .{ payload.bit_offset, payload.host_size });
615 }
616 try out_stream.writeAll(") ");
617 }
618 if (!payload.mutable) try out_stream.writeAll("const ");
619 if (payload.@"volatile") try out_stream.writeAll("volatile ");
620 if (payload.@"allowzero") try out_stream.writeAll("allowzero ");
621
622 ty = payload.pointee_type;
623 continue;
624 },
522 }625 }
523 unreachable;626 unreachable;
524 }627 }
...@@ -616,9 +719,7 @@ pub const Type = extern union {...@@ -616,9 +719,7 @@ pub const Type = extern union {
616 // TODO lazy types719 // TODO lazy types
617 .array => self.elemType().hasCodeGenBits() and self.arrayLen() != 0,720 .array => self.elemType().hasCodeGenBits() and self.arrayLen() != 0,
618 .array_u8 => self.arrayLen() != 0,721 .array_u8 => self.arrayLen() != 0,
619 .array_sentinel => self.elemType().hasCodeGenBits(),722 .array_sentinel, .single_const_pointer, .single_mut_pointer, .many_const_pointer, .many_mut_pointer, .c_const_pointer, .c_mut_pointer, .const_slice, .mut_slice, .pointer => self.elemType().hasCodeGenBits(),
620 .single_const_pointer => self.elemType().hasCodeGenBits(),
621 .single_mut_pointer => self.elemType().hasCodeGenBits(),
622 .int_signed => self.cast(Payload.IntSigned).?.bits == 0,723 .int_signed => self.cast(Payload.IntSigned).?.bits == 0,
623 .int_unsigned => self.cast(Payload.IntUnsigned).?.bits == 0,724 .int_unsigned => self.cast(Payload.IntUnsigned).?.bits == 0,
624725
...@@ -669,10 +770,23 @@ pub const Type = extern union {...@@ -669,10 +770,23 @@ pub const Type = extern union {
669 .const_slice_u8,770 .const_slice_u8,
670 .single_const_pointer,771 .single_const_pointer,
671 .single_mut_pointer,772 .single_mut_pointer,
773 .many_const_pointer,
774 .many_mut_pointer,
775 .c_const_pointer,
776 .c_mut_pointer,
777 .const_slice,
778 .mut_slice,
672 .optional_single_const_pointer,779 .optional_single_const_pointer,
673 .optional_single_mut_pointer,780 .optional_single_mut_pointer,
674 => return @divExact(target.cpu.arch.ptrBitWidth(), 8),781 => return @divExact(target.cpu.arch.ptrBitWidth(), 8),
675782
783 .pointer => {
784 const payload = @fieldParentPtr(Payload.Pointer, "base", self.ptr_otherwise);
785
786 if (payload.@"align" != 0) return payload.@"align";
787 return @divExact(target.cpu.arch.ptrBitWidth(), 8);
788 },
789
676 .c_short => return @divExact(CType.short.sizeInBits(target), 8),790 .c_short => return @divExact(CType.short.sizeInBits(target), 8),
677 .c_ushort => return @divExact(CType.ushort.sizeInBits(target), 8),791 .c_ushort => return @divExact(CType.ushort.sizeInBits(target), 8),
678 .c_int => return @divExact(CType.int.sizeInBits(target), 8),792 .c_int => return @divExact(CType.int.sizeInBits(target), 8),
...@@ -704,7 +818,7 @@ pub const Type = extern union {...@@ -704,7 +818,7 @@ pub const Type = extern union {
704 },818 },
705819
706 .optional => {820 .optional => {
707 var buf: Payload.Pointer = undefined;821 var buf: Payload.PointerSimple = undefined;
708 const child_type = self.optionalChild(&buf);822 const child_type = self.optionalChild(&buf);
709 if (!child_type.hasCodeGenBits()) return 1;823 if (!child_type.hasCodeGenBits()) return 1;
710824
...@@ -744,6 +858,7 @@ pub const Type = extern union {...@@ -744,6 +858,7 @@ pub const Type = extern union {
744 .@"null" => unreachable,858 .@"null" => unreachable,
745 .@"undefined" => unreachable,859 .@"undefined" => unreachable,
746 .enum_literal => unreachable,860 .enum_literal => unreachable,
861 .single_const_pointer_to_comptime_int => unreachable,
747862
748 .u8,863 .u8,
749 .i8,864 .i8,
...@@ -766,15 +881,31 @@ pub const Type = extern union {...@@ -766,15 +881,31 @@ pub const Type = extern union {
766 .i32, .u32 => return 4,881 .i32, .u32 => return 4,
767 .i64, .u64 => return 8,882 .i64, .u64 => return 8,
768883
769 .isize,884 .isize, .usize => return @divExact(target.cpu.arch.ptrBitWidth(), 8),
770 .usize,885
771 .single_const_pointer_to_comptime_int,886 .const_slice,
887 .mut_slice,
772 .const_slice_u8,888 .const_slice_u8,
773 .single_const_pointer,889 => return @divExact(target.cpu.arch.ptrBitWidth(), 8) * 2,
774 .single_mut_pointer,890
775 .optional_single_const_pointer,891 .optional_single_const_pointer,
776 .optional_single_mut_pointer,892 .optional_single_mut_pointer,
777 => return @divExact(target.cpu.arch.ptrBitWidth(), 8),893 => {
894 if (self.elemType().hasCodeGenBits()) return 1;
895 return @divExact(target.cpu.arch.ptrBitWidth(), 8);
896 },
897
898 .single_const_pointer,
899 .single_mut_pointer,
900 .many_const_pointer,
901 .many_mut_pointer,
902 .c_const_pointer,
903 .c_mut_pointer,
904 .pointer,
905 => {
906 if (self.elemType().hasCodeGenBits()) return 0;
907 return @divExact(target.cpu.arch.ptrBitWidth(), 8);
908 },
778909
779 .c_short => return @divExact(CType.short.sizeInBits(target), 8),910 .c_short => return @divExact(CType.short.sizeInBits(target), 8),
780 .c_ushort => return @divExact(CType.ushort.sizeInBits(target), 8),911 .c_ushort => return @divExact(CType.ushort.sizeInBits(target), 8),
...@@ -805,7 +936,7 @@ pub const Type = extern union {...@@ -805,7 +936,7 @@ pub const Type = extern union {
805 },936 },
806937
807 .optional => {938 .optional => {
808 var buf: Payload.Pointer = undefined;939 var buf: Payload.PointerSimple = undefined;
809 const child_type = self.optionalChild(&buf);940 const child_type = self.optionalChild(&buf);
810 if (!child_type.hasCodeGenBits()) return 1;941 if (!child_type.hasCodeGenBits()) return 1;
811942
...@@ -872,12 +1003,20 @@ pub const Type = extern union {...@@ -872,12 +1003,20 @@ pub const Type = extern union {
872 .optional_single_mut_pointer,1003 .optional_single_mut_pointer,
873 .optional_single_const_pointer,1004 .optional_single_const_pointer,
874 .enum_literal,1005 .enum_literal,
1006 .many_const_pointer,
1007 .many_mut_pointer,
1008 .c_const_pointer,
1009 .c_mut_pointer,
1010 .const_slice,
1011 .mut_slice,
875 => false,1012 => false,
8761013
877 .single_const_pointer,1014 .single_const_pointer,
878 .single_mut_pointer,1015 .single_mut_pointer,
879 .single_const_pointer_to_comptime_int,1016 .single_const_pointer_to_comptime_int,
880 => true,1017 => true,
1018
1019 .pointer => self.cast(Payload.Pointer).?.size == .One,
881 };1020 };
882 }1021 }
8831022
...@@ -922,6 +1061,10 @@ pub const Type = extern union {...@@ -922,6 +1061,10 @@ pub const Type = extern union {
922 .array_u8_sentinel_0,1061 .array_u8_sentinel_0,
923 .single_const_pointer,1062 .single_const_pointer,
924 .single_mut_pointer,1063 .single_mut_pointer,
1064 .many_const_pointer,
1065 .many_mut_pointer,
1066 .c_const_pointer,
1067 .c_mut_pointer,
925 .single_const_pointer_to_comptime_int,1068 .single_const_pointer_to_comptime_int,
926 .fn_noreturn_no_args,1069 .fn_noreturn_no_args,
927 .fn_void_no_args,1070 .fn_void_no_args,
...@@ -936,7 +1079,12 @@ pub const Type = extern union {...@@ -936,7 +1079,12 @@ pub const Type = extern union {
936 .enum_literal,1079 .enum_literal,
937 => false,1080 => false,
9381081
939 .const_slice_u8 => true,1082 .const_slice,
1083 .mut_slice,
1084 .const_slice_u8,
1085 => true,
1086
1087 .pointer => self.cast(Payload.Pointer).?.size == .Slice,
940 };1088 };
941 }1089 }
9421090
...@@ -987,16 +1135,24 @@ pub const Type = extern union {...@@ -987,16 +1135,24 @@ pub const Type = extern union {
987 .int_unsigned,1135 .int_unsigned,
988 .int_signed,1136 .int_signed,
989 .single_mut_pointer,1137 .single_mut_pointer,
1138 .many_mut_pointer,
1139 .c_mut_pointer,
990 .optional,1140 .optional,
991 .optional_single_mut_pointer,1141 .optional_single_mut_pointer,
992 .optional_single_const_pointer,1142 .optional_single_const_pointer,
993 .enum_literal,1143 .enum_literal,
1144 .mut_slice,
994 => false,1145 => false,
9951146
996 .single_const_pointer,1147 .single_const_pointer,
1148 .many_const_pointer,
1149 .c_const_pointer,
997 .single_const_pointer_to_comptime_int,1150 .single_const_pointer_to_comptime_int,
998 .const_slice_u8,1151 .const_slice_u8,
1152 .const_slice,
999 => true,1153 => true,
1154
1155 .pointer => !self.cast(Payload.Pointer).?.mutable,
1000 };1156 };
1001 }1157 }
10021158
...@@ -1048,6 +1204,12 @@ pub const Type = extern union {...@@ -1048,6 +1204,12 @@ pub const Type = extern union {
1048 .int_signed,1204 .int_signed,
1049 .single_mut_pointer,1205 .single_mut_pointer,
1050 .single_const_pointer,1206 .single_const_pointer,
1207 .many_const_pointer,
1208 .many_mut_pointer,
1209 .c_const_pointer,
1210 .c_mut_pointer,
1211 .const_slice,
1212 .mut_slice,
1051 .single_const_pointer_to_comptime_int,1213 .single_const_pointer_to_comptime_int,
1052 .const_slice_u8,1214 .const_slice_u8,
1053 .optional,1215 .optional,
...@@ -1055,6 +1217,11 @@ pub const Type = extern union {...@@ -1055,6 +1217,11 @@ pub const Type = extern union {
1055 .optional_single_const_pointer,1217 .optional_single_const_pointer,
1056 .enum_literal,1218 .enum_literal,
1057 => false,1219 => false,
1220
1221 .pointer => {
1222 const payload = @fieldParentPtr(Payload.Pointer, "base", self.ptr_otherwise);
1223 return payload.@"volatile";
1224 },
1058 };1225 };
1059 }1226 }
10601227
...@@ -1063,7 +1230,7 @@ pub const Type = extern union {...@@ -1063,7 +1230,7 @@ pub const Type = extern union {
1063 switch (self.tag()) {1230 switch (self.tag()) {
1064 .optional_single_const_pointer, .optional_single_mut_pointer => return true,1231 .optional_single_const_pointer, .optional_single_mut_pointer => return true,
1065 .optional => {1232 .optional => {
1066 var buf: Payload.Pointer = undefined;1233 var buf: Payload.PointerSimple = undefined;
1067 const child_type = self.optionalChild(&buf);1234 const child_type = self.optionalChild(&buf);
1068 // optionals of zero sized pointers behave like bools1235 // optionals of zero sized pointers behave like bools
1069 if (!child_type.hasCodeGenBits()) return false;1236 if (!child_type.hasCodeGenBits()) return false;
...@@ -1101,7 +1268,7 @@ pub const Type = extern union {...@@ -1101,7 +1268,7 @@ pub const Type = extern union {
1101 => return false,1268 => return false,
11021269
1103 .Optional => {1270 .Optional => {
1104 var buf: Payload.Pointer = undefined;1271 var buf: Payload.PointerSimple = undefined;
1105 return ty.optionalChild(&buf).isValidVarType(is_extern);1272 return ty.optionalChild(&buf).isValidVarType(is_extern);
1106 },1273 },
1107 .Pointer, .Array => ty = ty.elemType(),1274 .Pointer, .Array => ty = ty.elemType(),
...@@ -1164,15 +1331,23 @@ pub const Type = extern union {...@@ -1164,15 +1331,23 @@ pub const Type = extern union {
11641331
1165 .array => self.cast(Payload.Array).?.elem_type,1332 .array => self.cast(Payload.Array).?.elem_type,
1166 .array_sentinel => self.cast(Payload.ArraySentinel).?.elem_type,1333 .array_sentinel => self.cast(Payload.ArraySentinel).?.elem_type,
1167 .single_const_pointer => self.castPointer().?.pointee_type,1334 .single_const_pointer,
1168 .single_mut_pointer => self.castPointer().?.pointee_type,1335 .single_mut_pointer,
1336 .many_const_pointer,
1337 .many_mut_pointer,
1338 .c_const_pointer,
1339 .c_mut_pointer,
1340 .const_slice,
1341 .mut_slice,
1342 => self.castPointer().?.pointee_type,
1169 .array_u8, .array_u8_sentinel_0, .const_slice_u8 => Type.initTag(.u8),1343 .array_u8, .array_u8_sentinel_0, .const_slice_u8 => Type.initTag(.u8),
1170 .single_const_pointer_to_comptime_int => Type.initTag(.comptime_int),1344 .single_const_pointer_to_comptime_int => Type.initTag(.comptime_int),
1345 .pointer => self.cast(Payload.Pointer).?.pointee_type,
1171 };1346 };
1172 }1347 }
11731348
1174 /// Asserts that the type is an optional.1349 /// Asserts that the type is an optional.
1175 pub fn optionalChild(self: Type, buf: *Payload.Pointer) Type {1350 pub fn optionalChild(self: Type, buf: *Payload.PointerSimple) Type {
1176 return switch (self.tag()) {1351 return switch (self.tag()) {
1177 .optional => self.cast(Payload.Optional).?.child_type,1352 .optional => self.cast(Payload.Optional).?.child_type,
1178 .optional_single_mut_pointer => {1353 .optional_single_mut_pointer => {
...@@ -1199,7 +1374,7 @@ pub const Type = extern union {...@@ -1199,7 +1374,7 @@ pub const Type = extern union {
1199 return switch (self.tag()) {1374 return switch (self.tag()) {
1200 .optional => self.cast(Payload.Optional).?.child_type,1375 .optional => self.cast(Payload.Optional).?.child_type,
1201 .optional_single_mut_pointer, .optional_single_const_pointer => {1376 .optional_single_mut_pointer, .optional_single_const_pointer => {
1202 const payload = try allocator.create(Payload.Pointer);1377 const payload = try allocator.create(Payload.PointerSimple);
1203 payload.* = .{1378 payload.* = .{
1204 .base = .{1379 .base = .{
1205 .tag = if (self.tag() == .optional_single_const_pointer)1380 .tag = if (self.tag() == .optional_single_const_pointer)
...@@ -1256,8 +1431,15 @@ pub const Type = extern union {...@@ -1256,8 +1431,15 @@ pub const Type = extern union {
1256 .fn_naked_noreturn_no_args,1431 .fn_naked_noreturn_no_args,
1257 .fn_ccc_void_no_args,1432 .fn_ccc_void_no_args,
1258 .function,1433 .function,
1434 .pointer,
1259 .single_const_pointer,1435 .single_const_pointer,
1260 .single_mut_pointer,1436 .single_mut_pointer,
1437 .many_const_pointer,
1438 .many_mut_pointer,
1439 .c_const_pointer,
1440 .c_mut_pointer,
1441 .const_slice,
1442 .mut_slice,
1261 .single_const_pointer_to_comptime_int,1443 .single_const_pointer_to_comptime_int,
1262 .const_slice_u8,1444 .const_slice_u8,
1263 .int_unsigned,1445 .int_unsigned,
...@@ -1316,8 +1498,15 @@ pub const Type = extern union {...@@ -1316,8 +1498,15 @@ pub const Type = extern union {
1316 .fn_naked_noreturn_no_args,1498 .fn_naked_noreturn_no_args,
1317 .fn_ccc_void_no_args,1499 .fn_ccc_void_no_args,
1318 .function,1500 .function,
1501 .pointer,
1319 .single_const_pointer,1502 .single_const_pointer,
1320 .single_mut_pointer,1503 .single_mut_pointer,
1504 .many_const_pointer,
1505 .many_mut_pointer,
1506 .c_const_pointer,
1507 .c_mut_pointer,
1508 .const_slice,
1509 .mut_slice,
1321 .single_const_pointer_to_comptime_int,1510 .single_const_pointer_to_comptime_int,
1322 .const_slice_u8,1511 .const_slice_u8,
1323 .int_unsigned,1512 .int_unsigned,
...@@ -1366,8 +1555,15 @@ pub const Type = extern union {...@@ -1366,8 +1555,15 @@ pub const Type = extern union {
1366 .array_sentinel,1555 .array_sentinel,
1367 .array_u8,1556 .array_u8,
1368 .array_u8_sentinel_0,1557 .array_u8_sentinel_0,
1558 .pointer,
1369 .single_const_pointer,1559 .single_const_pointer,
1370 .single_mut_pointer,1560 .single_mut_pointer,
1561 .many_const_pointer,
1562 .many_mut_pointer,
1563 .c_const_pointer,
1564 .c_mut_pointer,
1565 .const_slice,
1566 .mut_slice,
1371 .single_const_pointer_to_comptime_int,1567 .single_const_pointer_to_comptime_int,
1372 .const_slice_u8,1568 .const_slice_u8,
1373 .int_unsigned,1569 .int_unsigned,
...@@ -1427,8 +1623,15 @@ pub const Type = extern union {...@@ -1427,8 +1623,15 @@ pub const Type = extern union {
1427 .array_sentinel,1623 .array_sentinel,
1428 .array_u8,1624 .array_u8,
1429 .array_u8_sentinel_0,1625 .array_u8_sentinel_0,
1626 .pointer,
1430 .single_const_pointer,1627 .single_const_pointer,
1431 .single_mut_pointer,1628 .single_mut_pointer,
1629 .many_const_pointer,
1630 .many_mut_pointer,
1631 .c_const_pointer,
1632 .c_mut_pointer,
1633 .const_slice,
1634 .mut_slice,
1432 .single_const_pointer_to_comptime_int,1635 .single_const_pointer_to_comptime_int,
1433 .const_slice_u8,1636 .const_slice_u8,
1434 .int_signed,1637 .int_signed,
...@@ -1488,8 +1691,15 @@ pub const Type = extern union {...@@ -1488,8 +1691,15 @@ pub const Type = extern union {
1488 .array_sentinel,1691 .array_sentinel,
1489 .array_u8,1692 .array_u8,
1490 .array_u8_sentinel_0,1693 .array_u8_sentinel_0,
1694 .pointer,
1491 .single_const_pointer,1695 .single_const_pointer,
1492 .single_mut_pointer,1696 .single_mut_pointer,
1697 .many_const_pointer,
1698 .many_mut_pointer,
1699 .c_const_pointer,
1700 .c_mut_pointer,
1701 .const_slice,
1702 .mut_slice,
1493 .single_const_pointer_to_comptime_int,1703 .single_const_pointer_to_comptime_int,
1494 .const_slice_u8,1704 .const_slice_u8,
1495 .optional,1705 .optional,
...@@ -1547,8 +1757,15 @@ pub const Type = extern union {...@@ -1547,8 +1757,15 @@ pub const Type = extern union {
1547 .array_sentinel,1757 .array_sentinel,
1548 .array_u8,1758 .array_u8,
1549 .array_u8_sentinel_0,1759 .array_u8_sentinel_0,
1760 .pointer,
1550 .single_const_pointer,1761 .single_const_pointer,
1551 .single_mut_pointer,1762 .single_mut_pointer,
1763 .many_const_pointer,
1764 .many_mut_pointer,
1765 .c_const_pointer,
1766 .c_mut_pointer,
1767 .const_slice,
1768 .mut_slice,
1552 .single_const_pointer_to_comptime_int,1769 .single_const_pointer_to_comptime_int,
1553 .const_slice_u8,1770 .const_slice_u8,
1554 .int_unsigned,1771 .int_unsigned,
...@@ -1635,8 +1852,15 @@ pub const Type = extern union {...@@ -1635,8 +1852,15 @@ pub const Type = extern union {
1635 .array_sentinel,1852 .array_sentinel,
1636 .array_u8,1853 .array_u8,
1637 .array_u8_sentinel_0,1854 .array_u8_sentinel_0,
1855 .pointer,
1638 .single_const_pointer,1856 .single_const_pointer,
1639 .single_mut_pointer,1857 .single_mut_pointer,
1858 .many_const_pointer,
1859 .many_mut_pointer,
1860 .c_const_pointer,
1861 .c_mut_pointer,
1862 .const_slice,
1863 .mut_slice,
1640 .single_const_pointer_to_comptime_int,1864 .single_const_pointer_to_comptime_int,
1641 .const_slice_u8,1865 .const_slice_u8,
1642 .u8,1866 .u8,
...@@ -1699,8 +1923,15 @@ pub const Type = extern union {...@@ -1699,8 +1923,15 @@ pub const Type = extern union {
1699 .array_sentinel,1923 .array_sentinel,
1700 .array_u8,1924 .array_u8,
1701 .array_u8_sentinel_0,1925 .array_u8_sentinel_0,
1926 .pointer,
1702 .single_const_pointer,1927 .single_const_pointer,
1703 .single_mut_pointer,1928 .single_mut_pointer,
1929 .many_const_pointer,
1930 .many_mut_pointer,
1931 .c_const_pointer,
1932 .c_mut_pointer,
1933 .const_slice,
1934 .mut_slice,
1704 .single_const_pointer_to_comptime_int,1935 .single_const_pointer_to_comptime_int,
1705 .const_slice_u8,1936 .const_slice_u8,
1706 .u8,1937 .u8,
...@@ -1762,8 +1993,15 @@ pub const Type = extern union {...@@ -1762,8 +1993,15 @@ pub const Type = extern union {
1762 .array_sentinel,1993 .array_sentinel,
1763 .array_u8,1994 .array_u8,
1764 .array_u8_sentinel_0,1995 .array_u8_sentinel_0,
1996 .pointer,
1765 .single_const_pointer,1997 .single_const_pointer,
1766 .single_mut_pointer,1998 .single_mut_pointer,
1999 .many_const_pointer,
2000 .many_mut_pointer,
2001 .c_const_pointer,
2002 .c_mut_pointer,
2003 .const_slice,
2004 .mut_slice,
1767 .single_const_pointer_to_comptime_int,2005 .single_const_pointer_to_comptime_int,
1768 .const_slice_u8,2006 .const_slice_u8,
1769 .u8,2007 .u8,
...@@ -1825,8 +2063,15 @@ pub const Type = extern union {...@@ -1825,8 +2063,15 @@ pub const Type = extern union {
1825 .array_sentinel,2063 .array_sentinel,
1826 .array_u8,2064 .array_u8,
1827 .array_u8_sentinel_0,2065 .array_u8_sentinel_0,
2066 .pointer,
1828 .single_const_pointer,2067 .single_const_pointer,
1829 .single_mut_pointer,2068 .single_mut_pointer,
2069 .many_const_pointer,
2070 .many_mut_pointer,
2071 .c_const_pointer,
2072 .c_mut_pointer,
2073 .const_slice,
2074 .mut_slice,
1830 .single_const_pointer_to_comptime_int,2075 .single_const_pointer_to_comptime_int,
1831 .const_slice_u8,2076 .const_slice_u8,
1832 .u8,2077 .u8,
...@@ -1885,8 +2130,15 @@ pub const Type = extern union {...@@ -1885,8 +2130,15 @@ pub const Type = extern union {
1885 .array_sentinel,2130 .array_sentinel,
1886 .array_u8,2131 .array_u8,
1887 .array_u8_sentinel_0,2132 .array_u8_sentinel_0,
2133 .pointer,
1888 .single_const_pointer,2134 .single_const_pointer,
1889 .single_mut_pointer,2135 .single_mut_pointer,
2136 .many_const_pointer,
2137 .many_mut_pointer,
2138 .c_const_pointer,
2139 .c_mut_pointer,
2140 .const_slice,
2141 .mut_slice,
1890 .single_const_pointer_to_comptime_int,2142 .single_const_pointer_to_comptime_int,
1891 .const_slice_u8,2143 .const_slice_u8,
1892 .u8,2144 .u8,
...@@ -1945,8 +2197,15 @@ pub const Type = extern union {...@@ -1945,8 +2197,15 @@ pub const Type = extern union {
1945 .array_sentinel,2197 .array_sentinel,
1946 .array_u8,2198 .array_u8,
1947 .array_u8_sentinel_0,2199 .array_u8_sentinel_0,
2200 .pointer,
1948 .single_const_pointer,2201 .single_const_pointer,
1949 .single_mut_pointer,2202 .single_mut_pointer,
2203 .many_const_pointer,
2204 .many_mut_pointer,
2205 .c_const_pointer,
2206 .c_mut_pointer,
2207 .const_slice,
2208 .mut_slice,
1950 .single_const_pointer_to_comptime_int,2209 .single_const_pointer_to_comptime_int,
1951 .const_slice_u8,2210 .const_slice_u8,
1952 .u8,2211 .u8,
...@@ -2025,8 +2284,15 @@ pub const Type = extern union {...@@ -2025,8 +2284,15 @@ pub const Type = extern union {
2025 .array_sentinel,2284 .array_sentinel,
2026 .array_u8,2285 .array_u8,
2027 .array_u8_sentinel_0,2286 .array_u8_sentinel_0,
2287 .pointer,
2028 .single_const_pointer,2288 .single_const_pointer,
2029 .single_mut_pointer,2289 .single_mut_pointer,
2290 .many_const_pointer,
2291 .many_mut_pointer,
2292 .c_const_pointer,
2293 .c_mut_pointer,
2294 .const_slice,
2295 .mut_slice,
2030 .single_const_pointer_to_comptime_int,2296 .single_const_pointer_to_comptime_int,
2031 .const_slice_u8,2297 .const_slice_u8,
2032 .optional,2298 .optional,
...@@ -2077,6 +2343,8 @@ pub const Type = extern union {...@@ -2077,6 +2343,8 @@ pub const Type = extern union {
2077 .array_sentinel,2343 .array_sentinel,
2078 .array_u8_sentinel_0,2344 .array_u8_sentinel_0,
2079 .const_slice_u8,2345 .const_slice_u8,
2346 .const_slice,
2347 .mut_slice,
2080 .c_void,2348 .c_void,
2081 .optional,2349 .optional,
2082 .optional_single_mut_pointer,2350 .optional_single_mut_pointer,
...@@ -2109,11 +2377,21 @@ pub const Type = extern union {...@@ -2109,11 +2377,21 @@ pub const Type = extern union {
2109 ty = ty.elemType();2377 ty = ty.elemType();
2110 continue;2378 continue;
2111 },2379 },
2112 .single_const_pointer, .single_mut_pointer => {2380 .many_const_pointer,
2381 .many_mut_pointer,
2382 .c_const_pointer,
2383 .c_mut_pointer,
2384 .single_const_pointer,
2385 .single_mut_pointer,
2386 => {
2113 const ptr = ty.castPointer().?;2387 const ptr = ty.castPointer().?;
2114 ty = ptr.pointee_type;2388 ty = ptr.pointee_type;
2115 continue;2389 continue;
2116 },2390 },
2391 .pointer => {
2392 ty = ty.cast(Payload.Pointer).?.pointee_type;
2393 continue;
2394 },
2117 };2395 };
2118 }2396 }
21192397
...@@ -2167,11 +2445,21 @@ pub const Type = extern union {...@@ -2167,11 +2445,21 @@ pub const Type = extern union {
2167 .array_u8_sentinel_0,2445 .array_u8_sentinel_0,
2168 .single_const_pointer,2446 .single_const_pointer,
2169 .single_mut_pointer,2447 .single_mut_pointer,
2448 .many_const_pointer,
2449 .many_mut_pointer,
2450 .const_slice,
2451 .mut_slice,
2170 .optional,2452 .optional,
2171 .optional_single_mut_pointer,2453 .optional_single_mut_pointer,
2172 .optional_single_const_pointer,2454 .optional_single_const_pointer,
2173 .enum_literal,2455 .enum_literal,
2174 => return false,2456 => return false,
2457
2458 .c_const_pointer,
2459 .c_mut_pointer,
2460 => return true,
2461
2462 .pointer => self.cast(Payload.Pointer).?.size == .C,
2175 };2463 };
2176 }2464 }
21772465
...@@ -2229,8 +2517,15 @@ pub const Type = extern union {...@@ -2229,8 +2517,15 @@ pub const Type = extern union {
2229 array_u8_sentinel_0,2517 array_u8_sentinel_0,
2230 array,2518 array,
2231 array_sentinel,2519 array_sentinel,
2520 pointer,
2232 single_const_pointer,2521 single_const_pointer,
2233 single_mut_pointer,2522 single_mut_pointer,
2523 many_const_pointer,
2524 many_mut_pointer,
2525 c_const_pointer,
2526 c_mut_pointer,
2527 const_slice,
2528 mut_slice,
2234 int_signed,2529 int_signed,
2235 int_unsigned,2530 int_unsigned,
2236 function,2531 function,
...@@ -2272,7 +2567,7 @@ pub const Type = extern union {...@@ -2272,7 +2567,7 @@ pub const Type = extern union {
2272 elem_type: Type,2567 elem_type: Type,
2273 };2568 };
22742569
2275 pub const Pointer = struct {2570 pub const PointerSimple = struct {
2276 base: Payload,2571 base: Payload,
22772572
2278 pointee_type: Type,2573 pointee_type: Type,
...@@ -2303,6 +2598,21 @@ pub const Type = extern union {...@@ -2303,6 +2598,21 @@ pub const Type = extern union {
23032598
2304 child_type: Type,2599 child_type: Type,
2305 };2600 };
2601
2602 pub const Pointer = struct {
2603 base: Payload = .{ .tag = .pointer },
2604
2605 pointee_type: Type,
2606 sentinel: ?Value,
2607 /// If zero use pointee_type.AbiAlign()
2608 @"align": u32,
2609 bit_offset: u16,
2610 host_size: u16,
2611 @"allowzero": bool,
2612 mutable: bool,
2613 @"volatile": bool,
2614 size: std.builtin.TypeInfo.Pointer.Size,
2615 };
2306 };2616 };
2307};2617};
23082618
src-self-hosted/zir.zig+29-4
...@@ -194,10 +194,22 @@ pub const Inst = struct {...@@ -194,10 +194,22 @@ pub const Inst = struct {
194 shl,194 shl,
195 /// Integer shift-right. Arithmetic or logical depending on the signedness of the integer type.195 /// Integer shift-right. Arithmetic or logical depending on the signedness of the integer type.
196 shr,196 shr,
197 /// Create a const pointer type based on the element type. `*const T`197 /// Create a const pointer type with element type T. `*const T`
198 single_const_ptr_type,198 single_const_ptr_type,
199 /// Create a mutable pointer type based on the element type. `*T`199 /// Create a mutable pointer type with element type T. `*T`
200 single_mut_ptr_type,200 single_mut_ptr_type,
201 /// Create a const pointer type with element type T. `[*]const T`
202 many_const_ptr_type,
203 /// Create a mutable pointer type with element type T. `[*]T`
204 many_mut_ptr_type,
205 /// Create a const pointer type with element type T. `[*c]const T`
206 c_const_ptr_type,
207 /// Create a mutable pointer type with element type T. `[*c]T`
208 c_mut_ptr_type,
209 /// Create a mutable slice type with element type T. `[]T`
210 mut_slice_type,
211 /// Create a const slice type with element type T. `[]T`
212 const_slice_type,
201 /// Create a pointer type with attributes213 /// Create a pointer type with attributes
202 ptr_type,214 ptr_type,
203 /// Write a value to a pointer. For loading, see `deref`.215 /// Write a value to a pointer. For loading, see `deref`.
...@@ -262,6 +274,12 @@ pub const Inst = struct {...@@ -262,6 +274,12 @@ pub const Inst = struct {
262 .typeof,274 .typeof,
263 .single_const_ptr_type,275 .single_const_ptr_type,
264 .single_mut_ptr_type,276 .single_mut_ptr_type,
277 .many_const_ptr_type,
278 .many_mut_ptr_type,
279 .c_const_ptr_type,
280 .c_mut_ptr_type,
281 .mut_slice_type,
282 .const_slice_type,
265 .optional_type,283 .optional_type,
266 .unwrap_optional_safe,284 .unwrap_optional_safe,
267 .unwrap_optional_unsafe,285 .unwrap_optional_unsafe,
...@@ -400,6 +418,12 @@ pub const Inst = struct {...@@ -400,6 +418,12 @@ pub const Inst = struct {
400 .shr,418 .shr,
401 .single_const_ptr_type,419 .single_const_ptr_type,
402 .single_mut_ptr_type,420 .single_mut_ptr_type,
421 .many_const_ptr_type,
422 .many_mut_ptr_type,
423 .c_const_ptr_type,
424 .c_mut_ptr_type,
425 .mut_slice_type,
426 .const_slice_type,
403 .store,427 .store,
404 .str,428 .str,
405 .sub,429 .sub,
...@@ -856,9 +880,10 @@ pub const Inst = struct {...@@ -856,9 +880,10 @@ pub const Inst = struct {
856 @"align": ?*Inst = null,880 @"align": ?*Inst = null,
857 align_bit_start: ?*Inst = null,881 align_bit_start: ?*Inst = null,
858 align_bit_end: ?*Inst = null,882 align_bit_end: ?*Inst = null,
859 @"const": bool = true,883 mutable: bool = true,
860 @"volatile": bool = false,884 @"volatile": bool = false,
861 sentinel: ?*Inst = null,885 sentinel: ?*Inst = null,
886 size: std.builtin.TypeInfo.Pointer.Size = .One,
862 },887 },
863 };888 };
864889
...@@ -2443,7 +2468,7 @@ const EmitZIR = struct {...@@ -2443,7 +2468,7 @@ const EmitZIR = struct {
2443 }2468 }
2444 },2469 },
2445 .Optional => {2470 .Optional => {
2446 var buf: Type.Payload.Pointer = undefined;2471 var buf: Type.Payload.PointerSimple = undefined;
2447 const inst = try self.arena.allocator.create(Inst.UnOp);2472 const inst = try self.arena.allocator.create(Inst.UnOp);
2448 inst.* = .{2473 inst.* = .{
2449 .base = .{2474 .base = .{
src-self-hosted/zir_sema.zig+60-15
...@@ -51,8 +51,14 @@ pub fn analyzeInst(mod: *Module, scope: *Scope, old_inst: *zir.Inst) InnerError!...@@ -51,8 +51,14 @@ pub fn analyzeInst(mod: *Module, scope: *Scope, old_inst: *zir.Inst) InnerError!
51 .ref => return analyzeInstRef(mod, scope, old_inst.castTag(.ref).?),51 .ref => return analyzeInstRef(mod, scope, old_inst.castTag(.ref).?),
52 .ret_ptr => return analyzeInstRetPtr(mod, scope, old_inst.castTag(.ret_ptr).?),52 .ret_ptr => return analyzeInstRetPtr(mod, scope, old_inst.castTag(.ret_ptr).?),
53 .ret_type => return analyzeInstRetType(mod, scope, old_inst.castTag(.ret_type).?),53 .ret_type => return analyzeInstRetType(mod, scope, old_inst.castTag(.ret_type).?),
54 .single_const_ptr_type => return analyzeInstSingleConstPtrType(mod, scope, old_inst.castTag(.single_const_ptr_type).?),54 .single_const_ptr_type => return analyzeInstSimplePtrType(mod, scope, old_inst.castTag(.single_const_ptr_type).?, false, .One),
55 .single_mut_ptr_type => return analyzeInstSingleMutPtrType(mod, scope, old_inst.castTag(.single_mut_ptr_type).?),55 .single_mut_ptr_type => return analyzeInstSimplePtrType(mod, scope, old_inst.castTag(.single_mut_ptr_type).?, true, .One),
56 .many_const_ptr_type => return analyzeInstSimplePtrType(mod, scope, old_inst.castTag(.many_const_ptr_type).?, false, .Many),
57 .many_mut_ptr_type => return analyzeInstSimplePtrType(mod, scope, old_inst.castTag(.many_mut_ptr_type).?, true, .Many),
58 .c_const_ptr_type => return analyzeInstSimplePtrType(mod, scope, old_inst.castTag(.c_const_ptr_type).?, false, .C),
59 .c_mut_ptr_type => return analyzeInstSimplePtrType(mod, scope, old_inst.castTag(.c_mut_ptr_type).?, true, .C),
60 .const_slice_type => return analyzeInstSimplePtrType(mod, scope, old_inst.castTag(.const_slice_type).?, false, .Slice),
61 .mut_slice_type => return analyzeInstSimplePtrType(mod, scope, old_inst.castTag(.mut_slice_type).?, true, .Slice),
56 .ptr_type => return analyzeInstPtrType(mod, scope, old_inst.castTag(.ptr_type).?),62 .ptr_type => return analyzeInstPtrType(mod, scope, old_inst.castTag(.ptr_type).?),
57 .store => return analyzeInstStore(mod, scope, old_inst.castTag(.store).?),63 .store => return analyzeInstStore(mod, scope, old_inst.castTag(.store).?),
58 .str => return analyzeInstStr(mod, scope, old_inst.castTag(.str).?),64 .str => return analyzeInstStr(mod, scope, old_inst.castTag(.str).?),
...@@ -267,6 +273,14 @@ fn resolveType(mod: *Module, scope: *Scope, old_inst: *zir.Inst) !Type {...@@ -267,6 +273,14 @@ fn resolveType(mod: *Module, scope: *Scope, old_inst: *zir.Inst) !Type {
267 return val.toType();273 return val.toType();
268}274}
269275
276fn resolveInt(mod: *Module, scope: *Scope, old_inst: *zir.Inst, dest_type: Type) !u64 {
277 const new_inst = try resolveInst(mod, scope, old_inst);
278 const coerced = try mod.coerce(scope, dest_type, new_inst);
279 const val = try mod.resolveConstValue(scope, coerced);
280
281 return val.toUnsignedInt();
282}
283
270pub fn resolveInstConst(mod: *Module, scope: *Scope, old_inst: *zir.Inst) InnerError!TypedValue {284pub fn resolveInstConst(mod: *Module, scope: *Scope, old_inst: *zir.Inst) InnerError!TypedValue {
271 const new_inst = try resolveInst(mod, scope, old_inst);285 const new_inst = try resolveInst(mod, scope, old_inst);
272 const val = try mod.resolveConstValue(scope, new_inst);286 const val = try mod.resolveConstValue(scope, new_inst);
...@@ -324,7 +338,7 @@ fn analyzeInstRetPtr(mod: *Module, scope: *Scope, inst: *zir.Inst.NoOp) InnerErr...@@ -324,7 +338,7 @@ fn analyzeInstRetPtr(mod: *Module, scope: *Scope, inst: *zir.Inst.NoOp) InnerErr
324338
325fn analyzeInstRef(mod: *Module, scope: *Scope, inst: *zir.Inst.UnOp) InnerError!*Inst {339fn analyzeInstRef(mod: *Module, scope: *Scope, inst: *zir.Inst.UnOp) InnerError!*Inst {
326 const operand = try resolveInst(mod, scope, inst.positionals.operand);340 const operand = try resolveInst(mod, scope, inst.positionals.operand);
327 const ptr_type = try mod.singlePtrType(scope, inst.base.src, false, operand.ty);341 const ptr_type = try mod.simplePtrType(scope, inst.base.src, operand.ty, false, .One);
328342
329 if (operand.value()) |val| {343 if (operand.value()) |val| {
330 const ref_payload = try scope.arena().create(Value.Payload.RefVal);344 const ref_payload = try scope.arena().create(Value.Payload.RefVal);
...@@ -369,7 +383,7 @@ fn analyzeInstAlloc(mod: *Module, scope: *Scope, inst: *zir.Inst.UnOp) InnerErro...@@ -369,7 +383,7 @@ fn analyzeInstAlloc(mod: *Module, scope: *Scope, inst: *zir.Inst.UnOp) InnerErro
369 if (!var_type.isValidVarType(false)) {383 if (!var_type.isValidVarType(false)) {
370 return mod.fail(scope, inst.base.src, "variable of type '{}' must be const or comptime", .{var_type});384 return mod.fail(scope, inst.base.src, "variable of type '{}' must be const or comptime", .{var_type});
371 }385 }
372 const ptr_type = try mod.singlePtrType(scope, inst.base.src, true, var_type);386 const ptr_type = try mod.simplePtrType(scope, inst.base.src, var_type, true, .One);
373 const b = try mod.requireRuntimeBlock(scope, inst.base.src);387 const b = try mod.requireRuntimeBlock(scope, inst.base.src);
374 return mod.addNoOp(b, inst.base.src, ptr_type, .alloc);388 return mod.addNoOp(b, inst.base.src, ptr_type, .alloc);
375}389}
...@@ -723,7 +737,7 @@ fn analyzeInstUnwrapOptional(mod: *Module, scope: *Scope, unwrap: *zir.Inst.UnOp...@@ -723,7 +737,7 @@ fn analyzeInstUnwrapOptional(mod: *Module, scope: *Scope, unwrap: *zir.Inst.UnOp
723 }737 }
724738
725 const child_type = try operand.ty.elemType().optionalChildAlloc(scope.arena());739 const child_type = try operand.ty.elemType().optionalChildAlloc(scope.arena());
726 const child_pointer = try mod.singlePtrType(scope, unwrap.base.src, operand.ty.isConstPtr(), child_type);740 const child_pointer = try mod.simplePtrType(scope, unwrap.base.src, child_type, operand.ty.isConstPtr(), .One);
727741
728 if (operand.value()) |val| {742 if (operand.value()) |val| {
729 if (val.isNull()) {743 if (val.isNull()) {
...@@ -940,7 +954,7 @@ fn analyzeInstElemPtr(mod: *Module, scope: *Scope, inst: *zir.Inst.ElemPtr) Inne...@@ -940,7 +954,7 @@ fn analyzeInstElemPtr(mod: *Module, scope: *Scope, inst: *zir.Inst.ElemPtr) Inne
940 // required a larger index.954 // required a larger index.
941 const elem_ptr = try array_ptr_val.elemPtr(scope.arena(), @intCast(usize, index_u64));955 const elem_ptr = try array_ptr_val.elemPtr(scope.arena(), @intCast(usize, index_u64));
942956
943 const type_payload = try scope.arena().create(Type.Payload.Pointer);957 const type_payload = try scope.arena().create(Type.Payload.PointerSimple);
944 type_payload.* = .{958 type_payload.* = .{
945 .base = .{ .tag = .single_const_pointer },959 .base = .{ .tag = .single_const_pointer },
946 .pointee_type = array_ptr.ty.elemType().elemType(),960 .pointee_type = array_ptr.ty.elemType().elemType(),
...@@ -1311,18 +1325,49 @@ fn analyzeDeclVal(mod: *Module, scope: *Scope, inst: *zir.Inst.DeclVal) InnerErr...@@ -1311,18 +1325,49 @@ fn analyzeDeclVal(mod: *Module, scope: *Scope, inst: *zir.Inst.DeclVal) InnerErr
1311 return decl;1325 return decl;
1312}1326}
13131327
1314fn analyzeInstSingleConstPtrType(mod: *Module, scope: *Scope, inst: *zir.Inst.UnOp) InnerError!*Inst {1328fn analyzeInstSimplePtrType(mod: *Module, scope: *Scope, inst: *zir.Inst.UnOp, mutable: bool, size: std.builtin.TypeInfo.Pointer.Size) InnerError!*Inst {
1315 const elem_type = try resolveType(mod, scope, inst.positionals.operand);
1316 const ty = try mod.singlePtrType(scope, inst.base.src, false, elem_type);
1317 return mod.constType(scope, inst.base.src, ty);
1318}
1319
1320fn analyzeInstSingleMutPtrType(mod: *Module, scope: *Scope, inst: *zir.Inst.UnOp) InnerError!*Inst {
1321 const elem_type = try resolveType(mod, scope, inst.positionals.operand);1329 const elem_type = try resolveType(mod, scope, inst.positionals.operand);
1322 const ty = try mod.singlePtrType(scope, inst.base.src, true, elem_type);1330 const ty = try mod.simplePtrType(scope, inst.base.src, elem_type, mutable, size);
1323 return mod.constType(scope, inst.base.src, ty);1331 return mod.constType(scope, inst.base.src, ty);
1324}1332}
13251333
1326fn analyzeInstPtrType(mod: *Module, scope: *Scope, inst: *zir.Inst.PtrType) InnerError!*Inst {1334fn analyzeInstPtrType(mod: *Module, scope: *Scope, inst: *zir.Inst.PtrType) InnerError!*Inst {
1327 return mod.fail(scope, inst.base.src, "TODO implement ptr_type", .{});1335 // TODO lazy values
1336 const @"align" = if (inst.kw_args.@"align") |some|
1337 @truncate(u32, try resolveInt(mod, scope, some, Type.initTag(.u32)))
1338 else
1339 0;
1340 const bit_offset = if (inst.kw_args.align_bit_start) |some|
1341 @truncate(u16, try resolveInt(mod, scope, some, Type.initTag(.u16)))
1342 else
1343 0;
1344 const host_size = if (inst.kw_args.align_bit_end) |some|
1345 @truncate(u16, try resolveInt(mod, scope, some, Type.initTag(.u16)))
1346 else
1347 0;
1348
1349 if (host_size != 0 and bit_offset >= host_size * 8)
1350 return mod.fail(scope, inst.base.src, "bit offset starts after end of host integer", .{});
1351
1352 const sentinel = if (inst.kw_args.sentinel) |some|
1353 (try resolveInstConst(mod, scope, some)).val
1354 else
1355 null;
1356
1357 const elem_type = try resolveType(mod, scope, inst.positionals.child_type);
1358
1359 const ty = try mod.ptrType(
1360 scope,
1361 inst.base.src,
1362 elem_type,
1363 sentinel,
1364 @"align",
1365 bit_offset,
1366 host_size,
1367 inst.kw_args.mutable,
1368 inst.kw_args.@"allowzero",
1369 inst.kw_args.@"volatile",
1370 inst.kw_args.size,
1371 );
1372 return mod.constType(scope, inst.base.src, ty);
1328}1373}
test/stage2/compare_output.zig deleted-710
...@@ -1,710 +0,0 @@
1const std = @import("std");
2const TestContext = @import("../../src-self-hosted/test.zig").TestContext;
3// self-hosted does not yet support PE executable files / COFF object files
4// or mach-o files. So we do these test cases cross compiling for x86_64-linux.
5const linux_x64 = std.zig.CrossTarget{
6 .cpu_arch = .x86_64,
7 .os_tag = .linux,
8};
9
10const linux_riscv64 = std.zig.CrossTarget{
11 .cpu_arch = .riscv64,
12 .os_tag = .linux,
13};
14
15const wasi = std.zig.CrossTarget{
16 .cpu_arch = .wasm32,
17 .os_tag = .wasi,
18};
19
20pub fn addCases(ctx: *TestContext) !void {
21 {
22 var case = ctx.exe("hello world with updates", linux_x64);
23
24 case.addError("", &[_][]const u8{":1:1: error: no entry point found"});
25
26 case.addError(
27 \\export fn _start() noreturn {
28 \\}
29 , &[_][]const u8{":2:1: error: expected noreturn, found void"});
30
31 // Regular old hello world
32 case.addCompareOutput(
33 \\export fn _start() noreturn {
34 \\ print();
35 \\
36 \\ exit();
37 \\}
38 \\
39 \\fn print() void {
40 \\ asm volatile ("syscall"
41 \\ :
42 \\ : [number] "{rax}" (1),
43 \\ [arg1] "{rdi}" (1),
44 \\ [arg2] "{rsi}" (@ptrToInt("Hello, World!\n")),
45 \\ [arg3] "{rdx}" (14)
46 \\ : "rcx", "r11", "memory"
47 \\ );
48 \\ return;
49 \\}
50 \\
51 \\fn exit() noreturn {
52 \\ asm volatile ("syscall"
53 \\ :
54 \\ : [number] "{rax}" (231),
55 \\ [arg1] "{rdi}" (0)
56 \\ : "rcx", "r11", "memory"
57 \\ );
58 \\ unreachable;
59 \\}
60 ,
61 "Hello, World!\n",
62 );
63 // Now change the message only
64 case.addCompareOutput(
65 \\export fn _start() noreturn {
66 \\ print();
67 \\
68 \\ exit();
69 \\}
70 \\
71 \\fn print() void {
72 \\ asm volatile ("syscall"
73 \\ :
74 \\ : [number] "{rax}" (1),
75 \\ [arg1] "{rdi}" (1),
76 \\ [arg2] "{rsi}" (@ptrToInt("What is up? This is a longer message that will force the data to be relocated in virtual address space.\n")),
77 \\ [arg3] "{rdx}" (104)
78 \\ : "rcx", "r11", "memory"
79 \\ );
80 \\ return;
81 \\}
82 \\
83 \\fn exit() noreturn {
84 \\ asm volatile ("syscall"
85 \\ :
86 \\ : [number] "{rax}" (231),
87 \\ [arg1] "{rdi}" (0)
88 \\ : "rcx", "r11", "memory"
89 \\ );
90 \\ unreachable;
91 \\}
92 ,
93 "What is up? This is a longer message that will force the data to be relocated in virtual address space.\n",
94 );
95 // Now we print it twice.
96 case.addCompareOutput(
97 \\export fn _start() noreturn {
98 \\ print();
99 \\ print();
100 \\
101 \\ exit();
102 \\}
103 \\
104 \\fn print() void {
105 \\ asm volatile ("syscall"
106 \\ :
107 \\ : [number] "{rax}" (1),
108 \\ [arg1] "{rdi}" (1),
109 \\ [arg2] "{rsi}" (@ptrToInt("What is up? This is a longer message that will force the data to be relocated in virtual address space.\n")),
110 \\ [arg3] "{rdx}" (104)
111 \\ : "rcx", "r11", "memory"
112 \\ );
113 \\ return;
114 \\}
115 \\
116 \\fn exit() noreturn {
117 \\ asm volatile ("syscall"
118 \\ :
119 \\ : [number] "{rax}" (231),
120 \\ [arg1] "{rdi}" (0)
121 \\ : "rcx", "r11", "memory"
122 \\ );
123 \\ unreachable;
124 \\}
125 ,
126 \\What is up? This is a longer message that will force the data to be relocated in virtual address space.
127 \\What is up? This is a longer message that will force the data to be relocated in virtual address space.
128 \\
129 );
130 }
131
132 {
133 var case = ctx.exe("hello world", linux_riscv64);
134 // Regular old hello world
135 case.addCompareOutput(
136 \\export fn _start() noreturn {
137 \\ print();
138 \\
139 \\ exit();
140 \\}
141 \\
142 \\fn print() void {
143 \\ asm volatile ("ecall"
144 \\ :
145 \\ : [number] "{a7}" (64),
146 \\ [arg1] "{a0}" (1),
147 \\ [arg2] "{a1}" (@ptrToInt("Hello, World!\n")),
148 \\ [arg3] "{a2}" ("Hello, World!\n".len)
149 \\ : "rcx", "r11", "memory"
150 \\ );
151 \\ return;
152 \\}
153 \\
154 \\fn exit() noreturn {
155 \\ asm volatile ("ecall"
156 \\ :
157 \\ : [number] "{a7}" (94),
158 \\ [arg1] "{a0}" (0)
159 \\ : "rcx", "r11", "memory"
160 \\ );
161 \\ unreachable;
162 \\}
163 ,
164 "Hello, World!\n",
165 );
166 }
167
168 {
169 var case = ctx.exe("adding numbers at comptime", linux_x64);
170 case.addCompareOutput(
171 \\export fn _start() noreturn {
172 \\ asm volatile ("syscall"
173 \\ :
174 \\ : [number] "{rax}" (1),
175 \\ [arg1] "{rdi}" (1),
176 \\ [arg2] "{rsi}" (@ptrToInt("Hello, World!\n")),
177 \\ [arg3] "{rdx}" (10 + 4)
178 \\ : "rcx", "r11", "memory"
179 \\ );
180 \\ asm volatile ("syscall"
181 \\ :
182 \\ : [number] "{rax}" (@as(usize, 230) + @as(usize, 1)),
183 \\ [arg1] "{rdi}" (0)
184 \\ : "rcx", "r11", "memory"
185 \\ );
186 \\ unreachable;
187 \\}
188 ,
189 "Hello, World!\n",
190 );
191 }
192
193 {
194 var case = ctx.exe("adding numbers at runtime", linux_x64);
195 case.addCompareOutput(
196 \\export fn _start() noreturn {
197 \\ add(3, 4);
198 \\
199 \\ exit();
200 \\}
201 \\
202 \\fn add(a: u32, b: u32) void {
203 \\ if (a + b != 7) unreachable;
204 \\}
205 \\
206 \\fn exit() noreturn {
207 \\ asm volatile ("syscall"
208 \\ :
209 \\ : [number] "{rax}" (231),
210 \\ [arg1] "{rdi}" (0)
211 \\ : "rcx", "r11", "memory"
212 \\ );
213 \\ unreachable;
214 \\}
215 ,
216 "",
217 );
218 }
219
220 {
221 var case = ctx.exe("substracting numbers at runtime", linux_x64);
222 case.addCompareOutput(
223 \\export fn _start() noreturn {
224 \\ sub(7, 4);
225 \\
226 \\ exit();
227 \\}
228 \\
229 \\fn sub(a: u32, b: u32) void {
230 \\ if (a - b != 3) unreachable;
231 \\}
232 \\
233 \\fn exit() noreturn {
234 \\ asm volatile ("syscall"
235 \\ :
236 \\ : [number] "{rax}" (231),
237 \\ [arg1] "{rdi}" (0)
238 \\ : "rcx", "r11", "memory"
239 \\ );
240 \\ unreachable;
241 \\}
242 ,
243 "",
244 );
245 }
246
247 {
248 var case = ctx.exe("assert function", linux_x64);
249 case.addCompareOutput(
250 \\export fn _start() noreturn {
251 \\ add(3, 4);
252 \\
253 \\ exit();
254 \\}
255 \\
256 \\fn add(a: u32, b: u32) void {
257 \\ assert(a + b == 7);
258 \\}
259 \\
260 \\pub fn assert(ok: bool) void {
261 \\ if (!ok) unreachable; // assertion failure
262 \\}
263 \\
264 \\fn exit() noreturn {
265 \\ asm volatile ("syscall"
266 \\ :
267 \\ : [number] "{rax}" (231),
268 \\ [arg1] "{rdi}" (0)
269 \\ : "rcx", "r11", "memory"
270 \\ );
271 \\ unreachable;
272 \\}
273 ,
274 "",
275 );
276
277 // Tests copying a register. For the `c = a + b`, it has to
278 // preserve both a and b, because they are both used later.
279 case.addCompareOutput(
280 \\export fn _start() noreturn {
281 \\ add(3, 4);
282 \\
283 \\ exit();
284 \\}
285 \\
286 \\fn add(a: u32, b: u32) void {
287 \\ const c = a + b; // 7
288 \\ const d = a + c; // 10
289 \\ const e = d + b; // 14
290 \\ assert(e == 14);
291 \\}
292 \\
293 \\pub fn assert(ok: bool) void {
294 \\ if (!ok) unreachable; // assertion failure
295 \\}
296 \\
297 \\fn exit() noreturn {
298 \\ asm volatile ("syscall"
299 \\ :
300 \\ : [number] "{rax}" (231),
301 \\ [arg1] "{rdi}" (0)
302 \\ : "rcx", "r11", "memory"
303 \\ );
304 \\ unreachable;
305 \\}
306 ,
307 "",
308 );
309
310 // More stress on the liveness detection.
311 case.addCompareOutput(
312 \\export fn _start() noreturn {
313 \\ add(3, 4);
314 \\
315 \\ exit();
316 \\}
317 \\
318 \\fn add(a: u32, b: u32) void {
319 \\ const c = a + b; // 7
320 \\ const d = a + c; // 10
321 \\ const e = d + b; // 14
322 \\ const f = d + e; // 24
323 \\ const g = e + f; // 38
324 \\ const h = f + g; // 62
325 \\ const i = g + h; // 100
326 \\ assert(i == 100);
327 \\}
328 \\
329 \\pub fn assert(ok: bool) void {
330 \\ if (!ok) unreachable; // assertion failure
331 \\}
332 \\
333 \\fn exit() noreturn {
334 \\ asm volatile ("syscall"
335 \\ :
336 \\ : [number] "{rax}" (231),
337 \\ [arg1] "{rdi}" (0)
338 \\ : "rcx", "r11", "memory"
339 \\ );
340 \\ unreachable;
341 \\}
342 ,
343 "",
344 );
345
346 // Requires a second move. The register allocator should figure out to re-use rax.
347 case.addCompareOutput(
348 \\export fn _start() noreturn {
349 \\ add(3, 4);
350 \\
351 \\ exit();
352 \\}
353 \\
354 \\fn add(a: u32, b: u32) void {
355 \\ const c = a + b; // 7
356 \\ const d = a + c; // 10
357 \\ const e = d + b; // 14
358 \\ const f = d + e; // 24
359 \\ const g = e + f; // 38
360 \\ const h = f + g; // 62
361 \\ const i = g + h; // 100
362 \\ const j = i + d; // 110
363 \\ assert(j == 110);
364 \\}
365 \\
366 \\pub fn assert(ok: bool) void {
367 \\ if (!ok) unreachable; // assertion failure
368 \\}
369 \\
370 \\fn exit() noreturn {
371 \\ asm volatile ("syscall"
372 \\ :
373 \\ : [number] "{rax}" (231),
374 \\ [arg1] "{rdi}" (0)
375 \\ : "rcx", "r11", "memory"
376 \\ );
377 \\ unreachable;
378 \\}
379 ,
380 "",
381 );
382
383 // Now we test integer return values.
384 case.addCompareOutput(
385 \\export fn _start() noreturn {
386 \\ assert(add(3, 4) == 7);
387 \\ assert(add(20, 10) == 30);
388 \\
389 \\ exit();
390 \\}
391 \\
392 \\fn add(a: u32, b: u32) u32 {
393 \\ return a + b;
394 \\}
395 \\
396 \\pub fn assert(ok: bool) void {
397 \\ if (!ok) unreachable; // assertion failure
398 \\}
399 \\
400 \\fn exit() noreturn {
401 \\ asm volatile ("syscall"
402 \\ :
403 \\ : [number] "{rax}" (231),
404 \\ [arg1] "{rdi}" (0)
405 \\ : "rcx", "r11", "memory"
406 \\ );
407 \\ unreachable;
408 \\}
409 ,
410 "",
411 );
412
413 // Local mutable variables.
414 case.addCompareOutput(
415 \\export fn _start() noreturn {
416 \\ assert(add(3, 4) == 7);
417 \\ assert(add(20, 10) == 30);
418 \\
419 \\ exit();
420 \\}
421 \\
422 \\fn add(a: u32, b: u32) u32 {
423 \\ var x: u32 = undefined;
424 \\ x = 0;
425 \\ x += a;
426 \\ x += b;
427 \\ return x;
428 \\}
429 \\
430 \\pub fn assert(ok: bool) void {
431 \\ if (!ok) unreachable; // assertion failure
432 \\}
433 \\
434 \\fn exit() noreturn {
435 \\ asm volatile ("syscall"
436 \\ :
437 \\ : [number] "{rax}" (231),
438 \\ [arg1] "{rdi}" (0)
439 \\ : "rcx", "r11", "memory"
440 \\ );
441 \\ unreachable;
442 \\}
443 ,
444 "",
445 );
446
447 // Optionals
448 case.addCompareOutput(
449 \\export fn _start() noreturn {
450 \\ const a: u32 = 2;
451 \\ const b: ?u32 = a;
452 \\ const c = b.?;
453 \\ if (c != 2) unreachable;
454 \\
455 \\ exit();
456 \\}
457 \\
458 \\fn exit() noreturn {
459 \\ asm volatile ("syscall"
460 \\ :
461 \\ : [number] "{rax}" (231),
462 \\ [arg1] "{rdi}" (0)
463 \\ : "rcx", "r11", "memory"
464 \\ );
465 \\ unreachable;
466 \\}
467 ,
468 "",
469 );
470
471 // While loops
472 case.addCompareOutput(
473 \\export fn _start() noreturn {
474 \\ var i: u32 = 0;
475 \\ while (i < 4) : (i += 1) print();
476 \\ assert(i == 4);
477 \\
478 \\ exit();
479 \\}
480 \\
481 \\fn print() void {
482 \\ asm volatile ("syscall"
483 \\ :
484 \\ : [number] "{rax}" (1),
485 \\ [arg1] "{rdi}" (1),
486 \\ [arg2] "{rsi}" (@ptrToInt("hello\n")),
487 \\ [arg3] "{rdx}" (6)
488 \\ : "rcx", "r11", "memory"
489 \\ );
490 \\ return;
491 \\}
492 \\
493 \\pub fn assert(ok: bool) void {
494 \\ if (!ok) unreachable; // assertion failure
495 \\}
496 \\
497 \\fn exit() noreturn {
498 \\ asm volatile ("syscall"
499 \\ :
500 \\ : [number] "{rax}" (231),
501 \\ [arg1] "{rdi}" (0)
502 \\ : "rcx", "r11", "memory"
503 \\ );
504 \\ unreachable;
505 \\}
506 ,
507 "hello\nhello\nhello\nhello\n",
508 );
509
510 // Labeled blocks (no conditional branch)
511 case.addCompareOutput(
512 \\export fn _start() noreturn {
513 \\ assert(add(3, 4) == 20);
514 \\
515 \\ exit();
516 \\}
517 \\
518 \\fn add(a: u32, b: u32) u32 {
519 \\ const x: u32 = blk: {
520 \\ const c = a + b; // 7
521 \\ const d = a + c; // 10
522 \\ const e = d + b; // 14
523 \\ break :blk e;
524 \\ };
525 \\ const y = x + a; // 17
526 \\ const z = y + a; // 20
527 \\ return z;
528 \\}
529 \\
530 \\pub fn assert(ok: bool) void {
531 \\ if (!ok) unreachable; // assertion failure
532 \\}
533 \\
534 \\fn exit() noreturn {
535 \\ asm volatile ("syscall"
536 \\ :
537 \\ : [number] "{rax}" (231),
538 \\ [arg1] "{rdi}" (0)
539 \\ : "rcx", "r11", "memory"
540 \\ );
541 \\ unreachable;
542 \\}
543 ,
544 "",
545 );
546
547 // This catches a possible bug in the logic for re-using dying operands.
548 case.addCompareOutput(
549 \\export fn _start() noreturn {
550 \\ assert(add(3, 4) == 116);
551 \\
552 \\ exit();
553 \\}
554 \\
555 \\fn add(a: u32, b: u32) u32 {
556 \\ const x: u32 = blk: {
557 \\ const c = a + b; // 7
558 \\ const d = a + c; // 10
559 \\ const e = d + b; // 14
560 \\ const f = d + e; // 24
561 \\ const g = e + f; // 38
562 \\ const h = f + g; // 62
563 \\ const i = g + h; // 100
564 \\ const j = i + d; // 110
565 \\ break :blk j;
566 \\ };
567 \\ const y = x + a; // 113
568 \\ const z = y + a; // 116
569 \\ return z;
570 \\}
571 \\
572 \\pub fn assert(ok: bool) void {
573 \\ if (!ok) unreachable; // assertion failure
574 \\}
575 \\
576 \\fn exit() noreturn {
577 \\ asm volatile ("syscall"
578 \\ :
579 \\ : [number] "{rax}" (231),
580 \\ [arg1] "{rdi}" (0)
581 \\ : "rcx", "r11", "memory"
582 \\ );
583 \\ unreachable;
584 \\}
585 ,
586 "",
587 );
588
589 // Character literals and multiline strings.
590 case.addCompareOutput(
591 \\export fn _start() noreturn {
592 \\ const ignore =
593 \\ \\ cool thx
594 \\ \\
595 \\ ;
596 \\ add('ぁ', '\x03');
597 \\
598 \\ exit();
599 \\}
600 \\
601 \\fn add(a: u32, b: u32) void {
602 \\ assert(a + b == 12356);
603 \\}
604 \\
605 \\pub fn assert(ok: bool) void {
606 \\ if (!ok) unreachable; // assertion failure
607 \\}
608 \\
609 \\fn exit() noreturn {
610 \\ asm volatile ("syscall"
611 \\ :
612 \\ : [number] "{rax}" (231),
613 \\ [arg1] "{rdi}" (0)
614 \\ : "rcx", "r11", "memory"
615 \\ );
616 \\ unreachable;
617 \\}
618 ,
619 "",
620 );
621
622 // Global const.
623 case.addCompareOutput(
624 \\export fn _start() noreturn {
625 \\ add(aa, bb);
626 \\
627 \\ exit();
628 \\}
629 \\
630 \\const aa = 'ぁ';
631 \\const bb = '\x03';
632 \\
633 \\fn add(a: u32, b: u32) void {
634 \\ assert(a + b == 12356);
635 \\}
636 \\
637 \\pub fn assert(ok: bool) void {
638 \\ if (!ok) unreachable; // assertion failure
639 \\}
640 \\
641 \\fn exit() noreturn {
642 \\ asm volatile ("syscall"
643 \\ :
644 \\ : [number] "{rax}" (231),
645 \\ [arg1] "{rdi}" (0)
646 \\ : "rcx", "r11", "memory"
647 \\ );
648 \\ unreachable;
649 \\}
650 ,
651 "",
652 );
653 }
654
655 {
656 var case = ctx.exe("wasm function calls", wasi);
657
658 case.addCompareOutput(
659 \\export fn _start() u32 {
660 \\ foo();
661 \\ bar();
662 \\ return 42;
663 \\}
664 \\fn foo() void {
665 \\ bar();
666 \\ bar();
667 \\}
668 \\fn bar() void {}
669 ,
670 "42\n",
671 );
672
673 case.addCompareOutput(
674 \\export fn _start() i64 {
675 \\ bar();
676 \\ foo();
677 \\ foo();
678 \\ bar();
679 \\ foo();
680 \\ bar();
681 \\ return 42;
682 \\}
683 \\fn foo() void {
684 \\ bar();
685 \\}
686 \\fn bar() void {}
687 ,
688 "42\n",
689 );
690
691 case.addCompareOutput(
692 \\export fn _start() f32 {
693 \\ bar();
694 \\ foo();
695 \\ return 42.0;
696 \\}
697 \\fn foo() void {
698 \\ bar();
699 \\ bar();
700 \\ bar();
701 \\}
702 \\fn bar() void {}
703 ,
704 // This is what you get when you take the bits of the IEE-754
705 // representation of 42.0 and reinterpret them as an unsigned
706 // integer. Guess that's a bug in wasmtime.
707 "1109917696\n",
708 );
709 }
710}
test/stage2/compile_errors.zig deleted-135
...@@ -1,135 +0,0 @@
1const TestContext = @import("../../src-self-hosted/test.zig").TestContext;
2const std = @import("std");
3
4const ErrorMsg = @import("../../src-self-hosted/Module.zig").ErrorMsg;
5
6const linux_x64 = std.zig.CrossTarget{
7 .cpu_arch = .x86_64,
8 .os_tag = .linux,
9};
10
11pub fn addCases(ctx: *TestContext) !void {
12 ctx.compileErrorZIR("call undefined local", linux_x64,
13 \\@noreturn = primitive(noreturn)
14 \\
15 \\@start_fnty = fntype([], @noreturn, cc=Naked)
16 \\@start = fn(@start_fnty, {
17 \\ %0 = call(%test, [])
18 \\})
19 // TODO: address inconsistency in this message and the one in the next test
20 , &[_][]const u8{":5:13: error: unrecognized identifier: %test"});
21
22 ctx.compileErrorZIR("call with non-existent target", linux_x64,
23 \\@noreturn = primitive(noreturn)
24 \\
25 \\@start_fnty = fntype([], @noreturn, cc=Naked)
26 \\@start = fn(@start_fnty, {
27 \\ %0 = call(@notafunc, [])
28 \\})
29 \\@0 = str("_start")
30 \\@1 = export(@0, "start")
31 , &[_][]const u8{":5:13: error: decl 'notafunc' not found"});
32
33 // TODO: this error should occur at the call site, not the fntype decl
34 ctx.compileErrorZIR("call naked function", linux_x64,
35 \\@noreturn = primitive(noreturn)
36 \\
37 \\@start_fnty = fntype([], @noreturn, cc=Naked)
38 \\@s = fn(@start_fnty, {})
39 \\@start = fn(@start_fnty, {
40 \\ %0 = call(@s, [])
41 \\})
42 \\@0 = str("_start")
43 \\@1 = export(@0, "start")
44 , &[_][]const u8{":4:9: error: unable to call function with naked calling convention"});
45
46 ctx.incrementalFailureZIR("exported symbol collision", linux_x64,
47 \\@noreturn = primitive(noreturn)
48 \\
49 \\@start_fnty = fntype([], @noreturn)
50 \\@start = fn(@start_fnty, {})
51 \\
52 \\@0 = str("_start")
53 \\@1 = export(@0, "start")
54 \\@2 = export(@0, "start")
55 , &[_][]const u8{":8:13: error: exported symbol collision: _start"},
56 \\@noreturn = primitive(noreturn)
57 \\
58 \\@start_fnty = fntype([], @noreturn)
59 \\@start = fn(@start_fnty, {})
60 \\
61 \\@0 = str("_start")
62 \\@1 = export(@0, "start")
63 );
64
65 ctx.compileError("function redefinition", linux_x64,
66 \\fn entry() void {}
67 \\fn entry() void {}
68 , &[_][]const u8{":2:4: error: redefinition of 'entry'"});
69
70 //ctx.incrementalFailure("function redefinition", linux_x64,
71 // \\fn entry() void {}
72 // \\fn entry() void {}
73 //, &[_][]const u8{":2:4: error: redefinition of 'entry'"},
74 // \\fn entry() void {}
75 //);
76
77 //// TODO: need to make sure this works with other variants of export.
78 //ctx.incrementalFailure("exported symbol collision", linux_x64,
79 // \\export fn entry() void {}
80 // \\export fn entry() void {}
81 //, &[_][]const u8{":2:11: error: redefinition of 'entry'"},
82 // \\export fn entry() void {}
83 //);
84
85 // ctx.incrementalFailure("missing function name", linux_x64,
86 // \\fn() void {}
87 // , &[_][]const u8{":1:3: error: missing function name"},
88 // \\fn a() void {}
89 // );
90
91 // TODO: re-enable these tests.
92 // https://github.com/ziglang/zig/issues/1364
93
94 //ctx.testCompileError(
95 // \\comptime {
96 // \\ return;
97 // \\}
98 //, "1.zig", 2, 5, "return expression outside function definition");
99
100 //ctx.testCompileError(
101 // \\export fn entry() void {
102 // \\ defer return;
103 // \\}
104 //, "1.zig", 2, 11, "cannot return from defer expression");
105
106 //ctx.testCompileError(
107 // \\export fn entry() c_int {
108 // \\ return 36893488147419103232;
109 // \\}
110 //, "1.zig", 2, 12, "integer value '36893488147419103232' cannot be stored in type 'c_int'");
111
112 //ctx.testCompileError(
113 // \\comptime {
114 // \\ var a: *align(4) align(4) i32 = 0;
115 // \\}
116 //, "1.zig", 2, 22, "Extra align qualifier");
117
118 //ctx.testCompileError(
119 // \\comptime {
120 // \\ var b: *const const i32 = 0;
121 // \\}
122 //, "1.zig", 2, 19, "Extra align qualifier");
123
124 //ctx.testCompileError(
125 // \\comptime {
126 // \\ var c: *volatile volatile i32 = 0;
127 // \\}
128 //, "1.zig", 2, 22, "Extra align qualifier");
129
130 //ctx.testCompileError(
131 // \\comptime {
132 // \\ var d: *allowzero allowzero i32 = 0;
133 // \\}
134 //, "1.zig", 2, 23, "Extra align qualifier");
135}
test/stage2/test.zig+720-2
...@@ -1,8 +1,726 @@...@@ -1,8 +1,726 @@
1const std = @import("std");
1const TestContext = @import("../../src-self-hosted/test.zig").TestContext;2const TestContext = @import("../../src-self-hosted/test.zig").TestContext;
23
4// self-hosted does not yet support PE executable files / COFF object files
5// or mach-o files. So we do these test cases cross compiling for x86_64-linux.
6const linux_x64 = std.zig.CrossTarget{
7 .cpu_arch = .x86_64,
8 .os_tag = .linux,
9};
10
11const linux_riscv64 = std.zig.CrossTarget{
12 .cpu_arch = .riscv64,
13 .os_tag = .linux,
14};
15
16const wasi = std.zig.CrossTarget{
17 .cpu_arch = .wasm32,
18 .os_tag = .wasi,
19};
20
3pub fn addCases(ctx: *TestContext) !void {21pub fn addCases(ctx: *TestContext) !void {
4 try @import("compile_errors.zig").addCases(ctx);
5 try @import("compare_output.zig").addCases(ctx);
6 try @import("zir.zig").addCases(ctx);22 try @import("zir.zig").addCases(ctx);
7 try @import("cbe.zig").addCases(ctx);23 try @import("cbe.zig").addCases(ctx);
24 {
25 var case = ctx.exe("hello world with updates", linux_x64);
26
27 case.addError("", &[_][]const u8{":1:1: error: no entry point found"});
28
29 // Incorrect return type
30 case.addError(
31 \\export fn _start() noreturn {
32 \\}
33 , &[_][]const u8{":2:1: error: expected noreturn, found void"});
34
35 // Regular old hello world
36 case.addCompareOutput(
37 \\export fn _start() noreturn {
38 \\ print();
39 \\
40 \\ exit();
41 \\}
42 \\
43 \\fn print() void {
44 \\ asm volatile ("syscall"
45 \\ :
46 \\ : [number] "{rax}" (1),
47 \\ [arg1] "{rdi}" (1),
48 \\ [arg2] "{rsi}" (@ptrToInt("Hello, World!\n")),
49 \\ [arg3] "{rdx}" (14)
50 \\ : "rcx", "r11", "memory"
51 \\ );
52 \\ return;
53 \\}
54 \\
55 \\fn exit() noreturn {
56 \\ asm volatile ("syscall"
57 \\ :
58 \\ : [number] "{rax}" (231),
59 \\ [arg1] "{rdi}" (0)
60 \\ : "rcx", "r11", "memory"
61 \\ );
62 \\ unreachable;
63 \\}
64 ,
65 "Hello, World!\n",
66 );
67 // Now change the message only
68 case.addCompareOutput(
69 \\export fn _start() noreturn {
70 \\ print();
71 \\
72 \\ exit();
73 \\}
74 \\
75 \\fn print() void {
76 \\ asm volatile ("syscall"
77 \\ :
78 \\ : [number] "{rax}" (1),
79 \\ [arg1] "{rdi}" (1),
80 \\ [arg2] "{rsi}" (@ptrToInt("What is up? This is a longer message that will force the data to be relocated in virtual address space.\n")),
81 \\ [arg3] "{rdx}" (104)
82 \\ : "rcx", "r11", "memory"
83 \\ );
84 \\ return;
85 \\}
86 \\
87 \\fn exit() noreturn {
88 \\ asm volatile ("syscall"
89 \\ :
90 \\ : [number] "{rax}" (231),
91 \\ [arg1] "{rdi}" (0)
92 \\ : "rcx", "r11", "memory"
93 \\ );
94 \\ unreachable;
95 \\}
96 ,
97 "What is up? This is a longer message that will force the data to be relocated in virtual address space.\n",
98 );
99 // Now we print it twice.
100 case.addCompareOutput(
101 \\export fn _start() noreturn {
102 \\ print();
103 \\ print();
104 \\
105 \\ exit();
106 \\}
107 \\
108 \\fn print() void {
109 \\ asm volatile ("syscall"
110 \\ :
111 \\ : [number] "{rax}" (1),
112 \\ [arg1] "{rdi}" (1),
113 \\ [arg2] "{rsi}" (@ptrToInt("What is up? This is a longer message that will force the data to be relocated in virtual address space.\n")),
114 \\ [arg3] "{rdx}" (104)
115 \\ : "rcx", "r11", "memory"
116 \\ );
117 \\ return;
118 \\}
119 \\
120 \\fn exit() noreturn {
121 \\ asm volatile ("syscall"
122 \\ :
123 \\ : [number] "{rax}" (231),
124 \\ [arg1] "{rdi}" (0)
125 \\ : "rcx", "r11", "memory"
126 \\ );
127 \\ unreachable;
128 \\}
129 ,
130 \\What is up? This is a longer message that will force the data to be relocated in virtual address space.
131 \\What is up? This is a longer message that will force the data to be relocated in virtual address space.
132 \\
133 );
134 }
135
136 {
137 var case = ctx.exe("hello world", linux_riscv64);
138 // Regular old hello world
139 case.addCompareOutput(
140 \\export fn _start() noreturn {
141 \\ print();
142 \\
143 \\ exit();
144 \\}
145 \\
146 \\fn print() void {
147 \\ asm volatile ("ecall"
148 \\ :
149 \\ : [number] "{a7}" (64),
150 \\ [arg1] "{a0}" (1),
151 \\ [arg2] "{a1}" (@ptrToInt("Hello, World!\n")),
152 \\ [arg3] "{a2}" ("Hello, World!\n".len)
153 \\ : "rcx", "r11", "memory"
154 \\ );
155 \\ return;
156 \\}
157 \\
158 \\fn exit() noreturn {
159 \\ asm volatile ("ecall"
160 \\ :
161 \\ : [number] "{a7}" (94),
162 \\ [arg1] "{a0}" (0)
163 \\ : "rcx", "r11", "memory"
164 \\ );
165 \\ unreachable;
166 \\}
167 ,
168 "Hello, World!\n",
169 );
170 }
171
172 {
173 var case = ctx.exe("adding numbers at comptime", linux_x64);
174 case.addCompareOutput(
175 \\export fn _start() noreturn {
176 \\ asm volatile ("syscall"
177 \\ :
178 \\ : [number] "{rax}" (1),
179 \\ [arg1] "{rdi}" (1),
180 \\ [arg2] "{rsi}" (@ptrToInt("Hello, World!\n")),
181 \\ [arg3] "{rdx}" (10 + 4)
182 \\ : "rcx", "r11", "memory"
183 \\ );
184 \\ asm volatile ("syscall"
185 \\ :
186 \\ : [number] "{rax}" (@as(usize, 230) + @as(usize, 1)),
187 \\ [arg1] "{rdi}" (0)
188 \\ : "rcx", "r11", "memory"
189 \\ );
190 \\ unreachable;
191 \\}
192 ,
193 "Hello, World!\n",
194 );
195 }
196
197 {
198 var case = ctx.exe("adding numbers at runtime", linux_x64);
199 case.addCompareOutput(
200 \\export fn _start() noreturn {
201 \\ add(3, 4);
202 \\
203 \\ exit();
204 \\}
205 \\
206 \\fn add(a: u32, b: u32) void {
207 \\ if (a + b != 7) unreachable;
208 \\}
209 \\
210 \\fn exit() noreturn {
211 \\ asm volatile ("syscall"
212 \\ :
213 \\ : [number] "{rax}" (231),
214 \\ [arg1] "{rdi}" (0)
215 \\ : "rcx", "r11", "memory"
216 \\ );
217 \\ unreachable;
218 \\}
219 ,
220 "",
221 );
222 }
223
224 {
225 var case = ctx.exe("substracting numbers at runtime", linux_x64);
226 case.addCompareOutput(
227 \\export fn _start() noreturn {
228 \\ sub(7, 4);
229 \\
230 \\ exit();
231 \\}
232 \\
233 \\fn sub(a: u32, b: u32) void {
234 \\ if (a - b != 3) unreachable;
235 \\}
236 \\
237 \\fn exit() noreturn {
238 \\ asm volatile ("syscall"
239 \\ :
240 \\ : [number] "{rax}" (231),
241 \\ [arg1] "{rdi}" (0)
242 \\ : "rcx", "r11", "memory"
243 \\ );
244 \\ unreachable;
245 \\}
246 ,
247 "",
248 );
249 }
250
251 {
252 var case = ctx.exe("assert function", linux_x64);
253 case.addCompareOutput(
254 \\export fn _start() noreturn {
255 \\ add(3, 4);
256 \\
257 \\ exit();
258 \\}
259 \\
260 \\fn add(a: u32, b: u32) void {
261 \\ assert(a + b == 7);
262 \\}
263 \\
264 \\pub fn assert(ok: bool) void {
265 \\ if (!ok) unreachable; // assertion failure
266 \\}
267 \\
268 \\fn exit() noreturn {
269 \\ asm volatile ("syscall"
270 \\ :
271 \\ : [number] "{rax}" (231),
272 \\ [arg1] "{rdi}" (0)
273 \\ : "rcx", "r11", "memory"
274 \\ );
275 \\ unreachable;
276 \\}
277 ,
278 "",
279 );
280
281 // Tests copying a register. For the `c = a + b`, it has to
282 // preserve both a and b, because they are both used later.
283 case.addCompareOutput(
284 \\export fn _start() noreturn {
285 \\ add(3, 4);
286 \\
287 \\ exit();
288 \\}
289 \\
290 \\fn add(a: u32, b: u32) void {
291 \\ const c = a + b; // 7
292 \\ const d = a + c; // 10
293 \\ const e = d + b; // 14
294 \\ assert(e == 14);
295 \\}
296 \\
297 \\pub fn assert(ok: bool) void {
298 \\ if (!ok) unreachable; // assertion failure
299 \\}
300 \\
301 \\fn exit() noreturn {
302 \\ asm volatile ("syscall"
303 \\ :
304 \\ : [number] "{rax}" (231),
305 \\ [arg1] "{rdi}" (0)
306 \\ : "rcx", "r11", "memory"
307 \\ );
308 \\ unreachable;
309 \\}
310 ,
311 "",
312 );
313
314 // More stress on the liveness detection.
315 case.addCompareOutput(
316 \\export fn _start() noreturn {
317 \\ add(3, 4);
318 \\
319 \\ exit();
320 \\}
321 \\
322 \\fn add(a: u32, b: u32) void {
323 \\ const c = a + b; // 7
324 \\ const d = a + c; // 10
325 \\ const e = d + b; // 14
326 \\ const f = d + e; // 24
327 \\ const g = e + f; // 38
328 \\ const h = f + g; // 62
329 \\ const i = g + h; // 100
330 \\ assert(i == 100);
331 \\}
332 \\
333 \\pub fn assert(ok: bool) void {
334 \\ if (!ok) unreachable; // assertion failure
335 \\}
336 \\
337 \\fn exit() noreturn {
338 \\ asm volatile ("syscall"
339 \\ :
340 \\ : [number] "{rax}" (231),
341 \\ [arg1] "{rdi}" (0)
342 \\ : "rcx", "r11", "memory"
343 \\ );
344 \\ unreachable;
345 \\}
346 ,
347 "",
348 );
349
350 // Requires a second move. The register allocator should figure out to re-use rax.
351 case.addCompareOutput(
352 \\export fn _start() noreturn {
353 \\ add(3, 4);
354 \\
355 \\ exit();
356 \\}
357 \\
358 \\fn add(a: u32, b: u32) void {
359 \\ const c = a + b; // 7
360 \\ const d = a + c; // 10
361 \\ const e = d + b; // 14
362 \\ const f = d + e; // 24
363 \\ const g = e + f; // 38
364 \\ const h = f + g; // 62
365 \\ const i = g + h; // 100
366 \\ const j = i + d; // 110
367 \\ assert(j == 110);
368 \\}
369 \\
370 \\pub fn assert(ok: bool) void {
371 \\ if (!ok) unreachable; // assertion failure
372 \\}
373 \\
374 \\fn exit() noreturn {
375 \\ asm volatile ("syscall"
376 \\ :
377 \\ : [number] "{rax}" (231),
378 \\ [arg1] "{rdi}" (0)
379 \\ : "rcx", "r11", "memory"
380 \\ );
381 \\ unreachable;
382 \\}
383 ,
384 "",
385 );
386
387 // Now we test integer return values.
388 case.addCompareOutput(
389 \\export fn _start() noreturn {
390 \\ assert(add(3, 4) == 7);
391 \\ assert(add(20, 10) == 30);
392 \\
393 \\ exit();
394 \\}
395 \\
396 \\fn add(a: u32, b: u32) u32 {
397 \\ return a + b;
398 \\}
399 \\
400 \\pub fn assert(ok: bool) void {
401 \\ if (!ok) unreachable; // assertion failure
402 \\}
403 \\
404 \\fn exit() noreturn {
405 \\ asm volatile ("syscall"
406 \\ :
407 \\ : [number] "{rax}" (231),
408 \\ [arg1] "{rdi}" (0)
409 \\ : "rcx", "r11", "memory"
410 \\ );
411 \\ unreachable;
412 \\}
413 ,
414 "",
415 );
416
417 // Local mutable variables.
418 case.addCompareOutput(
419 \\export fn _start() noreturn {
420 \\ assert(add(3, 4) == 7);
421 \\ assert(add(20, 10) == 30);
422 \\
423 \\ exit();
424 \\}
425 \\
426 \\fn add(a: u32, b: u32) u32 {
427 \\ var x: u32 = undefined;
428 \\ x = 0;
429 \\ x += a;
430 \\ x += b;
431 \\ return x;
432 \\}
433 \\
434 \\pub fn assert(ok: bool) void {
435 \\ if (!ok) unreachable; // assertion failure
436 \\}
437 \\
438 \\fn exit() noreturn {
439 \\ asm volatile ("syscall"
440 \\ :
441 \\ : [number] "{rax}" (231),
442 \\ [arg1] "{rdi}" (0)
443 \\ : "rcx", "r11", "memory"
444 \\ );
445 \\ unreachable;
446 \\}
447 ,
448 "",
449 );
450
451 // Optionals
452 case.addCompareOutput(
453 \\export fn _start() noreturn {
454 \\ const a: u32 = 2;
455 \\ const b: ?u32 = a;
456 \\ const c = b.?;
457 \\ if (c != 2) unreachable;
458 \\
459 \\ exit();
460 \\}
461 \\
462 \\fn exit() noreturn {
463 \\ asm volatile ("syscall"
464 \\ :
465 \\ : [number] "{rax}" (231),
466 \\ [arg1] "{rdi}" (0)
467 \\ : "rcx", "r11", "memory"
468 \\ );
469 \\ unreachable;
470 \\}
471 ,
472 "",
473 );
474
475 // While loops
476 case.addCompareOutput(
477 \\export fn _start() noreturn {
478 \\ var i: u32 = 0;
479 \\ while (i < 4) : (i += 1) print();
480 \\ assert(i == 4);
481 \\
482 \\ exit();
483 \\}
484 \\
485 \\fn print() void {
486 \\ asm volatile ("syscall"
487 \\ :
488 \\ : [number] "{rax}" (1),
489 \\ [arg1] "{rdi}" (1),
490 \\ [arg2] "{rsi}" (@ptrToInt("hello\n")),
491 \\ [arg3] "{rdx}" (6)
492 \\ : "rcx", "r11", "memory"
493 \\ );
494 \\ return;
495 \\}
496 \\
497 \\pub fn assert(ok: bool) void {
498 \\ if (!ok) unreachable; // assertion failure
499 \\}
500 \\
501 \\fn exit() noreturn {
502 \\ asm volatile ("syscall"
503 \\ :
504 \\ : [number] "{rax}" (231),
505 \\ [arg1] "{rdi}" (0)
506 \\ : "rcx", "r11", "memory"
507 \\ );
508 \\ unreachable;
509 \\}
510 ,
511 "hello\nhello\nhello\nhello\n",
512 );
513
514 // Labeled blocks (no conditional branch)
515 case.addCompareOutput(
516 \\export fn _start() noreturn {
517 \\ assert(add(3, 4) == 20);
518 \\
519 \\ exit();
520 \\}
521 \\
522 \\fn add(a: u32, b: u32) u32 {
523 \\ const x: u32 = blk: {
524 \\ const c = a + b; // 7
525 \\ const d = a + c; // 10
526 \\ const e = d + b; // 14
527 \\ break :blk e;
528 \\ };
529 \\ const y = x + a; // 17
530 \\ const z = y + a; // 20
531 \\ return z;
532 \\}
533 \\
534 \\pub fn assert(ok: bool) void {
535 \\ if (!ok) unreachable; // assertion failure
536 \\}
537 \\
538 \\fn exit() noreturn {
539 \\ asm volatile ("syscall"
540 \\ :
541 \\ : [number] "{rax}" (231),
542 \\ [arg1] "{rdi}" (0)
543 \\ : "rcx", "r11", "memory"
544 \\ );
545 \\ unreachable;
546 \\}
547 ,
548 "",
549 );
550
551 // This catches a possible bug in the logic for re-using dying operands.
552 case.addCompareOutput(
553 \\export fn _start() noreturn {
554 \\ assert(add(3, 4) == 116);
555 \\
556 \\ exit();
557 \\}
558 \\
559 \\fn add(a: u32, b: u32) u32 {
560 \\ const x: u32 = blk: {
561 \\ const c = a + b; // 7
562 \\ const d = a + c; // 10
563 \\ const e = d + b; // 14
564 \\ const f = d + e; // 24
565 \\ const g = e + f; // 38
566 \\ const h = f + g; // 62
567 \\ const i = g + h; // 100
568 \\ const j = i + d; // 110
569 \\ break :blk j;
570 \\ };
571 \\ const y = x + a; // 113
572 \\ const z = y + a; // 116
573 \\ return z;
574 \\}
575 \\
576 \\pub fn assert(ok: bool) void {
577 \\ if (!ok) unreachable; // assertion failure
578 \\}
579 \\
580 \\fn exit() noreturn {
581 \\ asm volatile ("syscall"
582 \\ :
583 \\ : [number] "{rax}" (231),
584 \\ [arg1] "{rdi}" (0)
585 \\ : "rcx", "r11", "memory"
586 \\ );
587 \\ unreachable;
588 \\}
589 ,
590 "",
591 );
592
593 // Character literals and multiline strings.
594 case.addCompareOutput(
595 \\export fn _start() noreturn {
596 \\ const ignore =
597 \\ \\ cool thx
598 \\ \\
599 \\ ;
600 \\ add('ぁ', '\x03');
601 \\
602 \\ exit();
603 \\}
604 \\
605 \\fn add(a: u32, b: u32) void {
606 \\ assert(a + b == 12356);
607 \\}
608 \\
609 \\pub fn assert(ok: bool) void {
610 \\ if (!ok) unreachable; // assertion failure
611 \\}
612 \\
613 \\fn exit() noreturn {
614 \\ asm volatile ("syscall"
615 \\ :
616 \\ : [number] "{rax}" (231),
617 \\ [arg1] "{rdi}" (0)
618 \\ : "rcx", "r11", "memory"
619 \\ );
620 \\ unreachable;
621 \\}
622 ,
623 "",
624 );
625
626 // Global const.
627 case.addCompareOutput(
628 \\export fn _start() noreturn {
629 \\ add(aa, bb);
630 \\
631 \\ exit();
632 \\}
633 \\
634 \\const aa = 'ぁ';
635 \\const bb = '\x03';
636 \\
637 \\fn add(a: u32, b: u32) void {
638 \\ assert(a + b == 12356);
639 \\}
640 \\
641 \\pub fn assert(ok: bool) void {
642 \\ if (!ok) unreachable; // assertion failure
643 \\}
644 \\
645 \\fn exit() noreturn {
646 \\ asm volatile ("syscall"
647 \\ :
648 \\ : [number] "{rax}" (231),
649 \\ [arg1] "{rdi}" (0)
650 \\ : "rcx", "r11", "memory"
651 \\ );
652 \\ unreachable;
653 \\}
654 ,
655 "",
656 );
657 }
658
659 {
660 var case = ctx.exe("wasm function calls", wasi);
661
662 case.addCompareOutput(
663 \\export fn _start() u32 {
664 \\ foo();
665 \\ bar();
666 \\ return 42;
667 \\}
668 \\fn foo() void {
669 \\ bar();
670 \\ bar();
671 \\}
672 \\fn bar() void {}
673 ,
674 "42\n",
675 );
676
677 case.addCompareOutput(
678 \\export fn _start() i64 {
679 \\ bar();
680 \\ foo();
681 \\ foo();
682 \\ bar();
683 \\ foo();
684 \\ bar();
685 \\ return 42;
686 \\}
687 \\fn foo() void {
688 \\ bar();
689 \\}
690 \\fn bar() void {}
691 ,
692 "42\n",
693 );
694
695 case.addCompareOutput(
696 \\export fn _start() f32 {
697 \\ bar();
698 \\ foo();
699 \\ return 42.0;
700 \\}
701 \\fn foo() void {
702 \\ bar();
703 \\ bar();
704 \\ bar();
705 \\}
706 \\fn bar() void {}
707 ,
708 // This is what you get when you take the bits of the IEE-754
709 // representation of 42.0 and reinterpret them as an unsigned
710 // integer. Guess that's a bug in wasmtime.
711 "1109917696\n",
712 );
713 }
714
715 ctx.compileError("function redefinition", linux_x64,
716 \\fn entry() void {}
717 \\fn entry() void {}
718 , &[_][]const u8{":2:4: error: redefinition of 'entry'"});
719
720 ctx.compileError("extern variable has no type", linux_x64,
721 \\comptime {
722 \\ _ = foo;
723 \\}
724 \\extern var foo;
725 , &[_][]const u8{":4:1: error: unable to infer variable type"});
8}726}