authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-08-19 17:59:37-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-08-19 17:59:37-07:00
loga30950706f858e052376fb2d526895970f59d0ca
tree31f0da7dad51bcf707cba8555d7aa33f0ab0a1ba
parentb0846b6ecbb3e2557c5c95ddee04ecc055881d75
parent9ec9c0f5e57820f4baa04b9674a6a4a88235b863

Merge branch 'Vexu-stage2'

closes #6093

9 files changed, 415 insertions(+), 23 deletions(-)

src-self-hosted/Module.zig+240-8
...@@ -170,6 +170,9 @@ pub const Decl = struct {...@@ -170,6 +170,9 @@ pub const Decl = struct {
170 /// This flag is set when this Decl is added to a check_for_deletion set, and cleared170 /// This flag is set when this Decl is added to a check_for_deletion set, and cleared
171 /// when removed.171 /// when removed.
172 deletion_flag: bool,172 deletion_flag: bool,
173 /// Whether the corresponding AST decl has a `pub` keyword.
174 is_pub: bool,
175
173 /// An integer that can be checked against the corresponding incrementing176 /// An integer that can be checked against the corresponding incrementing
174 /// generation field of Module. This is used to determine whether `complete` status177 /// generation field of Module. This is used to determine whether `complete` status
175 /// represents pre- or post- re-analysis.178 /// represents pre- or post- re-analysis.
...@@ -320,6 +323,16 @@ pub const Fn = struct {...@@ -320,6 +323,16 @@ pub const Fn = struct {
320 }323 }
321};324};
322325
326pub const Var = struct {
327 init: Value,
328 owner_decl: *Decl,
329
330 has_init: bool,
331 is_extern: bool,
332 is_mutable: bool,
333 is_threadlocal: bool,
334};
335
323pub const Scope = struct {336pub const Scope = struct {
324 tag: Tag,337 tag: Tag,
325338
...@@ -1235,6 +1248,7 @@ fn astGenAndAnalyzeDecl(self: *Module, decl: *Decl) !bool {...@@ -1235,6 +1248,7 @@ fn astGenAndAnalyzeDecl(self: *Module, decl: *Decl) !bool {
1235 };1248 };
1236 defer fn_type_scope.instructions.deinit(self.gpa);1249 defer fn_type_scope.instructions.deinit(self.gpa);
12371250
1251 decl.is_pub = fn_proto.getTrailer("visib_token") != null;
1238 const body_node = fn_proto.getTrailer("body_node") orelse1252 const body_node = fn_proto.getTrailer("body_node") orelse
1239 return self.failTok(&fn_type_scope.base, fn_proto.fn_token, "TODO implement extern functions", .{});1253 return self.failTok(&fn_type_scope.base, fn_proto.fn_token, "TODO implement extern functions", .{});
12401254
...@@ -1419,7 +1433,173 @@ fn astGenAndAnalyzeDecl(self: *Module, decl: *Decl) !bool {...@@ -1419,7 +1433,173 @@ fn astGenAndAnalyzeDecl(self: *Module, decl: *Decl) !bool {
1419 }1433 }
1420 return type_changed;1434 return type_changed;
1421 },1435 },
1422 .VarDecl => @panic("TODO var decl"),1436 .VarDecl => {
1437 const var_decl = @fieldParentPtr(ast.Node.VarDecl, "base", ast_node);
1438
1439 decl.analysis = .in_progress;
1440
1441 // We need the memory for the Type to go into the arena for the Decl
1442 var decl_arena = std.heap.ArenaAllocator.init(self.gpa);
1443 errdefer decl_arena.deinit();
1444 const decl_arena_state = try decl_arena.allocator.create(std.heap.ArenaAllocator.State);
1445
1446 var block_scope: Scope.Block = .{
1447 .parent = null,
1448 .func = null,
1449 .decl = decl,
1450 .instructions = .{},
1451 .arena = &decl_arena.allocator,
1452 };
1453 defer block_scope.instructions.deinit(self.gpa);
1454
1455 decl.is_pub = var_decl.getTrailer("visib_token") != null;
1456 const is_extern = blk: {
1457 const maybe_extern_token = var_decl.getTrailer("extern_export_token") orelse
1458 break :blk false;
1459 break :blk tree.token_ids[maybe_extern_token] == .Keyword_extern;
1460 };
1461 if (var_decl.getTrailer("lib_name")) |lib_name| {
1462 assert(is_extern);
1463 return self.failNode(&block_scope.base, lib_name, "TODO implement function library name", .{});
1464 }
1465 const is_mutable = tree.token_ids[var_decl.mut_token] == .Keyword_var;
1466 const is_threadlocal = if (var_decl.getTrailer("thread_local_token")) |some| blk: {
1467 if (!is_mutable) {
1468 return self.failTok(&block_scope.base, some, "threadlocal variable cannot be constant", .{});
1469 }
1470 break :blk true;
1471 } else false;
1472 assert(var_decl.getTrailer("comptime_token") == null);
1473 if (var_decl.getTrailer("align_node")) |align_expr| {
1474 return self.failNode(&block_scope.base, align_expr, "TODO implement function align expression", .{});
1475 }
1476 if (var_decl.getTrailer("section_node")) |sect_expr| {
1477 return self.failNode(&block_scope.base, sect_expr, "TODO implement function section expression", .{});
1478 }
1479
1480 const explicit_type = blk: {
1481 const type_node = var_decl.getTrailer("type_node") orelse
1482 break :blk null;
1483
1484 var type_scope_arena = std.heap.ArenaAllocator.init(self.gpa);
1485 defer type_scope_arena.deinit();
1486 var type_scope: Scope.GenZIR = .{
1487 .decl = decl,
1488 .arena = &type_scope_arena.allocator,
1489 .parent = decl.scope,
1490 };
1491 defer type_scope.instructions.deinit(self.gpa);
1492
1493 const src = tree.token_locs[type_node.firstToken()].start;
1494 const type_type = try astgen.addZIRInstConst(self, &type_scope.base, src, .{
1495 .ty = Type.initTag(.type),
1496 .val = Value.initTag(.type_type),
1497 });
1498 const var_type = try astgen.expr(self, &type_scope.base, .{ .ty = type_type }, type_node);
1499 _ = try astgen.addZIRUnOp(self, &type_scope.base, src, .@"return", var_type);
1500
1501 break :blk try zir_sema.analyzeBodyValueAsType(self, &block_scope, .{
1502 .instructions = type_scope.instructions.items,
1503 });
1504 };
1505
1506 var var_type: Type = undefined;
1507 const value: ?Value = if (var_decl.getTrailer("init_node")) |init_node| blk: {
1508 var gen_scope_arena = std.heap.ArenaAllocator.init(self.gpa);
1509 defer gen_scope_arena.deinit();
1510 var gen_scope: Scope.GenZIR = .{
1511 .decl = decl,
1512 .arena = &gen_scope_arena.allocator,
1513 .parent = decl.scope,
1514 };
1515 defer gen_scope.instructions.deinit(self.gpa);
1516 const src = tree.token_locs[init_node.firstToken()].start;
1517
1518 // TODO comptime scope here
1519 const init_inst = try astgen.expr(self, &gen_scope.base, .none, init_node);
1520 _ = try astgen.addZIRUnOp(self, &gen_scope.base, src, .@"return", init_inst);
1521
1522 var inner_block: Scope.Block = .{
1523 .parent = null,
1524 .func = null,
1525 .decl = decl,
1526 .instructions = .{},
1527 .arena = &gen_scope_arena.allocator,
1528 };
1529 defer inner_block.instructions.deinit(self.gpa);
1530 try zir_sema.analyzeBody(self, &inner_block.base, .{ .instructions = gen_scope.instructions.items });
1531
1532 for (inner_block.instructions.items) |inst| {
1533 if (inst.castTag(.ret)) |ret| {
1534 const coerced = if (explicit_type) |some|
1535 try self.coerce(&inner_block.base, some, ret.operand)
1536 else
1537 ret.operand;
1538 const val = try self.resolveConstValue(&inner_block.base, coerced);
1539
1540 var_type = explicit_type orelse try ret.operand.ty.copy(block_scope.arena);
1541 break :blk try val.copy(block_scope.arena);
1542 } else {
1543 return self.fail(&block_scope.base, inst.src, "unable to resolve comptime value", .{});
1544 }
1545 }
1546 unreachable;
1547 } else if (!is_extern) {
1548 return self.failTok(&block_scope.base, var_decl.firstToken(), "variables must be initialized", .{});
1549 } else if (explicit_type) |some| blk: {
1550 var_type = some;
1551 break :blk null;
1552 } else {
1553 return self.failTok(&block_scope.base, var_decl.firstToken(), "unable to infer variable type", .{});
1554 };
1555
1556 if (is_mutable and !var_type.isValidVarType(is_extern)) {
1557 return self.failTok(&block_scope.base, var_decl.firstToken(), "variable of type '{}' must be const", .{var_type});
1558 }
1559
1560 var type_changed = true;
1561 if (decl.typedValueManaged()) |tvm| {
1562 type_changed = !tvm.typed_value.ty.eql(var_type);
1563
1564 tvm.deinit(self.gpa);
1565 }
1566
1567 const new_variable = try decl_arena.allocator.create(Var);
1568 const var_payload = try decl_arena.allocator.create(Value.Payload.Variable);
1569 new_variable.* = .{
1570 .owner_decl = decl,
1571 .init = value orelse undefined,
1572 .has_init = value != null,
1573 .is_extern = is_extern,
1574 .is_mutable = is_mutable,
1575 .is_threadlocal = is_threadlocal,
1576 };
1577 var_payload.* = .{ .variable = new_variable };
1578
1579 decl_arena_state.* = decl_arena.state;
1580 decl.typed_value = .{
1581 .most_recent = .{
1582 .typed_value = .{
1583 .ty = var_type,
1584 .val = Value.initPayload(&var_payload.base),
1585 },
1586 .arena = decl_arena_state,
1587 },
1588 };
1589 decl.analysis = .complete;
1590 decl.generation = self.generation;
1591
1592 if (var_decl.getTrailer("extern_export_token")) |maybe_export_token| {
1593 if (tree.token_ids[maybe_export_token] == .Keyword_export) {
1594 const export_src = tree.token_locs[maybe_export_token].start;
1595 const name_loc = tree.token_locs[var_decl.name_token];
1596 const name = tree.tokenSliceLoc(name_loc);
1597 // The scope needs to have the decl in it.
1598 try self.analyzeExport(&block_scope.base, export_src, name, decl);
1599 }
1600 }
1601 return type_changed;
1602 },
1423 .Comptime => @panic("TODO comptime decl"),1603 .Comptime => @panic("TODO comptime decl"),
1424 .Use => @panic("TODO usingnamespace decl"),1604 .Use => @panic("TODO usingnamespace decl"),
1425 else => unreachable,1605 else => unreachable,
...@@ -1584,7 +1764,32 @@ fn analyzeRootSrcFile(self: *Module, root_scope: *Scope.File) !void {...@@ -1584,7 +1764,32 @@ fn analyzeRootSrcFile(self: *Module, root_scope: *Scope.File) !void {
1584 }1764 }
1585 }1765 }
1586 } else if (src_decl.castTag(.VarDecl)) |var_decl| {1766 } else if (src_decl.castTag(.VarDecl)) |var_decl| {
1587 log.err("TODO: analyze var decl", .{});1767 const name_loc = tree.token_locs[var_decl.name_token];
1768 const name = tree.tokenSliceLoc(name_loc);
1769 const name_hash = root_scope.fullyQualifiedNameHash(name);
1770 const contents_hash = std.zig.hashSrc(tree.getNodeSource(src_decl));
1771 if (self.decl_table.get(name_hash)) |decl| {
1772 // Update the AST Node index of the decl, even if its contents are unchanged, it may
1773 // have been re-ordered.
1774 decl.src_index = decl_i;
1775 if (deleted_decls.remove(decl) == null) {
1776 decl.analysis = .sema_failure;
1777 const err_msg = try ErrorMsg.create(self.gpa, name_loc.start, "redefinition of '{}'", .{decl.name});
1778 errdefer err_msg.destroy(self.gpa);
1779 try self.failed_decls.putNoClobber(self.gpa, decl, err_msg);
1780 } else if (!srcHashEql(decl.contents_hash, contents_hash)) {
1781 try self.markOutdatedDecl(decl);
1782 decl.contents_hash = contents_hash;
1783 }
1784 } else {
1785 const new_decl = try self.createNewDecl(&root_scope.base, name, decl_i, name_hash, contents_hash);
1786 root_scope.decls.appendAssumeCapacity(new_decl);
1787 if (var_decl.getTrailer("extern_export_token")) |maybe_export_token| {
1788 if (tree.token_ids[maybe_export_token] == .Keyword_export) {
1789 self.work_queue.writeItemAssumeCapacity(.{ .analyze_decl = new_decl });
1790 }
1791 }
1792 }
1588 } else if (src_decl.castTag(.Comptime)) |comptime_node| {1793 } else if (src_decl.castTag(.Comptime)) |comptime_node| {
1589 log.err("TODO: analyze comptime decl", .{});1794 log.err("TODO: analyze comptime decl", .{});
1590 } else if (src_decl.castTag(.ContainerField)) |container_field| {1795 } else if (src_decl.castTag(.ContainerField)) |container_field| {
...@@ -1798,6 +2003,7 @@ fn allocateNewDecl(...@@ -1798,6 +2003,7 @@ fn allocateNewDecl(
1798 .wasm => .{ .wasm = null },2003 .wasm => .{ .wasm = null },
1799 },2004 },
1800 .generation = 0,2005 .generation = 0,
2006 .is_pub = false,
1801 };2007 };
1802 return new_decl;2008 return new_decl;
1803}2009}
...@@ -2217,20 +2423,46 @@ pub fn analyzeDeclRef(self: *Module, scope: *Scope, src: usize, decl: *Decl) Inn...@@ -2217,20 +2423,46 @@ pub fn analyzeDeclRef(self: *Module, scope: *Scope, src: usize, decl: *Decl) Inn
2217 };2423 };
22182424
2219 const decl_tv = try decl.typedValue();2425 const decl_tv = try decl.typedValue();
2220 const ty_payload = try scope.arena().create(Type.Payload.Pointer);2426 if (decl_tv.val.tag() == .variable) {
2221 ty_payload.* = .{2427 return self.analyzeVarRef(scope, src, decl_tv);
2222 .base = .{ .tag = .single_const_pointer },2428 }
2223 .pointee_type = decl_tv.ty,2429 const ty = try self.singlePtrType(scope, src, false, decl_tv.ty);
2224 };
2225 const val_payload = try scope.arena().create(Value.Payload.DeclRef);2430 const val_payload = try scope.arena().create(Value.Payload.DeclRef);
2226 val_payload.* = .{ .decl = decl };2431 val_payload.* = .{ .decl = decl };
22272432
2228 return self.constInst(scope, src, .{2433 return self.constInst(scope, src, .{
2229 .ty = Type.initPayload(&ty_payload.base),2434 .ty = ty,
2230 .val = Value.initPayload(&val_payload.base),2435 .val = Value.initPayload(&val_payload.base),
2231 });2436 });
2232}2437}
22332438
2439fn analyzeVarRef(self: *Module, scope: *Scope, src: usize, tv: TypedValue) InnerError!*Inst {
2440 const variable = tv.val.cast(Value.Payload.Variable).?.variable;
2441
2442 const ty = try self.singlePtrType(scope, src, variable.is_mutable, tv.ty);
2443 if (!variable.is_mutable and !variable.is_extern and variable.has_init) {
2444 const val_payload = try scope.arena().create(Value.Payload.RefVal);
2445 val_payload.* = .{ .val = variable.init };
2446 return self.constInst(scope, src, .{
2447 .ty = ty,
2448 .val = Value.initPayload(&val_payload.base),
2449 });
2450 }
2451
2452 const b = try self.requireRuntimeBlock(scope, src);
2453 const inst = try b.arena.create(Inst.VarPtr);
2454 inst.* = .{
2455 .base = .{
2456 .tag = .varptr,
2457 .ty = ty,
2458 .src = src,
2459 },
2460 .variable = variable,
2461 };
2462 try b.instructions.append(self.gpa, &inst.base);
2463 return &inst.base;
2464}
2465
2234pub fn analyzeDeref(self: *Module, scope: *Scope, src: usize, ptr: *Inst, ptr_src: usize) InnerError!*Inst {2466pub fn analyzeDeref(self: *Module, scope: *Scope, src: usize, ptr: *Inst, ptr_src: usize) InnerError!*Inst {
2235 const elem_ty = switch (ptr.ty.zigTypeTag()) {2467 const elem_ty = switch (ptr.ty.zigTypeTag()) {
2236 .Pointer => ptr.ty.elemType(),2468 .Pointer => ptr.ty.elemType(),
src-self-hosted/astgen.zig+8-6
...@@ -1223,9 +1223,10 @@ fn identifier(mod: *Module, scope: *Scope, rl: ResultLoc, ident: *ast.Node.OneTo...@@ -1223,9 +1223,10 @@ fn identifier(mod: *Module, scope: *Scope, rl: ResultLoc, ident: *ast.Node.OneTo
1223 }1223 }
12241224
1225 if (mod.lookupDeclName(scope, ident_name)) |decl| {1225 if (mod.lookupDeclName(scope, ident_name)) |decl| {
1226 // TODO handle lvalues
1227 const result = try addZIRInst(mod, scope, src, zir.Inst.DeclValInModule, .{ .decl = decl }, .{});1226 const result = try addZIRInst(mod, scope, src, zir.Inst.DeclValInModule, .{ .decl = decl }, .{});
1228 return rlWrap(mod, scope, rl, result);1227 if (rl == .lvalue or rl == .ref)
1228 return result;
1229 return rlWrap(mod, scope, rl, try addZIRUnOp(mod, scope, src, .deref, result));
1229 }1230 }
12301231
1231 return mod.failNode(scope, &ident.base, "use of undeclared identifier '{}'", .{ident_name});1232 return mod.failNode(scope, &ident.base, "use of undeclared identifier '{}'", .{ident_name});
...@@ -1258,7 +1259,8 @@ fn multilineStrLiteral(mod: *Module, scope: *Scope, node: *ast.Node.MultilineStr...@@ -1258,7 +1259,8 @@ fn multilineStrLiteral(mod: *Module, scope: *Scope, node: *ast.Node.MultilineStr
1258 // line lengths and new lines1259 // line lengths and new lines
1259 var len = lines.len - 1;1260 var len = lines.len - 1;
1260 for (lines) |line| {1261 for (lines) |line| {
1261 len += tree.tokenSlice(line).len - 2;1262 // 2 for the '//' + 1 for '\n'
1263 len += tree.tokenSlice(line).len - 3;
1262 }1264 }
12631265
1264 const bytes = try scope.arena().alloc(u8, len);1266 const bytes = try scope.arena().alloc(u8, len);
...@@ -1268,9 +1270,9 @@ fn multilineStrLiteral(mod: *Module, scope: *Scope, node: *ast.Node.MultilineStr...@@ -1268,9 +1270,9 @@ fn multilineStrLiteral(mod: *Module, scope: *Scope, node: *ast.Node.MultilineStr
1268 bytes[i] = '\n';1270 bytes[i] = '\n';
1269 i += 1;1271 i += 1;
1270 }1272 }
1271 const slice = tree.tokenSlice(line)[2..];1273 const slice = tree.tokenSlice(line);
1272 mem.copy(u8, bytes[i..], slice);1274 mem.copy(u8, bytes[i..], slice[2..slice.len - 1]);
1273 i += slice.len;1275 i += slice.len - 3;
1274 }1276 }
12751277
1276 return addZIRInst(mod, scope, src, zir.Inst.Str, .{ .bytes = bytes }, .{});1278 return addZIRInst(mod, scope, src, zir.Inst.Str, .{ .bytes = bytes }, .{});
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+5-4
...@@ -457,7 +457,8 @@ pub const Type = extern union {...@@ -457,7 +457,8 @@ pub const Type = extern union {
457 try param_type.format("", .{}, out_stream);457 try param_type.format("", .{}, out_stream);
458 }458 }
459 try out_stream.writeAll(") ");459 try out_stream.writeAll(") ");
460 try payload.return_type.format("", .{}, out_stream);460 ty = payload.return_type;
461 continue;
461 },462 },
462463
463 .array_u8 => {464 .array_u8 => {
...@@ -1074,7 +1075,7 @@ pub const Type = extern union {...@@ -1074,7 +1075,7 @@ pub const Type = extern union {
1074 }1075 }
10751076
1076 /// Returns if type can be used for a runtime variable1077 /// Returns if type can be used for a runtime variable
1077 pub fn isValidVarType(self: Type) bool {1078 pub fn isValidVarType(self: Type, is_extern: bool) bool {
1078 var ty = self;1079 var ty = self;
1079 while (true) switch (ty.zigTypeTag()) {1080 while (true) switch (ty.zigTypeTag()) {
1080 .Bool,1081 .Bool,
...@@ -1087,6 +1088,7 @@ pub const Type = extern union {...@@ -1087,6 +1088,7 @@ pub const Type = extern union {
1087 .Vector,1088 .Vector,
1088 => return true,1089 => return true,
10891090
1091 .Opaque => return is_extern,
1090 .BoundFn,1092 .BoundFn,
1091 .ComptimeFloat,1093 .ComptimeFloat,
1092 .ComptimeInt,1094 .ComptimeInt,
...@@ -1096,12 +1098,11 @@ pub const Type = extern union {...@@ -1096,12 +1098,11 @@ pub const Type = extern union {
1096 .Void,1098 .Void,
1097 .Undefined,1099 .Undefined,
1098 .Null,1100 .Null,
1099 .Opaque,
1100 => return false,1101 => return false,
11011102
1102 .Optional => {1103 .Optional => {
1103 var buf: Payload.Pointer = undefined;1104 var buf: Payload.Pointer = undefined;
1104 return ty.optionalChild(&buf).isValidVarType();1105 return ty.optionalChild(&buf).isValidVarType(is_extern);
1105 },1106 },
1106 .Pointer, .Array => ty = ty.elemType(),1107 .Pointer, .Array => ty = ty.elemType(),
11071108
src-self-hosted/value.zig+29-1
...@@ -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);
...@@ -216,7 +218,7 @@ pub const Value = extern union {...@@ -216,7 +218,7 @@ pub const Value = extern union {
216 };218 };
217 return Value{ .ptr_otherwise = &new_payload.base };219 return Value{ .ptr_otherwise = &new_payload.base };
218 },220 },
219 .enum_literal, .bytes => return self.copyPayloadShallow(allocator, Payload.Bytes),221 .bytes => return self.copyPayloadShallow(allocator, Payload.Bytes),
220 .repeated => {222 .repeated => {
221 const payload = @fieldParentPtr(Payload.Repeated, "base", self.ptr_otherwise);223 const payload = @fieldParentPtr(Payload.Repeated, "base", self.ptr_otherwise);
222 const new_payload = try allocator.create(Payload.Repeated);224 const new_payload = try allocator.create(Payload.Repeated);
...@@ -230,6 +232,15 @@ pub const Value = extern union {...@@ -230,6 +232,15 @@ pub const Value = extern union {
230 .float_32 => return self.copyPayloadShallow(allocator, Payload.Float_32),232 .float_32 => return self.copyPayloadShallow(allocator, Payload.Float_32),
231 .float_64 => return self.copyPayloadShallow(allocator, Payload.Float_64),233 .float_64 => return self.copyPayloadShallow(allocator, Payload.Float_64),
232 .float_128 => return self.copyPayloadShallow(allocator, Payload.Float_128),234 .float_128 => return self.copyPayloadShallow(allocator, Payload.Float_128),
235 .enum_literal => {
236 const payload = @fieldParentPtr(Payload.Bytes, "base", self.ptr_otherwise);
237 const new_payload = try allocator.create(Payload.Bytes);
238 new_payload.* = .{
239 .base = payload.base,
240 .data = try allocator.dupe(u8, payload.data),
241 };
242 return Value{ .ptr_otherwise = &new_payload.base };
243 },
233 }244 }
234 }245 }
235246
...@@ -310,6 +321,7 @@ pub const Value = extern union {...@@ -310,6 +321,7 @@ pub const Value = extern union {
310 .int_big_positive => return out_stream.print("{}", .{val.cast(Payload.IntBigPositive).?.asBigInt()}),321 .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()}),322 .int_big_negative => return out_stream.print("{}", .{val.cast(Payload.IntBigNegative).?.asBigInt()}),
312 .function => return out_stream.writeAll("(function)"),323 .function => return out_stream.writeAll("(function)"),
324 .variable => return out_stream.writeAll("(variable)"),
313 .ref_val => {325 .ref_val => {
314 const ref_val = val.cast(Payload.RefVal).?;326 const ref_val = val.cast(Payload.RefVal).?;
315 try out_stream.writeAll("&const ");327 try out_stream.writeAll("&const ");
...@@ -410,6 +422,7 @@ pub const Value = extern union {...@@ -410,6 +422,7 @@ pub const Value = extern union {
410 .int_big_positive,422 .int_big_positive,
411 .int_big_negative,423 .int_big_negative,
412 .function,424 .function,
425 .variable,
413 .ref_val,426 .ref_val,
414 .decl_ref,427 .decl_ref,
415 .elem_ptr,428 .elem_ptr,
...@@ -471,6 +484,7 @@ pub const Value = extern union {...@@ -471,6 +484,7 @@ pub const Value = extern union {
471 .enum_literal_type,484 .enum_literal_type,
472 .null_value,485 .null_value,
473 .function,486 .function,
487 .variable,
474 .ref_val,488 .ref_val,
475 .decl_ref,489 .decl_ref,
476 .elem_ptr,490 .elem_ptr,
...@@ -548,6 +562,7 @@ pub const Value = extern union {...@@ -548,6 +562,7 @@ pub const Value = extern union {
548 .enum_literal_type,562 .enum_literal_type,
549 .null_value,563 .null_value,
550 .function,564 .function,
565 .variable,
551 .ref_val,566 .ref_val,
552 .decl_ref,567 .decl_ref,
553 .elem_ptr,568 .elem_ptr,
...@@ -625,6 +640,7 @@ pub const Value = extern union {...@@ -625,6 +640,7 @@ pub const Value = extern union {
625 .enum_literal_type,640 .enum_literal_type,
626 .null_value,641 .null_value,
627 .function,642 .function,
643 .variable,
628 .ref_val,644 .ref_val,
629 .decl_ref,645 .decl_ref,
630 .elem_ptr,646 .elem_ptr,
...@@ -728,6 +744,7 @@ pub const Value = extern union {...@@ -728,6 +744,7 @@ pub const Value = extern union {
728 .enum_literal_type,744 .enum_literal_type,
729 .null_value,745 .null_value,
730 .function,746 .function,
747 .variable,
731 .ref_val,748 .ref_val,
732 .decl_ref,749 .decl_ref,
733 .elem_ptr,750 .elem_ptr,
...@@ -810,6 +827,7 @@ pub const Value = extern union {...@@ -810,6 +827,7 @@ pub const Value = extern union {
810 .enum_literal_type,827 .enum_literal_type,
811 .null_value,828 .null_value,
812 .function,829 .function,
830 .variable,
813 .ref_val,831 .ref_val,
814 .decl_ref,832 .decl_ref,
815 .elem_ptr,833 .elem_ptr,
...@@ -974,6 +992,7 @@ pub const Value = extern union {...@@ -974,6 +992,7 @@ pub const Value = extern union {
974 .bool_false,992 .bool_false,
975 .null_value,993 .null_value,
976 .function,994 .function,
995 .variable,
977 .ref_val,996 .ref_val,
978 .decl_ref,997 .decl_ref,
979 .elem_ptr,998 .elem_ptr,
...@@ -1046,6 +1065,7 @@ pub const Value = extern union {...@@ -1046,6 +1065,7 @@ pub const Value = extern union {
1046 .enum_literal_type,1065 .enum_literal_type,
1047 .null_value,1066 .null_value,
1048 .function,1067 .function,
1068 .variable,
1049 .ref_val,1069 .ref_val,
1050 .decl_ref,1070 .decl_ref,
1051 .elem_ptr,1071 .elem_ptr,
...@@ -1182,6 +1202,7 @@ pub const Value = extern union {...@@ -1182,6 +1202,7 @@ pub const Value = extern union {
1182 .bool_false,1202 .bool_false,
1183 .null_value,1203 .null_value,
1184 .function,1204 .function,
1205 .variable,
1185 .int_u64,1206 .int_u64,
1186 .int_i64,1207 .int_i64,
1187 .int_big_positive,1208 .int_big_positive,
...@@ -1260,6 +1281,7 @@ pub const Value = extern union {...@@ -1260,6 +1281,7 @@ pub const Value = extern union {
1260 .bool_false,1281 .bool_false,
1261 .null_value,1282 .null_value,
1262 .function,1283 .function,
1284 .variable,
1263 .int_u64,1285 .int_u64,
1264 .int_i64,1286 .int_i64,
1265 .int_big_positive,1287 .int_big_positive,
...@@ -1355,6 +1377,7 @@ pub const Value = extern union {...@@ -1355,6 +1377,7 @@ pub const Value = extern union {
1355 .bool_true,1377 .bool_true,
1356 .bool_false,1378 .bool_false,
1357 .function,1379 .function,
1380 .variable,
1358 .int_u64,1381 .int_u64,
1359 .int_i64,1382 .int_i64,
1360 .int_big_positive,1383 .int_big_positive,
...@@ -1429,6 +1452,11 @@ pub const Value = extern union {...@@ -1429,6 +1452,11 @@ pub const Value = extern union {
1429 func: *Module.Fn,1452 func: *Module.Fn,
1430 };1453 };
14311454
1455 pub const Variable = struct {
1456 base: Payload = Payload{ .tag = .variable },
1457 variable: *Module.Var,
1458 };
1459
1432 pub const ArraySentinel0_u8_Type = struct {1460 pub const ArraySentinel0_u8_Type = struct {
1433 base: Payload = Payload{ .tag = .array_sentinel_0_u8_type },1461 base: Payload = Payload{ .tag = .array_sentinel_0_u8_type },
1434 len: u64,1462 len: u64,
src-self-hosted/zir.zig+70
...@@ -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 };
...@@ -1875,6 +1878,11 @@ const EmitZIR = struct {...@@ -1875,6 +1878,11 @@ const EmitZIR = struct {
1875 if (typed_value.val.cast(Value.Payload.DeclRef)) |decl_ref| {1878 if (typed_value.val.cast(Value.Payload.DeclRef)) |decl_ref| {
1876 const decl = decl_ref.decl;1879 const decl = decl_ref.decl;
1877 return try self.emitUnnamedDecl(try self.emitDeclRef(src, decl));1880 return try self.emitUnnamedDecl(try self.emitDeclRef(src, decl));
1881 } else if (typed_value.val.cast(Value.Payload.Variable)) |variable| {
1882 return self.emitTypedValue(src, .{
1883 .ty = typed_value.ty,
1884 .val = variable.variable.init,
1885 });
1878 }1886 }
1879 if (typed_value.val.isUndef()) {1887 if (typed_value.val.isUndef()) {
1880 const as_inst = try self.arena.allocator.create(Inst.BinOp);1888 const as_inst = try self.arena.allocator.create(Inst.BinOp);
...@@ -1964,6 +1972,21 @@ const EmitZIR = struct {...@@ -1964,6 +1972,21 @@ const EmitZIR = struct {
1964 return self.emitPrimitive(src, .@"true")1972 return self.emitPrimitive(src, .@"true")
1965 else1973 else
1966 return self.emitPrimitive(src, .@"false"),1974 return self.emitPrimitive(src, .@"false"),
1975 .EnumLiteral => {
1976 const enum_literal = @fieldParentPtr(Value.Payload.Bytes, "base", typed_value.val.ptr_otherwise);
1977 const inst = try self.arena.allocator.create(Inst.Str);
1978 inst.* = .{
1979 .base = .{
1980 .src = src,
1981 .tag = .enum_literal,
1982 },
1983 .positionals = .{
1984 .bytes = enum_literal.data,
1985 },
1986 .kw_args = .{},
1987 };
1988 return self.emitUnnamedDecl(&inst.base);
1989 },
1967 else => |t| std.debug.panic("TODO implement emitTypedValue for {}", .{@tagName(t)}),1990 else => |t| std.debug.panic("TODO implement emitTypedValue for {}", .{@tagName(t)}),
1968 }1991 }
1969 }1992 }
...@@ -2311,6 +2334,8 @@ const EmitZIR = struct {...@@ -2311,6 +2334,8 @@ const EmitZIR = struct {
2311 };2334 };
2312 break :blk &new_inst.base;2335 break :blk &new_inst.base;
2313 },2336 },
2337
2338 .varptr => @panic("TODO"),
2314 };2339 };
2315 try self.metadata.put(new_inst, .{ .deaths = inst.deaths });2340 try self.metadata.put(new_inst, .{ .deaths = inst.deaths });
2316 try instructions.append(new_inst);2341 try instructions.append(new_inst);
...@@ -2432,6 +2457,51 @@ const EmitZIR = struct {...@@ -2432,6 +2457,51 @@ const EmitZIR = struct {
2432 };2457 };
2433 return self.emitUnnamedDecl(&inst.base);2458 return self.emitUnnamedDecl(&inst.base);
2434 },2459 },
2460 .Array => {
2461 var len_pl = Value.Payload.Int_u64{ .int = ty.arrayLen() };
2462 const len = Value.initPayload(&len_pl.base);
2463
2464 const inst = if (ty.arraySentinel()) |sentinel| blk: {
2465 const inst = try self.arena.allocator.create(Inst.ArrayTypeSentinel);
2466 inst.* = .{
2467 .base = .{
2468 .src = src,
2469 .tag = .array_type,
2470 },
2471 .positionals = .{
2472 .len = (try self.emitTypedValue(src, .{
2473 .ty = Type.initTag(.usize),
2474 .val = len,
2475 })).inst,
2476 .sentinel = (try self.emitTypedValue(src, .{
2477 .ty = ty.elemType(),
2478 .val = sentinel,
2479 })).inst,
2480 .elem_type = (try self.emitType(src, ty.elemType())).inst,
2481 },
2482 .kw_args = .{},
2483 };
2484 break :blk &inst.base;
2485 } else blk: {
2486 const inst = try self.arena.allocator.create(Inst.BinOp);
2487 inst.* = .{
2488 .base = .{
2489 .src = src,
2490 .tag = .array_type,
2491 },
2492 .positionals = .{
2493 .lhs = (try self.emitTypedValue(src, .{
2494 .ty = Type.initTag(.usize),
2495 .val = len,
2496 })).inst,
2497 .rhs = (try self.emitType(src, ty.elemType())).inst,
2498 },
2499 .kw_args = .{},
2500 };
2501 break :blk &inst.base;
2502 };
2503 return self.emitUnnamedDecl(inst);
2504 },
2435 else => std.debug.panic("TODO implement emitType for {}", .{ty}),2505 else => std.debug.panic("TODO implement emitType for {}", .{ty}),
2436 },2506 },
2437 }2507 }
src-self-hosted/zir_sema.zig+3-4
...@@ -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);
...@@ -581,8 +581,7 @@ fn analyzeInstDeclVal(mod: *Module, scope: *Scope, inst: *zir.Inst.DeclVal) Inne...@@ -581,8 +581,7 @@ fn analyzeInstDeclVal(mod: *Module, scope: *Scope, inst: *zir.Inst.DeclVal) Inne
581581
582fn analyzeInstDeclValInModule(mod: *Module, scope: *Scope, inst: *zir.Inst.DeclValInModule) InnerError!*Inst {582fn analyzeInstDeclValInModule(mod: *Module, scope: *Scope, inst: *zir.Inst.DeclValInModule) InnerError!*Inst {
583 const decl = inst.positionals.decl;583 const decl = inst.positionals.decl;
584 const ptr = try mod.analyzeDeclRef(scope, inst.base.src, decl);584 return mod.analyzeDeclRef(scope, inst.base.src, decl);
585 return mod.analyzeDeref(scope, inst.base.src, ptr, inst.base.src);
586}585}
587586
588fn analyzeInstCall(mod: *Module, scope: *Scope, inst: *zir.Inst.Call) InnerError!*Inst {587fn analyzeInstCall(mod: *Module, scope: *Scope, inst: *zir.Inst.Call) InnerError!*Inst {
...@@ -779,7 +778,7 @@ fn analyzeInstFnType(mod: *Module, scope: *Scope, fntype: *zir.Inst.FnType) Inne...@@ -779,7 +778,7 @@ fn analyzeInstFnType(mod: *Module, scope: *Scope, fntype: *zir.Inst.FnType) Inne
779 for (fntype.positionals.param_types) |param_type, i| {778 for (fntype.positionals.param_types) |param_type, i| {
780 const resolved = try resolveType(mod, scope, param_type);779 const resolved = try resolveType(mod, scope, param_type);
781 // TODO skip for comptime params780 // TODO skip for comptime params
782 if (!resolved.isValidVarType()) {781 if (!resolved.isValidVarType(false)) {
783 return mod.fail(scope, param_type.src, "parameter of type '{}' must be declared comptime", .{resolved});782 return mod.fail(scope, param_type.src, "parameter of type '{}' must be declared comptime", .{resolved});
784 }783 }
785 param_types[i] = resolved;784 param_types[i] = resolved;
test/stage2/compare_output.zig+33
...@@ -586,6 +586,7 @@ pub fn addCases(ctx: *TestContext) !void {...@@ -586,6 +586,7 @@ pub fn addCases(ctx: *TestContext) !void {
586 "",586 "",
587 );587 );
588588
589 // Character literals and multiline strings.
589 case.addCompareOutput(590 case.addCompareOutput(
590 \\export fn _start() noreturn {591 \\export fn _start() noreturn {
591 \\ const ignore = 592 \\ const ignore =
...@@ -617,6 +618,38 @@ pub fn addCases(ctx: *TestContext) !void {...@@ -617,6 +618,38 @@ pub fn addCases(ctx: *TestContext) !void {
617 ,618 ,
618 "",619 "",
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 );
620 }653 }
621654
622 {655 {