| author | |
| committer | |
| log | 338a495648f07a2734e012034fd301a0e77f8202 |
| tree | 020b47ea8f5e7a6f8906de9424cda1828d05ceca |
| parent | b0846b6ecbb3e2557c5c95ddee04ecc055881d75 |
7 files changed, 266 insertions(+), 13 deletions(-)
src-self-hosted/Module.zig+210-8| ... | @@ -320,6 +320,12 @@ pub const Fn = struct { | ... | @@ -320,6 +320,12 @@ pub const Fn = struct { |
| 320 | } | 320 | } |
| 321 | }; | 321 | }; |
| 322 | 322 | ||
| 323 | pub const Var = struct { | ||
| 324 | value: ?Value, | ||
| 325 | owner_decl: *Decl, | ||
| 326 | is_mutable: bool, | ||
| 327 | }; | ||
| 328 | |||
| 323 | pub const Scope = struct { | 329 | pub const Scope = struct { |
| 324 | tag: Tag, | 330 | tag: Tag, |
| 325 | 331 | ||
| ... | @@ -1419,7 +1425,152 @@ fn astGenAndAnalyzeDecl(self: *Module, decl: *Decl) !bool { | ... | @@ -1419,7 +1425,152 @@ fn astGenAndAnalyzeDecl(self: *Module, decl: *Decl) !bool { |
| 1419 | } | 1425 | } |
| 1420 | return type_changed; | 1426 | return type_changed; |
| 1421 | }, | 1427 | }, |
| 1422 | .VarDecl => @panic("TODO var decl"), | 1428 | .VarDecl => { |
| 1429 | const var_decl = @fieldParentPtr(ast.Node.VarDecl, "base", ast_node); | ||
| 1430 | |||
| 1431 | decl.analysis = .in_progress; | ||
| 1432 | |||
| 1433 | const is_extern = blk: { | ||
| 1434 | const maybe_extern_token = var_decl.getTrailer("extern_export_token") orelse | ||
| 1435 | break :blk false; | ||
| 1436 | break :blk tree.token_ids[maybe_extern_token] == .Keyword_extern; | ||
| 1437 | }; | ||
| 1438 | const is_mutable = tree.token_ids[var_decl.mut_token] == .Keyword_var; | ||
| 1439 | |||
| 1440 | // We need the memory for the Type to go into the arena for the Decl | ||
| 1441 | var decl_arena = std.heap.ArenaAllocator.init(self.gpa); | ||
| 1442 | errdefer decl_arena.deinit(); | ||
| 1443 | const decl_arena_state = try decl_arena.allocator.create(std.heap.ArenaAllocator.State); | ||
| 1444 | |||
| 1445 | var block_scope: Scope.Block = .{ | ||
| 1446 | .parent = null, | ||
| 1447 | .func = null, | ||
| 1448 | .decl = decl, | ||
| 1449 | .instructions = .{}, | ||
| 1450 | .arena = &decl_arena.allocator, | ||
| 1451 | }; | ||
| 1452 | defer block_scope.instructions.deinit(self.gpa); | ||
| 1453 | |||
| 1454 | const explicit_type = blk: { | ||
| 1455 | const type_node = var_decl.getTrailer("type_node") orelse | ||
| 1456 | break :blk null; | ||
| 1457 | |||
| 1458 | var type_scope_arena = std.heap.ArenaAllocator.init(self.gpa); | ||
| 1459 | defer type_scope_arena.deinit(); | ||
| 1460 | var type_scope: Scope.GenZIR = .{ | ||
| 1461 | .decl = decl, | ||
| 1462 | .arena = &type_scope_arena.allocator, | ||
| 1463 | .parent = decl.scope, | ||
| 1464 | }; | ||
| 1465 | defer type_scope.instructions.deinit(self.gpa); | ||
| 1466 | |||
| 1467 | const src = tree.token_locs[type_node.firstToken()].start; | ||
| 1468 | const type_type = try astgen.addZIRInstConst(self, &type_scope.base, src, .{ | ||
| 1469 | .ty = Type.initTag(.type), | ||
| 1470 | .val = Value.initTag(.type_type), | ||
| 1471 | }); | ||
| 1472 | const var_type = try astgen.expr(self, &type_scope.base, .{ .ty = type_type }, type_node); | ||
| 1473 | _ = try astgen.addZIRUnOp(self, &type_scope.base, src, .@"return", var_type); | ||
| 1474 | |||
| 1475 | break :blk try zir_sema.analyzeBodyValueAsType(self, &block_scope, .{ | ||
| 1476 | .instructions = type_scope.instructions.items, | ||
| 1477 | }); | ||
| 1478 | }; | ||
| 1479 | |||
| 1480 | var var_type: Type = undefined; | ||
| 1481 | const value: ?Value = if (var_decl.getTrailer("init_node")) |init_node| blk: { | ||
| 1482 | var gen_scope_arena = std.heap.ArenaAllocator.init(self.gpa); | ||
| 1483 | defer gen_scope_arena.deinit(); | ||
| 1484 | var gen_scope: Scope.GenZIR = .{ | ||
| 1485 | .decl = decl, | ||
| 1486 | .arena = &gen_scope_arena.allocator, | ||
| 1487 | .parent = decl.scope, | ||
| 1488 | }; | ||
| 1489 | defer gen_scope.instructions.deinit(self.gpa); | ||
| 1490 | const src = tree.token_locs[init_node.firstToken()].start; | ||
| 1491 | |||
| 1492 | // TODO comptime scope here | ||
| 1493 | const init_inst = try astgen.expr(self, &gen_scope.base, .none, init_node); | ||
| 1494 | _ = try astgen.addZIRUnOp(self, &gen_scope.base, src, .@"return", init_inst); | ||
| 1495 | |||
| 1496 | var inner_block: Scope.Block = .{ | ||
| 1497 | .parent = null, | ||
| 1498 | .func = null, | ||
| 1499 | .decl = decl, | ||
| 1500 | .instructions = .{}, | ||
| 1501 | .arena = &gen_scope_arena.allocator, | ||
| 1502 | }; | ||
| 1503 | defer inner_block.instructions.deinit(self.gpa); | ||
| 1504 | try zir_sema.analyzeBody(self, &inner_block.base, .{ .instructions = gen_scope.instructions.items }); | ||
| 1505 | |||
| 1506 | for (inner_block.instructions.items) |inst| { | ||
| 1507 | if (inst.castTag(.ret)) |ret| { | ||
| 1508 | const coerced = if (explicit_type) |some| | ||
| 1509 | try self.coerce(&inner_block.base, some, ret.operand) | ||
| 1510 | else | ||
| 1511 | ret.operand; | ||
| 1512 | const val = try self.resolveConstValue(&inner_block.base, coerced); | ||
| 1513 | |||
| 1514 | var_type = explicit_type orelse try ret.operand.ty.copy(block_scope.arena); | ||
| 1515 | break :blk try val.copy(block_scope.arena); | ||
| 1516 | } else { | ||
| 1517 | return self.fail(&block_scope.base, inst.src, "unable to resolve comptime value", .{}); | ||
| 1518 | } | ||
| 1519 | } | ||
| 1520 | unreachable; | ||
| 1521 | } else if (!is_extern) { | ||
| 1522 | return self.failTok(&block_scope.base, var_decl.firstToken(), "variables must be initialized", .{}); | ||
| 1523 | } else if (explicit_type) |some| blk: { | ||
| 1524 | var_type = some; | ||
| 1525 | break :blk null; | ||
| 1526 | } else { | ||
| 1527 | return self.failTok(&block_scope.base, var_decl.firstToken(), "unable to infer variable type", .{}); | ||
| 1528 | }; | ||
| 1529 | |||
| 1530 | if (is_mutable and !var_type.isValidVarType(is_extern)) { | ||
| 1531 | return self.failTok(&block_scope.base, var_decl.firstToken(), "variable of type '{}' must be const", .{var_type}); | ||
| 1532 | } | ||
| 1533 | |||
| 1534 | var type_changed = true; | ||
| 1535 | if (decl.typedValueManaged()) |tvm| { | ||
| 1536 | type_changed = !tvm.typed_value.ty.eql(var_type); | ||
| 1537 | |||
| 1538 | tvm.deinit(self.gpa); | ||
| 1539 | } | ||
| 1540 | |||
| 1541 | const new_variable = try decl_arena.allocator.create(Var); | ||
| 1542 | const var_payload = try decl_arena.allocator.create(Value.Payload.Variable); | ||
| 1543 | new_variable.* = .{ | ||
| 1544 | .value = value, | ||
| 1545 | .owner_decl = decl, | ||
| 1546 | .is_mutable = is_mutable, | ||
| 1547 | }; | ||
| 1548 | var_payload.* = .{ .variable = new_variable }; | ||
| 1549 | |||
| 1550 | decl_arena_state.* = decl_arena.state; | ||
| 1551 | decl.typed_value = .{ | ||
| 1552 | .most_recent = .{ | ||
| 1553 | .typed_value = .{ | ||
| 1554 | .ty = var_type, | ||
| 1555 | .val = Value.initPayload(&var_payload.base), | ||
| 1556 | }, | ||
| 1557 | .arena = decl_arena_state, | ||
| 1558 | }, | ||
| 1559 | }; | ||
| 1560 | decl.analysis = .complete; | ||
| 1561 | decl.generation = self.generation; | ||
| 1562 | |||
| 1563 | if (var_decl.getTrailer("extern_export_token")) |maybe_export_token| { | ||
| 1564 | if (tree.token_ids[maybe_export_token] == .Keyword_export) { | ||
| 1565 | const export_src = tree.token_locs[maybe_export_token].start; | ||
| 1566 | const name_loc = tree.token_locs[var_decl.name_token]; | ||
| 1567 | const name = tree.tokenSliceLoc(name_loc); | ||
| 1568 | // The scope needs to have the decl in it. | ||
| 1569 | try self.analyzeExport(&block_scope.base, export_src, name, decl); | ||
| 1570 | } | ||
| 1571 | } | ||
| 1572 | return type_changed; | ||
| 1573 | }, | ||
| 1423 | .Comptime => @panic("TODO comptime decl"), | 1574 | .Comptime => @panic("TODO comptime decl"), |
| 1424 | .Use => @panic("TODO usingnamespace decl"), | 1575 | .Use => @panic("TODO usingnamespace decl"), |
| 1425 | else => unreachable, | 1576 | else => unreachable, |
| ... | @@ -1584,7 +1735,32 @@ fn analyzeRootSrcFile(self: *Module, root_scope: *Scope.File) !void { | ... | @@ -1584,7 +1735,32 @@ fn analyzeRootSrcFile(self: *Module, root_scope: *Scope.File) !void { |
| 1584 | } | 1735 | } |
| 1585 | } | 1736 | } |
| 1586 | } else if (src_decl.castTag(.VarDecl)) |var_decl| { | 1737 | } else if (src_decl.castTag(.VarDecl)) |var_decl| { |
| 1587 | log.err("TODO: analyze var decl", .{}); | 1738 | const name_loc = tree.token_locs[var_decl.name_token]; |
| 1739 | const name = tree.tokenSliceLoc(name_loc); | ||
| 1740 | const name_hash = root_scope.fullyQualifiedNameHash(name); | ||
| 1741 | const contents_hash = std.zig.hashSrc(tree.getNodeSource(src_decl)); | ||
| 1742 | if (self.decl_table.get(name_hash)) |decl| { | ||
| 1743 | // Update the AST Node index of the decl, even if its contents are unchanged, it may | ||
| 1744 | // have been re-ordered. | ||
| 1745 | decl.src_index = decl_i; | ||
| 1746 | if (deleted_decls.remove(decl) == null) { | ||
| 1747 | decl.analysis = .sema_failure; | ||
| 1748 | const err_msg = try ErrorMsg.create(self.gpa, name_loc.start, "redefinition of '{}'", .{decl.name}); | ||
| 1749 | errdefer err_msg.destroy(self.gpa); | ||
| 1750 | try self.failed_decls.putNoClobber(self.gpa, decl, err_msg); | ||
| 1751 | } else if (!srcHashEql(decl.contents_hash, contents_hash)) { | ||
| 1752 | try self.markOutdatedDecl(decl); | ||
| 1753 | decl.contents_hash = contents_hash; | ||
| 1754 | } | ||
| 1755 | } else { | ||
| 1756 | const new_decl = try self.createNewDecl(&root_scope.base, name, decl_i, name_hash, contents_hash); | ||
| 1757 | root_scope.decls.appendAssumeCapacity(new_decl); | ||
| 1758 | if (var_decl.getTrailer("extern_export_token")) |maybe_export_token| { | ||
| 1759 | if (tree.token_ids[maybe_export_token] == .Keyword_export) { | ||
| 1760 | self.work_queue.writeItemAssumeCapacity(.{ .analyze_decl = new_decl }); | ||
| 1761 | } | ||
| 1762 | } | ||
| 1763 | } | ||
| 1588 | } else if (src_decl.castTag(.Comptime)) |comptime_node| { | 1764 | } else if (src_decl.castTag(.Comptime)) |comptime_node| { |
| 1589 | log.err("TODO: analyze comptime decl", .{}); | 1765 | log.err("TODO: analyze comptime decl", .{}); |
| 1590 | } else if (src_decl.castTag(.ContainerField)) |container_field| { | 1766 | } else if (src_decl.castTag(.ContainerField)) |container_field| { |
| ... | @@ -2217,20 +2393,46 @@ pub fn analyzeDeclRef(self: *Module, scope: *Scope, src: usize, decl: *Decl) Inn | ... | @@ -2217,20 +2393,46 @@ pub fn analyzeDeclRef(self: *Module, scope: *Scope, src: usize, decl: *Decl) Inn |
| 2217 | }; | 2393 | }; |
| 2218 | 2394 | ||
| 2219 | const decl_tv = try decl.typedValue(); | 2395 | const decl_tv = try decl.typedValue(); |
| 2220 | const ty_payload = try scope.arena().create(Type.Payload.Pointer); | 2396 | if (decl_tv.val.tag() == .variable) { |
| 2221 | ty_payload.* = .{ | 2397 | return self.getVarRef(scope, src, decl_tv); |
| 2222 | .base = .{ .tag = .single_const_pointer }, | 2398 | } |
| 2223 | .pointee_type = decl_tv.ty, | 2399 | const ty = try self.singlePtrType(scope, src, false, decl_tv.ty); |
| 2224 | }; | ||
| 2225 | const val_payload = try scope.arena().create(Value.Payload.DeclRef); | 2400 | const val_payload = try scope.arena().create(Value.Payload.DeclRef); |
| 2226 | val_payload.* = .{ .decl = decl }; | 2401 | val_payload.* = .{ .decl = decl }; |
| 2227 | 2402 | ||
| 2228 | return self.constInst(scope, src, .{ | 2403 | return self.constInst(scope, src, .{ |
| 2229 | .ty = Type.initPayload(&ty_payload.base), | 2404 | .ty = ty, |
| 2230 | .val = Value.initPayload(&val_payload.base), | 2405 | .val = Value.initPayload(&val_payload.base), |
| 2231 | }); | 2406 | }); |
| 2232 | } | 2407 | } |
| 2233 | 2408 | ||
| 2409 | fn getVarRef(self: *Module, scope: *Scope, src: usize, tv: TypedValue) InnerError!*Inst { | ||
| 2410 | const variable = tv.val.cast(Value.Payload.Variable).?.variable; | ||
| 2411 | |||
| 2412 | const ty = try self.singlePtrType(scope, src, variable.is_mutable, tv.ty); | ||
| 2413 | if (!variable.is_mutable and variable.value != null) { | ||
| 2414 | const val_payload = try scope.arena().create(Value.Payload.RefVal); | ||
| 2415 | val_payload.* = .{ .val = variable.value.? }; | ||
| 2416 | return self.constInst(scope, src, .{ | ||
| 2417 | .ty = ty, | ||
| 2418 | .val = Value.initPayload(&val_payload.base), | ||
| 2419 | }); | ||
| 2420 | } | ||
| 2421 | |||
| 2422 | const b = try self.requireRuntimeBlock(scope, src); | ||
| 2423 | const inst = try b.arena.create(Inst.VarPtr); | ||
| 2424 | inst.* = .{ | ||
| 2425 | .base = .{ | ||
| 2426 | .tag = .varptr, | ||
| 2427 | .ty = ty, | ||
| 2428 | .src = src, | ||
| 2429 | }, | ||
| 2430 | .variable = variable, | ||
| 2431 | }; | ||
| 2432 | try b.instructions.append(self.gpa, &inst.base); | ||
| 2433 | return &inst.base; | ||
| 2434 | } | ||
| 2435 | |||
| 2234 | pub fn analyzeDeref(self: *Module, scope: *Scope, src: usize, ptr: *Inst, ptr_src: usize) InnerError!*Inst { | 2436 | pub fn analyzeDeref(self: *Module, scope: *Scope, src: usize, ptr: *Inst, ptr_src: usize) InnerError!*Inst { |
| 2235 | const elem_ty = switch (ptr.ty.zigTypeTag()) { | 2437 | const elem_ty = switch (ptr.ty.zigTypeTag()) { |
| 2236 | .Pointer => ptr.ty.elemType(), | 2438 | .Pointer => ptr.ty.elemType(), |
src-self-hosted/codegen.zig+11| ... | @@ -684,6 +684,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { | ... | @@ -684,6 +684,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { |
| 684 | .unreach => return MCValue{ .unreach = {} }, | 684 | .unreach => return MCValue{ .unreach = {} }, |
| 685 | .unwrap_optional => return self.genUnwrapOptional(inst.castTag(.unwrap_optional).?), | 685 | .unwrap_optional => return self.genUnwrapOptional(inst.castTag(.unwrap_optional).?), |
| 686 | .wrap_optional => return self.genWrapOptional(inst.castTag(.wrap_optional).?), | 686 | .wrap_optional => return self.genWrapOptional(inst.castTag(.wrap_optional).?), |
| 687 | .varptr => return self.genVarPtr(inst.castTag(.varptr).?), | ||
| 687 | } | 688 | } |
| 688 | } | 689 | } |
| 689 | 690 | ||
| ... | @@ -858,6 +859,16 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { | ... | @@ -858,6 +859,16 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { |
| 858 | } | 859 | } |
| 859 | } | 860 | } |
| 860 | 861 | ||
| 862 | fn genVarPtr(self: *Self, inst: *ir.Inst.VarPtr) !MCValue { | ||
| 863 | // No side effects, so if it's unreferenced, do nothing. | ||
| 864 | if (inst.base.isUnused()) | ||
| 865 | return MCValue.dead; | ||
| 866 | |||
| 867 | switch (arch) { | ||
| 868 | else => return self.fail(inst.base.src, "TODO implement varptr for {}", .{self.target.cpu.arch}), | ||
| 869 | } | ||
| 870 | } | ||
| 871 | |||
| 861 | fn reuseOperand(inst: *ir.Inst, op_index: ir.Inst.DeathsBitIndex, mcv: MCValue) bool { | 872 | fn reuseOperand(inst: *ir.Inst, op_index: ir.Inst.DeathsBitIndex, mcv: MCValue) bool { |
| 862 | if (!inst.operandDies(op_index) or !mcv.isMutable()) | 873 | if (!inst.operandDies(op_index) or !mcv.isMutable()) |
| 863 | return false; | 874 | return false; |
src-self-hosted/ir.zig+16| ... | @@ -81,6 +81,7 @@ pub const Inst = struct { | ... | @@ -81,6 +81,7 @@ pub const Inst = struct { |
| 81 | ref, | 81 | ref, |
| 82 | ret, | 82 | ret, |
| 83 | retvoid, | 83 | retvoid, |
| 84 | varptr, | ||
| 84 | /// Write a value to a pointer. LHS is pointer, RHS is value. | 85 | /// Write a value to a pointer. LHS is pointer, RHS is value. |
| 85 | store, | 86 | store, |
| 86 | sub, | 87 | sub, |
| ... | @@ -135,6 +136,7 @@ pub const Inst = struct { | ... | @@ -135,6 +136,7 @@ pub const Inst = struct { |
| 135 | .condbr => CondBr, | 136 | .condbr => CondBr, |
| 136 | .constant => Constant, | 137 | .constant => Constant, |
| 137 | .loop => Loop, | 138 | .loop => Loop, |
| 139 | .varptr => VarPtr, | ||
| 138 | }; | 140 | }; |
| 139 | } | 141 | } |
| 140 | 142 | ||
| ... | @@ -434,6 +436,20 @@ pub const Inst = struct { | ... | @@ -434,6 +436,20 @@ pub const Inst = struct { |
| 434 | return null; | 436 | return null; |
| 435 | } | 437 | } |
| 436 | }; | 438 | }; |
| 439 | |||
| 440 | pub const VarPtr = struct { | ||
| 441 | pub const base_tag = Tag.varptr; | ||
| 442 | |||
| 443 | base: Inst, | ||
| 444 | variable: *Module.Var, | ||
| 445 | |||
| 446 | pub fn operandCount(self: *const VarPtr) usize { | ||
| 447 | return 0; | ||
| 448 | } | ||
| 449 | pub fn getOperand(self: *const VarPtr, index: usize) ?*Inst { | ||
| 450 | return null; | ||
| 451 | } | ||
| 452 | }; | ||
| 437 | }; | 453 | }; |
| 438 | 454 | ||
| 439 | pub const Body = struct { | 455 | pub const Body = struct { |
src-self-hosted/type.zig+3-3| ... | @@ -1074,7 +1074,7 @@ pub const Type = extern union { | ... | @@ -1074,7 +1074,7 @@ pub const Type = extern union { |
| 1074 | } | 1074 | } |
| 1075 | 1075 | ||
| 1076 | /// Returns if type can be used for a runtime variable | 1076 | /// Returns if type can be used for a runtime variable |
| 1077 | pub fn isValidVarType(self: Type) bool { | 1077 | pub fn isValidVarType(self: Type, is_extern: bool) bool { |
| 1078 | var ty = self; | 1078 | var ty = self; |
| 1079 | while (true) switch (ty.zigTypeTag()) { | 1079 | while (true) switch (ty.zigTypeTag()) { |
| 1080 | .Bool, | 1080 | .Bool, |
| ... | @@ -1087,6 +1087,7 @@ pub const Type = extern union { | ... | @@ -1087,6 +1087,7 @@ pub const Type = extern union { |
| 1087 | .Vector, | 1087 | .Vector, |
| 1088 | => return true, | 1088 | => return true, |
| 1089 | 1089 | ||
| 1090 | .Opaque => return is_extern, | ||
| 1090 | .BoundFn, | 1091 | .BoundFn, |
| 1091 | .ComptimeFloat, | 1092 | .ComptimeFloat, |
| 1092 | .ComptimeInt, | 1093 | .ComptimeInt, |
| ... | @@ -1096,12 +1097,11 @@ pub const Type = extern union { | ... | @@ -1096,12 +1097,11 @@ pub const Type = extern union { |
| 1096 | .Void, | 1097 | .Void, |
| 1097 | .Undefined, | 1098 | .Undefined, |
| 1098 | .Null, | 1099 | .Null, |
| 1099 | .Opaque, | ||
| 1100 | => return false, | 1100 | => return false, |
| 1101 | 1101 | ||
| 1102 | .Optional => { | 1102 | .Optional => { |
| 1103 | var buf: Payload.Pointer = undefined; | 1103 | var buf: Payload.Pointer = undefined; |
| 1104 | return ty.optionalChild(&buf).isValidVarType(); | 1104 | return ty.optionalChild(&buf).isValidVarType(is_extern); |
| 1105 | }, | 1105 | }, |
| 1106 | .Pointer, .Array => ty = ty.elemType(), | 1106 | .Pointer, .Array => ty = ty.elemType(), |
| 1107 | 1107 |
src-self-hosted/value.zig+19| ... | @@ -79,6 +79,7 @@ pub const Value = extern union { | ... | @@ -79,6 +79,7 @@ pub const Value = extern union { |
| 79 | int_big_positive, | 79 | int_big_positive, |
| 80 | int_big_negative, | 80 | int_big_negative, |
| 81 | function, | 81 | function, |
| 82 | variable, | ||
| 82 | ref_val, | 83 | ref_val, |
| 83 | decl_ref, | 84 | decl_ref, |
| 84 | elem_ptr, | 85 | elem_ptr, |
| ... | @@ -196,6 +197,7 @@ pub const Value = extern union { | ... | @@ -196,6 +197,7 @@ pub const Value = extern union { |
| 196 | @panic("TODO implement copying of big ints"); | 197 | @panic("TODO implement copying of big ints"); |
| 197 | }, | 198 | }, |
| 198 | .function => return self.copyPayloadShallow(allocator, Payload.Function), | 199 | .function => return self.copyPayloadShallow(allocator, Payload.Function), |
| 200 | .variable => return self.copyPayloadShallow(allocator, Payload.Variable), | ||
| 199 | .ref_val => { | 201 | .ref_val => { |
| 200 | const payload = @fieldParentPtr(Payload.RefVal, "base", self.ptr_otherwise); | 202 | const payload = @fieldParentPtr(Payload.RefVal, "base", self.ptr_otherwise); |
| 201 | const new_payload = try allocator.create(Payload.RefVal); | 203 | const new_payload = try allocator.create(Payload.RefVal); |
| ... | @@ -310,6 +312,7 @@ pub const Value = extern union { | ... | @@ -310,6 +312,7 @@ pub const Value = extern union { |
| 310 | .int_big_positive => return out_stream.print("{}", .{val.cast(Payload.IntBigPositive).?.asBigInt()}), | 312 | .int_big_positive => return out_stream.print("{}", .{val.cast(Payload.IntBigPositive).?.asBigInt()}), |
| 311 | .int_big_negative => return out_stream.print("{}", .{val.cast(Payload.IntBigNegative).?.asBigInt()}), | 313 | .int_big_negative => return out_stream.print("{}", .{val.cast(Payload.IntBigNegative).?.asBigInt()}), |
| 312 | .function => return out_stream.writeAll("(function)"), | 314 | .function => return out_stream.writeAll("(function)"), |
| 315 | .variable => return out_stream.writeAll("(variable)"), | ||
| 313 | .ref_val => { | 316 | .ref_val => { |
| 314 | const ref_val = val.cast(Payload.RefVal).?; | 317 | const ref_val = val.cast(Payload.RefVal).?; |
| 315 | try out_stream.writeAll("&const "); | 318 | try out_stream.writeAll("&const "); |
| ... | @@ -410,6 +413,7 @@ pub const Value = extern union { | ... | @@ -410,6 +413,7 @@ pub const Value = extern union { |
| 410 | .int_big_positive, | 413 | .int_big_positive, |
| 411 | .int_big_negative, | 414 | .int_big_negative, |
| 412 | .function, | 415 | .function, |
| 416 | .variable, | ||
| 413 | .ref_val, | 417 | .ref_val, |
| 414 | .decl_ref, | 418 | .decl_ref, |
| 415 | .elem_ptr, | 419 | .elem_ptr, |
| ... | @@ -471,6 +475,7 @@ pub const Value = extern union { | ... | @@ -471,6 +475,7 @@ pub const Value = extern union { |
| 471 | .enum_literal_type, | 475 | .enum_literal_type, |
| 472 | .null_value, | 476 | .null_value, |
| 473 | .function, | 477 | .function, |
| 478 | .variable, | ||
| 474 | .ref_val, | 479 | .ref_val, |
| 475 | .decl_ref, | 480 | .decl_ref, |
| 476 | .elem_ptr, | 481 | .elem_ptr, |
| ... | @@ -548,6 +553,7 @@ pub const Value = extern union { | ... | @@ -548,6 +553,7 @@ pub const Value = extern union { |
| 548 | .enum_literal_type, | 553 | .enum_literal_type, |
| 549 | .null_value, | 554 | .null_value, |
| 550 | .function, | 555 | .function, |
| 556 | .variable, | ||
| 551 | .ref_val, | 557 | .ref_val, |
| 552 | .decl_ref, | 558 | .decl_ref, |
| 553 | .elem_ptr, | 559 | .elem_ptr, |
| ... | @@ -625,6 +631,7 @@ pub const Value = extern union { | ... | @@ -625,6 +631,7 @@ pub const Value = extern union { |
| 625 | .enum_literal_type, | 631 | .enum_literal_type, |
| 626 | .null_value, | 632 | .null_value, |
| 627 | .function, | 633 | .function, |
| 634 | .variable, | ||
| 628 | .ref_val, | 635 | .ref_val, |
| 629 | .decl_ref, | 636 | .decl_ref, |
| 630 | .elem_ptr, | 637 | .elem_ptr, |
| ... | @@ -728,6 +735,7 @@ pub const Value = extern union { | ... | @@ -728,6 +735,7 @@ pub const Value = extern union { |
| 728 | .enum_literal_type, | 735 | .enum_literal_type, |
| 729 | .null_value, | 736 | .null_value, |
| 730 | .function, | 737 | .function, |
| 738 | .variable, | ||
| 731 | .ref_val, | 739 | .ref_val, |
| 732 | .decl_ref, | 740 | .decl_ref, |
| 733 | .elem_ptr, | 741 | .elem_ptr, |
| ... | @@ -810,6 +818,7 @@ pub const Value = extern union { | ... | @@ -810,6 +818,7 @@ pub const Value = extern union { |
| 810 | .enum_literal_type, | 818 | .enum_literal_type, |
| 811 | .null_value, | 819 | .null_value, |
| 812 | .function, | 820 | .function, |
| 821 | .variable, | ||
| 813 | .ref_val, | 822 | .ref_val, |
| 814 | .decl_ref, | 823 | .decl_ref, |
| 815 | .elem_ptr, | 824 | .elem_ptr, |
| ... | @@ -974,6 +983,7 @@ pub const Value = extern union { | ... | @@ -974,6 +983,7 @@ pub const Value = extern union { |
| 974 | .bool_false, | 983 | .bool_false, |
| 975 | .null_value, | 984 | .null_value, |
| 976 | .function, | 985 | .function, |
| 986 | .variable, | ||
| 977 | .ref_val, | 987 | .ref_val, |
| 978 | .decl_ref, | 988 | .decl_ref, |
| 979 | .elem_ptr, | 989 | .elem_ptr, |
| ... | @@ -1046,6 +1056,7 @@ pub const Value = extern union { | ... | @@ -1046,6 +1056,7 @@ pub const Value = extern union { |
| 1046 | .enum_literal_type, | 1056 | .enum_literal_type, |
| 1047 | .null_value, | 1057 | .null_value, |
| 1048 | .function, | 1058 | .function, |
| 1059 | .variable, | ||
| 1049 | .ref_val, | 1060 | .ref_val, |
| 1050 | .decl_ref, | 1061 | .decl_ref, |
| 1051 | .elem_ptr, | 1062 | .elem_ptr, |
| ... | @@ -1182,6 +1193,7 @@ pub const Value = extern union { | ... | @@ -1182,6 +1193,7 @@ pub const Value = extern union { |
| 1182 | .bool_false, | 1193 | .bool_false, |
| 1183 | .null_value, | 1194 | .null_value, |
| 1184 | .function, | 1195 | .function, |
| 1196 | .variable, | ||
| 1185 | .int_u64, | 1197 | .int_u64, |
| 1186 | .int_i64, | 1198 | .int_i64, |
| 1187 | .int_big_positive, | 1199 | .int_big_positive, |
| ... | @@ -1260,6 +1272,7 @@ pub const Value = extern union { | ... | @@ -1260,6 +1272,7 @@ pub const Value = extern union { |
| 1260 | .bool_false, | 1272 | .bool_false, |
| 1261 | .null_value, | 1273 | .null_value, |
| 1262 | .function, | 1274 | .function, |
| 1275 | .variable, | ||
| 1263 | .int_u64, | 1276 | .int_u64, |
| 1264 | .int_i64, | 1277 | .int_i64, |
| 1265 | .int_big_positive, | 1278 | .int_big_positive, |
| ... | @@ -1355,6 +1368,7 @@ pub const Value = extern union { | ... | @@ -1355,6 +1368,7 @@ pub const Value = extern union { |
| 1355 | .bool_true, | 1368 | .bool_true, |
| 1356 | .bool_false, | 1369 | .bool_false, |
| 1357 | .function, | 1370 | .function, |
| 1371 | .variable, | ||
| 1358 | .int_u64, | 1372 | .int_u64, |
| 1359 | .int_i64, | 1373 | .int_i64, |
| 1360 | .int_big_positive, | 1374 | .int_big_positive, |
| ... | @@ -1429,6 +1443,11 @@ pub const Value = extern union { | ... | @@ -1429,6 +1443,11 @@ pub const Value = extern union { |
| 1429 | func: *Module.Fn, | 1443 | func: *Module.Fn, |
| 1430 | }; | 1444 | }; |
| 1431 | 1445 | ||
| 1446 | pub const Variable = struct { | ||
| 1447 | base: Payload = Payload{ .tag = .variable }, | ||
| 1448 | variable: *Module.Var, | ||
| 1449 | }; | ||
| 1450 | |||
| 1432 | pub const ArraySentinel0_u8_Type = struct { | 1451 | pub const ArraySentinel0_u8_Type = struct { |
| 1433 | base: Payload = Payload{ .tag = .array_sentinel_0_u8_type }, | 1452 | base: Payload = Payload{ .tag = .array_sentinel_0_u8_type }, |
| 1434 | len: u64, | 1453 | len: u64, |
src-self-hosted/zir.zig+5| ... | @@ -1752,6 +1752,9 @@ const EmitZIR = struct { | ... | @@ -1752,6 +1752,9 @@ const EmitZIR = struct { |
| 1752 | const decl_ref = try self.emitDeclRef(inst.src, declref.decl); | 1752 | const decl_ref = try self.emitDeclRef(inst.src, declref.decl); |
| 1753 | try new_body.instructions.append(decl_ref); | 1753 | try new_body.instructions.append(decl_ref); |
| 1754 | break :blk decl_ref; | 1754 | break :blk decl_ref; |
| 1755 | } else if (const_inst.val.cast(Value.Payload.Variable)) |var_pl| blk: { | ||
| 1756 | const owner_decl = var_pl.variable.owner_decl; | ||
| 1757 | break :blk try self.emitDeclVal(inst.src, mem.spanZ(owner_decl.name)); | ||
| 1755 | } else blk: { | 1758 | } else blk: { |
| 1756 | break :blk (try self.emitTypedValue(inst.src, .{ .ty = inst.ty, .val = const_inst.val })).inst; | 1759 | break :blk (try self.emitTypedValue(inst.src, .{ .ty = inst.ty, .val = const_inst.val })).inst; |
| 1757 | }; | 1760 | }; |
| ... | @@ -2311,6 +2314,8 @@ const EmitZIR = struct { | ... | @@ -2311,6 +2314,8 @@ const EmitZIR = struct { |
| 2311 | }; | 2314 | }; |
| 2312 | break :blk &new_inst.base; | 2315 | break :blk &new_inst.base; |
| 2313 | }, | 2316 | }, |
| 2317 | |||
| 2318 | .varptr => @panic("TODO"), | ||
| 2314 | }; | 2319 | }; |
| 2315 | try self.metadata.put(new_inst, .{ .deaths = inst.deaths }); | 2320 | try self.metadata.put(new_inst, .{ .deaths = inst.deaths }); |
| 2316 | try instructions.append(new_inst); | 2321 | try instructions.append(new_inst); |
src-self-hosted/zir_sema.zig+2-2| ... | @@ -366,7 +366,7 @@ fn analyzeInstEnsureResultNonError(mod: *Module, scope: *Scope, inst: *zir.Inst. | ... | @@ -366,7 +366,7 @@ fn analyzeInstEnsureResultNonError(mod: *Module, scope: *Scope, inst: *zir.Inst. |
| 366 | fn analyzeInstAlloc(mod: *Module, scope: *Scope, inst: *zir.Inst.UnOp) InnerError!*Inst { | 366 | fn analyzeInstAlloc(mod: *Module, scope: *Scope, inst: *zir.Inst.UnOp) InnerError!*Inst { |
| 367 | const var_type = try resolveType(mod, scope, inst.positionals.operand); | 367 | const var_type = try resolveType(mod, scope, inst.positionals.operand); |
| 368 | // TODO this should happen only for var allocs | 368 | // TODO this should happen only for var allocs |
| 369 | if (!var_type.isValidVarType()) { | 369 | if (!var_type.isValidVarType(false)) { |
| 370 | return mod.fail(scope, inst.base.src, "variable of type '{}' must be const or comptime", .{var_type}); | 370 | return mod.fail(scope, inst.base.src, "variable of type '{}' must be const or comptime", .{var_type}); |
| 371 | } | 371 | } |
| 372 | const ptr_type = try mod.singlePtrType(scope, inst.base.src, true, var_type); | 372 | const ptr_type = try mod.singlePtrType(scope, inst.base.src, true, var_type); |
| ... | @@ -779,7 +779,7 @@ fn analyzeInstFnType(mod: *Module, scope: *Scope, fntype: *zir.Inst.FnType) Inne | ... | @@ -779,7 +779,7 @@ fn analyzeInstFnType(mod: *Module, scope: *Scope, fntype: *zir.Inst.FnType) Inne |
| 779 | for (fntype.positionals.param_types) |param_type, i| { | 779 | for (fntype.positionals.param_types) |param_type, i| { |
| 780 | const resolved = try resolveType(mod, scope, param_type); | 780 | const resolved = try resolveType(mod, scope, param_type); |
| 781 | // TODO skip for comptime params | 781 | // TODO skip for comptime params |
| 782 | if (!resolved.isValidVarType()) { | 782 | if (!resolved.isValidVarType(false)) { |
| 783 | return mod.fail(scope, param_type.src, "parameter of type '{}' must be declared comptime", .{resolved}); | 783 | return mod.fail(scope, param_type.src, "parameter of type '{}' must be declared comptime", .{resolved}); |
| 784 | } | 784 | } |
| 785 | param_types[i] = resolved; | 785 | param_types[i] = resolved; |