authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-07-15 22:36:35-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-07-15 22:36:35-07:00
logd29dd5834b9d7386bb88e44bd2852428863cae81
tree6a1f15d341c00be937ef9308ec750b35c308a5c0
parentaf12596e8d728423e361e4755a6078c5ef8faf69

stage2: local consts

These are now supported enough that this example code hits the limitations of the register allocator: fn add(a: u32, b: u32) void { const c = a + b; // 7 const d = a + c; // 10 const e = d + b; // 14 assert(e == 14); } // error: TODO implement copyToNewRegister So now the next step is to implement register allocation as planned.

5 files changed, 72 insertions(+), 36 deletions(-)

src-self-hosted/Module.zig+33-10
...@@ -700,19 +700,22 @@ pub const Scope = struct {...@@ -700,19 +700,22 @@ pub const Scope = struct {
700 pub const GenZIR = struct {700 pub const GenZIR = struct {
701 pub const base_tag: Tag = .gen_zir;701 pub const base_tag: Tag = .gen_zir;
702 base: Scope = Scope{ .tag = base_tag },702 base: Scope = Scope{ .tag = base_tag },
703 /// Parents can be: `GenZIR`, `ZIRModule`, `File`
704 parent: *Scope,
703 decl: *Decl,705 decl: *Decl,
704 arena: *Allocator,706 arena: *Allocator,
707 /// The first N instructions in a function body ZIR are arg instructions.
705 instructions: std.ArrayListUnmanaged(*zir.Inst) = .{},708 instructions: std.ArrayListUnmanaged(*zir.Inst) = .{},
706 };709 };
707710
708 /// This structure lives as long as the AST generation of the Block711 /// This structure lives as long as the AST generation of the Block
709 /// node that contains the variable. This struct's parents can be712 /// node that contains the variable.
710 /// other `LocalVar` and finally a `GenZIR` at the top.
711 pub const LocalVar = struct {713 pub const LocalVar = struct {
712 pub const base_tag: Tag = .local_var;714 pub const base_tag: Tag = .local_var;
713 base: Scope = Scope{ .tag = base_tag },715 base: Scope = Scope{ .tag = base_tag },
714 gen_zir: *GenZIR,716 /// Parents can be: `LocalVar`, `GenZIR`.
715 parent: *Scope,717 parent: *Scope,
718 gen_zir: *GenZIR,
716 name: []const u8,719 name: []const u8,
717 inst: *zir.Inst,720 inst: *zir.Inst,
718 };721 };
...@@ -1164,6 +1167,7 @@ fn astGenAndAnalyzeDecl(self: *Module, decl: *Decl) !bool {...@@ -1164,6 +1167,7 @@ fn astGenAndAnalyzeDecl(self: *Module, decl: *Decl) !bool {
1164 var fn_type_scope: Scope.GenZIR = .{1167 var fn_type_scope: Scope.GenZIR = .{
1165 .decl = decl,1168 .decl = decl,
1166 .arena = &fn_type_scope_arena.allocator,1169 .arena = &fn_type_scope_arena.allocator,
1170 .parent = decl.scope,
1167 };1171 };
1168 defer fn_type_scope.instructions.deinit(self.gpa);1172 defer fn_type_scope.instructions.deinit(self.gpa);
11691173
...@@ -1241,12 +1245,32 @@ fn astGenAndAnalyzeDecl(self: *Module, decl: *Decl) !bool {...@@ -1241,12 +1245,32 @@ fn astGenAndAnalyzeDecl(self: *Module, decl: *Decl) !bool {
1241 var gen_scope: Scope.GenZIR = .{1245 var gen_scope: Scope.GenZIR = .{
1242 .decl = decl,1246 .decl = decl,
1243 .arena = &gen_scope_arena.allocator,1247 .arena = &gen_scope_arena.allocator,
1248 .parent = decl.scope,
1244 };1249 };
1245 defer gen_scope.instructions.deinit(self.gpa);1250 defer gen_scope.instructions.deinit(self.gpa);
12461251
1252 // We need an instruction for each parameter, and they must be first in the body.
1253 try gen_scope.instructions.resize(self.gpa, fn_proto.params_len);
1254 var params_scope = &gen_scope.base;
1255 for (fn_proto.params()) |param, i| {
1256 const name_token = param.name_token.?;
1257 const src = tree.token_locs[name_token].start;
1258 const param_name = tree.tokenSlice(name_token);
1259 const arg = try newZIRInst(&gen_scope_arena.allocator, src, zir.Inst.Arg, .{}, .{});
1260 gen_scope.instructions.items[i] = &arg.base;
1261 const sub_scope = try gen_scope_arena.allocator.create(Scope.LocalVar);
1262 sub_scope.* = .{
1263 .parent = params_scope,
1264 .gen_zir = &gen_scope,
1265 .name = param_name,
1266 .inst = &arg.base,
1267 };
1268 params_scope = &sub_scope.base;
1269 }
1270
1247 const body_block = body_node.cast(ast.Node.Block).?;1271 const body_block = body_node.cast(ast.Node.Block).?;
12481272
1249 try astgen.blockExpr(self, &gen_scope.base, body_block);1273 try astgen.blockExpr(self, params_scope, body_block);
12501274
1251 if (!fn_type.fnReturnType().isNoReturn() and (gen_scope.instructions.items.len == 0 or1275 if (!fn_type.fnReturnType().isNoReturn() and (gen_scope.instructions.items.len == 0 or
1252 !gen_scope.instructions.items[gen_scope.instructions.items.len - 1].tag.isNoReturn()))1276 !gen_scope.instructions.items[gen_scope.instructions.items.len - 1].tag.isNoReturn()))
...@@ -2236,17 +2260,16 @@ fn analyzeInstCompileError(self: *Module, scope: *Scope, inst: *zir.Inst.Compile...@@ -2236,17 +2260,16 @@ fn analyzeInstCompileError(self: *Module, scope: *Scope, inst: *zir.Inst.Compile
2236fn analyzeInstArg(self: *Module, scope: *Scope, inst: *zir.Inst.Arg) InnerError!*Inst {2260fn analyzeInstArg(self: *Module, scope: *Scope, inst: *zir.Inst.Arg) InnerError!*Inst {
2237 const b = try self.requireRuntimeBlock(scope, inst.base.src);2261 const b = try self.requireRuntimeBlock(scope, inst.base.src);
2238 const fn_ty = b.func.?.owner_decl.typed_value.most_recent.typed_value.ty;2262 const fn_ty = b.func.?.owner_decl.typed_value.most_recent.typed_value.ty;
2263 const param_index = b.instructions.items.len;
2239 const param_count = fn_ty.fnParamLen();2264 const param_count = fn_ty.fnParamLen();
2240 if (inst.positionals.index >= param_count) {2265 if (param_index >= param_count) {
2241 return self.fail(scope, inst.base.src, "parameter index {} outside list of length {}", .{2266 return self.fail(scope, inst.base.src, "parameter index {} outside list of length {}", .{
2242 inst.positionals.index,2267 param_index,
2243 param_count,2268 param_count,
2244 });2269 });
2245 }2270 }
2246 const param_type = fn_ty.fnParamType(inst.positionals.index);2271 const param_type = fn_ty.fnParamType(param_index);
2247 return self.addNewInstArgs(b, inst.base.src, param_type, Inst.Arg, .{2272 return self.addNewInstArgs(b, inst.base.src, param_type, Inst.Arg, {});
2248 .index = inst.positionals.index,
2249 });
2250}2273}
22512274
2252fn analyzeInstBlock(self: *Module, scope: *Scope, inst: *zir.Inst.Block) InnerError!*Inst {2275fn analyzeInstBlock(self: *Module, scope: *Scope, inst: *zir.Inst.Block) InnerError!*Inst {
src-self-hosted/astgen.zig+25-14
...@@ -160,6 +160,7 @@ fn ifExpr(mod: *Module, scope: *Scope, if_node: *ast.Node.If) InnerError!*zir.In...@@ -160,6 +160,7 @@ fn ifExpr(mod: *Module, scope: *Scope, if_node: *ast.Node.If) InnerError!*zir.In
160 }160 }
161 }161 }
162 var block_scope: Scope.GenZIR = .{162 var block_scope: Scope.GenZIR = .{
163 .parent = scope,
163 .decl = scope.decl().?,164 .decl = scope.decl().?,
164 .arena = scope.arena(),165 .arena = scope.arena(),
165 .instructions = .{},166 .instructions = .{},
...@@ -180,6 +181,7 @@ fn ifExpr(mod: *Module, scope: *Scope, if_node: *ast.Node.If) InnerError!*zir.In...@@ -180,6 +181,7 @@ fn ifExpr(mod: *Module, scope: *Scope, if_node: *ast.Node.If) InnerError!*zir.In
180 .instructions = try block_scope.arena.dupe(*zir.Inst, block_scope.instructions.items),181 .instructions = try block_scope.arena.dupe(*zir.Inst, block_scope.instructions.items),
181 });182 });
182 var then_scope: Scope.GenZIR = .{183 var then_scope: Scope.GenZIR = .{
184 .parent = scope,
183 .decl = block_scope.decl,185 .decl = block_scope.decl,
184 .arena = block_scope.arena,186 .arena = block_scope.arena,
185 .instructions = .{},187 .instructions = .{},
...@@ -199,6 +201,7 @@ fn ifExpr(mod: *Module, scope: *Scope, if_node: *ast.Node.If) InnerError!*zir.In...@@ -199,6 +201,7 @@ fn ifExpr(mod: *Module, scope: *Scope, if_node: *ast.Node.If) InnerError!*zir.In
199 };201 };
200202
201 var else_scope: Scope.GenZIR = .{203 var else_scope: Scope.GenZIR = .{
204 .parent = scope,
202 .decl = block_scope.decl,205 .decl = block_scope.decl,
203 .arena = block_scope.arena,206 .arena = block_scope.arena,
204 .instructions = .{},207 .instructions = .{},
...@@ -250,7 +253,11 @@ fn controlFlowExpr(...@@ -250,7 +253,11 @@ fn controlFlowExpr(
250}253}
251254
252fn identifier(mod: *Module, scope: *Scope, ident: *ast.Node.Identifier) InnerError!*zir.Inst {255fn identifier(mod: *Module, scope: *Scope, ident: *ast.Node.Identifier) InnerError!*zir.Inst {
256 const tracy = trace(@src());
257 defer tracy.end();
258
253 const tree = scope.tree();259 const tree = scope.tree();
260 // TODO implement @"aoeu" identifiers
254 const ident_name = tree.tokenSlice(ident.token);261 const ident_name = tree.tokenSlice(ident.token);
255 const src = tree.token_locs[ident.token].start;262 const src = tree.token_locs[ident.token].start;
256 if (mem.eql(u8, ident_name, "_")) {263 if (mem.eql(u8, ident_name, "_")) {
...@@ -288,23 +295,27 @@ fn identifier(mod: *Module, scope: *Scope, ident: *ast.Node.Identifier) InnerErr...@@ -288,23 +295,27 @@ fn identifier(mod: *Module, scope: *Scope, ident: *ast.Node.Identifier) InnerErr
288 }295 }
289 }296 }
290297
291 if (mod.lookupDeclName(scope, ident_name)) |decl| {298 // Local variables, including function parameters.
292 return try mod.addZIRInst(scope, src, zir.Inst.DeclValInModule, .{ .decl = decl }, .{});299 {
300 var s = scope;
301 while (true) switch (s.tag) {
302 .local_var => {
303 const local_var = s.cast(Scope.LocalVar).?;
304 if (mem.eql(u8, local_var.name, ident_name)) {
305 return local_var.inst;
306 }
307 s = local_var.parent;
308 },
309 .gen_zir => s = s.cast(Scope.GenZIR).?.parent,
310 else => break,
311 };
293 }312 }
294313
295 // Function parameter314 if (mod.lookupDeclName(scope, ident_name)) |decl| {
296 if (scope.decl()) |decl| {315 return try mod.addZIRInst(scope, src, zir.Inst.DeclValInModule, .{ .decl = decl }, .{});
297 if (tree.root_node.decls()[decl.src_index].cast(ast.Node.FnProto)) |fn_proto| {
298 for (fn_proto.params()) |param, i| {
299 const param_name = tree.tokenSlice(param.name_token.?);
300 if (mem.eql(u8, param_name, ident_name)) {
301 return try mod.addZIRInst(scope, src, zir.Inst.Arg, .{ .index = i }, .{});
302 }
303 }
304 }
305 }316 }
306317
307 return mod.failNode(scope, &ident.base, "TODO implement local variable identifier lookup", .{});318 return mod.failNode(scope, &ident.base, "use of undeclared identifier '{}'", .{ident_name});
308}319}
309320
310fn stringLiteral(mod: *Module, scope: *Scope, str_lit: *ast.Node.StringLiteral) InnerError!*zir.Inst {321fn stringLiteral(mod: *Module, scope: *Scope, str_lit: *ast.Node.StringLiteral) InnerError!*zir.Inst {
...@@ -434,7 +445,7 @@ fn callExpr(mod: *Module, scope: *Scope, node: *ast.Node.Call) InnerError!*zir.I...@@ -434,7 +445,7 @@ fn callExpr(mod: *Module, scope: *Scope, node: *ast.Node.Call) InnerError!*zir.I
434 const lhs = try expr(mod, scope, node.lhs);445 const lhs = try expr(mod, scope, node.lhs);
435446
436 const param_nodes = node.params();447 const param_nodes = node.params();
437 const args = try scope.cast(Scope.GenZIR).?.arena.alloc(*zir.Inst, param_nodes.len);448 const args = try scope.getGenZIR().arena.alloc(*zir.Inst, param_nodes.len);
438 for (param_nodes) |param_node, i| {449 for (param_nodes) |param_node, i| {
439 args[i] = try expr(mod, scope, param_node);450 args[i] = try expr(mod, scope, param_node);
440 }451 }
src-self-hosted/codegen.zig+5-1
...@@ -73,6 +73,7 @@ pub fn generateSymbol(...@@ -73,6 +73,7 @@ pub fn generateSymbol(
73 .code = code,73 .code = code,
74 .err_msg = null,74 .err_msg = null,
75 .args = mc_args,75 .args = mc_args,
76 .arg_index = 0,
76 .branch_stack = &branch_stack,77 .branch_stack = &branch_stack,
77 .src = src,78 .src = src,
78 };79 };
...@@ -255,6 +256,7 @@ const Function = struct {...@@ -255,6 +256,7 @@ const Function = struct {
255 code: *std.ArrayList(u8),256 code: *std.ArrayList(u8),
256 err_msg: ?*ErrorMsg,257 err_msg: ?*ErrorMsg,
257 args: []MCValue,258 args: []MCValue,
259 arg_index: usize,
258 src: usize,260 src: usize,
259261
260 /// Whenever there is a runtime branch, we push a Branch onto this stack,262 /// Whenever there is a runtime branch, we push a Branch onto this stack,
...@@ -603,7 +605,9 @@ const Function = struct {...@@ -603,7 +605,9 @@ const Function = struct {
603 }605 }
604606
605 fn genArg(self: *Function, inst: *ir.Inst.Arg) !MCValue {607 fn genArg(self: *Function, inst: *ir.Inst.Arg) !MCValue {
606 return self.args[inst.args.index];608 const i = self.arg_index;
609 self.arg_index += 1;
610 return self.args[i];
607 }611 }
608612
609 fn genBreakpoint(self: *Function, src: usize, comptime arch: std.Target.Cpu.Arch) !MCValue {613 fn genBreakpoint(self: *Function, src: usize, comptime arch: std.Target.Cpu.Arch) !MCValue {
src-self-hosted/ir.zig+1-4
...@@ -101,10 +101,7 @@ pub const Inst = struct {...@@ -101,10 +101,7 @@ pub const Inst = struct {
101 pub const Arg = struct {101 pub const Arg = struct {
102 pub const base_tag = Tag.arg;102 pub const base_tag = Tag.arg;
103 base: Inst,103 base: Inst,
104104 args: void,
105 args: struct {
106 index: usize,
107 },
108 };105 };
109106
110 pub const Assembly = struct {107 pub const Assembly = struct {
src-self-hosted/zir.zig+8-7
...@@ -34,7 +34,8 @@ pub const Inst = struct {...@@ -34,7 +34,8 @@ pub const Inst = struct {
3434
35 /// These names are used directly as the instruction names in the text format.35 /// These names are used directly as the instruction names in the text format.
36 pub const Tag = enum {36 pub const Tag = enum {
37 /// Function parameter value.37 /// Function parameter value. These must be first in a function's main block,
38 /// in respective order with the parameters.
38 arg,39 arg,
39 /// A labeled block of code, which can return a value.40 /// A labeled block of code, which can return a value.
40 block,41 block,
...@@ -184,9 +185,7 @@ pub const Inst = struct {...@@ -184,9 +185,7 @@ pub const Inst = struct {
184 pub const base_tag = Tag.arg;185 pub const base_tag = Tag.arg;
185 base: Inst,186 base: Inst,
186187
187 positionals: struct {188 positionals: struct {},
188 index: usize,
189 },
190 kw_args: struct {},189 kw_args: struct {},
191 };190 };
192191
...@@ -1384,15 +1383,17 @@ const EmitZIR = struct {...@@ -1384,15 +1383,17 @@ const EmitZIR = struct {
1384 for (src_decls.items) |ir_decl| {1383 for (src_decls.items) |ir_decl| {
1385 switch (ir_decl.analysis) {1384 switch (ir_decl.analysis) {
1386 .unreferenced => continue,1385 .unreferenced => continue,
1386
1387 .complete => {},1387 .complete => {},
1388 .codegen_failure => {}, // We still can emit the ZIR.
1389 .codegen_failure_retryable => {}, // We still can emit the ZIR.
1390
1388 .in_progress => unreachable,1391 .in_progress => unreachable,
1389 .outdated => unreachable,1392 .outdated => unreachable,
13901393
1391 .sema_failure,1394 .sema_failure,
1392 .sema_failure_retryable,1395 .sema_failure_retryable,
1393 .codegen_failure,
1394 .dependency_failure,1396 .dependency_failure,
1395 .codegen_failure_retryable,
1396 => if (self.old_module.failed_decls.get(ir_decl)) |err_msg| {1397 => if (self.old_module.failed_decls.get(ir_decl)) |err_msg| {
1397 const fail_inst = try self.arena.allocator.create(Inst.CompileError);1398 const fail_inst = try self.arena.allocator.create(Inst.CompileError);
1398 fail_inst.* = .{1399 fail_inst.* = .{
...@@ -1728,7 +1729,7 @@ const EmitZIR = struct {...@@ -1728,7 +1729,7 @@ const EmitZIR = struct {
1728 .src = inst.src,1729 .src = inst.src,
1729 .tag = Inst.Arg.base_tag,1730 .tag = Inst.Arg.base_tag,
1730 },1731 },
1731 .positionals = .{ .index = old_inst.args.index },1732 .positionals = .{},
1732 .kw_args = .{},1733 .kw_args = .{},
1733 };1734 };
1734 break :blk &new_inst.base;1735 break :blk &new_inst.base;