| author | |
| committer | |
| log | 6bbb168f6667520dc106bc93c6e3761d5611fccb |
| tree | c12be20be24223f37ab9a3c6cfdb9db8e7d263b4 |
| parent | eef111fe78d7b246b634a07561082a6fcf947e09 |
| parent | 73d16d015e09c05aecba8a58881cbc429e8126fa |
closes #61079 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") orelse | 1485 | const type_node = var_decl.getTrailer("type_node") orelse |
| 1486 | break :blk null; | 1486 | break :blk null; |
| 1487 | 1487 | ||
| 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 | else | 1541 | 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", .{}); | ||
| 1543 | 1545 | ||
| 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 }; |
| 2435 | 2480 | ||
| ... | @@ -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 |
| 2442 | fn analyzeVarRef(self: *Module, scope: *Scope, src: usize, tv: TypedValue) InnerError!*Inst { | 2487 | fn 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; |
| 2444 | 2489 | ||
| 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 |
| 2766 | 2811 | ||
| 2767 | // T to ?T | 2812 | // 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 | } |
| 3147 | 3192 | ||
| 3148 | pub fn singlePtrType(self: *Module, scope: *Scope, src: usize, mutable: bool, elem_ty: Type) Allocator.Error!Type { | 3193 | pub 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 | |||
| 3215 | pub 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 |
| 3157 | pub fn optionalType(self: *Module, scope: *Scope, child_type: Type) Allocator.Error!Type { | 3247 | pub 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).?)), | ||
| 265 | 266 | ||
| 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 | } |
| 571 | 571 | ||
| 572 | fn 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 | |||
| 572 | fn ptrType(mod: *Module, scope: *Scope, node: *ast.Node.PtrType) InnerError!*zir.Inst { | 578 | fn 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 | |||
| 592 | fn 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 | }); |
| 579 | 597 | ||
| 580 | const simple = node.ptr_info.allowzero_token == null and | 598 | const simple = ptr_info.allowzero_token == null and |
| 581 | node.ptr_info.align_info == null and | 599 | ptr_info.align_info == null and |
| 582 | node.ptr_info.volatile_token == null and | 600 | ptr_info.volatile_token == null and |
| 583 | node.ptr_info.sentinel == null; | 601 | ptr_info.sentinel == null; |
| 584 | 602 | ||
| 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_type | 606 | // TODO stage1 type inference bug |
| 589 | else | 607 | 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 | } |
| 592 | 615 | ||
| 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 | } |
| 607 | 631 | ||
| 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 | } |
| 1277 | 1301 |
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 }; |
| 2062 | 2062 | ||
| 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, |
| 67 | 67 | ||
| 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, | ||
| 73 | 81 | ||
| 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 | } |
| 110 | 118 | ||
| 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 | } |
| 382 | 421 | ||
| ... | @@ -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 types | 719 | // 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, |
| 624 | 725 | ||
| ... | @@ -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), |
| 675 | 782 | ||
| 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 | }, |
| 705 | 819 | ||
| 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; |
| 710 | 824 | ||
| ... | @@ -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, | ||
| 747 | 862 | ||
| 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, |
| 768 | 883 | ||
| 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 | }, | ||
| 778 | 909 | ||
| 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 | }, |
| 806 | 937 | ||
| 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; |
| 811 | 942 | ||
| ... | @@ -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, |
| 876 | 1013 | ||
| 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 | } |
| 883 | 1022 | ||
| ... | @@ -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, |
| 938 | 1081 | ||
| 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 | } |
| 942 | 1090 | ||
| ... | @@ -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, |
| 995 | 1146 | ||
| 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 | } |
| 1002 | 1158 | ||
| ... | @@ -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 | } |
| 1060 | 1227 | ||
| ... | @@ -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 bools | 1235 | // 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, |
| 1102 | 1269 | ||
| 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 { |
| 1164 | 1331 | ||
| 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 | } |
| 1173 | 1348 | ||
| 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 | } |
| 2119 | 2397 | ||
| ... | @@ -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 | } |
| 2177 | 2465 | ||
| ... | @@ -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 | }; |
| 2274 | 2569 | ||
| 2275 | pub const Pointer = struct { | 2570 | pub const PointerSimple = struct { |
| 2276 | base: Payload, | 2571 | base: Payload, |
| 2277 | 2572 | ||
| 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 { |
| 2303 | 2598 | ||
| 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 | }; |
| 2308 | 2618 |
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 attributes | 213 | /// 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 | }; |
| 864 | 889 | ||
| ... | @@ -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 | } |
| 269 | 275 | ||
| 276 | fn 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 | |||
| 270 | pub fn resolveInstConst(mod: *Module, scope: *Scope, old_inst: *zir.Inst) InnerError!TypedValue { | 284 | pub 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 |
| 324 | 338 | ||
| 325 | fn analyzeInstRef(mod: *Module, scope: *Scope, inst: *zir.Inst.UnOp) InnerError!*Inst { | 339 | fn 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); |
| 328 | 342 | ||
| 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 | } |
| 724 | 738 | ||
| 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); |
| 727 | 741 | ||
| 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)); |
| 942 | 956 | ||
| 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 | } |
| 1313 | 1327 | ||
| 1314 | fn analyzeInstSingleConstPtrType(mod: *Module, scope: *Scope, inst: *zir.Inst.UnOp) InnerError!*Inst { | 1328 | fn 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 | |||
| 1320 | fn 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 | } |
| 1325 | 1333 | ||
| 1326 | fn analyzeInstPtrType(mod: *Module, scope: *Scope, inst: *zir.Inst.PtrType) InnerError!*Inst { | 1334 | fn 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 @@ | ||
| 1 | const std = @import("std"); | ||
| 2 | const 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. | ||
| 5 | const linux_x64 = std.zig.CrossTarget{ | ||
| 6 | .cpu_arch = .x86_64, | ||
| 7 | .os_tag = .linux, | ||
| 8 | }; | ||
| 9 | |||
| 10 | const linux_riscv64 = std.zig.CrossTarget{ | ||
| 11 | .cpu_arch = .riscv64, | ||
| 12 | .os_tag = .linux, | ||
| 13 | }; | ||
| 14 | |||
| 15 | const wasi = std.zig.CrossTarget{ | ||
| 16 | .cpu_arch = .wasm32, | ||
| 17 | .os_tag = .wasi, | ||
| 18 | }; | ||
| 19 | |||
| 20 | pub 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 @@ | ||
| 1 | const TestContext = @import("../../src-self-hosted/test.zig").TestContext; | ||
| 2 | const std = @import("std"); | ||
| 3 | |||
| 4 | const ErrorMsg = @import("../../src-self-hosted/Module.zig").ErrorMsg; | ||
| 5 | |||
| 6 | const linux_x64 = std.zig.CrossTarget{ | ||
| 7 | .cpu_arch = .x86_64, | ||
| 8 | .os_tag = .linux, | ||
| 9 | }; | ||
| 10 | |||
| 11 | pub 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 @@ |
| 1 | const std = @import("std"); | ||
| 1 | const TestContext = @import("../../src-self-hosted/test.zig").TestContext; | 2 | const TestContext = @import("../../src-self-hosted/test.zig").TestContext; |
| 2 | 3 | ||
| 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. | ||
| 6 | const linux_x64 = std.zig.CrossTarget{ | ||
| 7 | .cpu_arch = .x86_64, | ||
| 8 | .os_tag = .linux, | ||
| 9 | }; | ||
| 10 | |||
| 11 | const linux_riscv64 = std.zig.CrossTarget{ | ||
| 12 | .cpu_arch = .riscv64, | ||
| 13 | .os_tag = .linux, | ||
| 14 | }; | ||
| 15 | |||
| 16 | const wasi = std.zig.CrossTarget{ | ||
| 17 | .cpu_arch = .wasm32, | ||
| 18 | .os_tag = .wasi, | ||
| 19 | }; | ||
| 20 | |||
| 3 | pub fn addCases(ctx: *TestContext) !void { | 21 | pub 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 | } |