authorgravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2020-08-19 13:56:48+03:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-08-19 16:12:29-07:00
log338a495648f07a2734e012034fd301a0e77f8202
tree020b47ea8f5e7a6f8906de9424cda1828d05ceca
parentb0846b6ecbb3e2557c5c95ddee04ecc055881d75

stage2: implement global variables


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};
322322
323pub const Var = struct {
324 value: ?Value,
325 owner_decl: *Decl,
326 is_mutable: bool,
327};
328
323pub const Scope = struct {329pub const Scope = struct {
324 tag: Tag,330 tag: Tag,
325331
...@@ -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 };
22182394
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 };
22272402
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}
22332408
2409fn 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
2234pub fn analyzeDeref(self: *Module, scope: *Scope, src: usize, ptr: *Inst, ptr_src: usize) InnerError!*Inst {2436pub 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 }
689690
...@@ -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 }
860861
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 }
140142
...@@ -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};
438454
439pub const Body = struct {455pub 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 }
10751075
1076 /// Returns if type can be used for a runtime variable1076 /// 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,
10891089
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,
11011101
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(),
11071107
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 };
14311445
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.
366fn analyzeInstAlloc(mod: *Module, scope: *Scope, inst: *zir.Inst.UnOp) InnerError!*Inst {366fn 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 allocs368 // 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 params781 // 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;