Commit 351b57497b

Andrew Kelley <andrew@ziglang.org>
2021-05-01 08:11:20
stage2: implement function body analysis
now with whole-file-astgen
1 parent 077b8d3
Changed files (2)
src/Module.zig
@@ -3986,48 +3986,44 @@ pub fn analyzeFnBody(mod: *Module, decl: *Decl, func: *Fn) !void {
         param_inst.* = &arg_inst.base;
     }
 
-    var f = false;
-    if (f) {
-        return error.AnalysisFail;
-    }
-    @panic("TODO reimplement analyzeFnBody now that ZIR is whole-file");
-
-    //var sema: Sema = .{
-    //    .mod = mod,
-    //    .gpa = mod.gpa,
-    //    .arena = &arena.allocator,
-    //    .code = func.zir,
-    //    .inst_map = try mod.gpa.alloc(*ir.Inst, func.zir.instructions.len),
-    //    .owner_decl = decl,
-    //    .namespace = decl.namespace,
-    //    .func = func,
-    //    .owner_func = func,
-    //    .param_inst_list = param_inst_list,
-    //};
-    //defer mod.gpa.free(sema.inst_map);
-
-    //var inner_block: Scope.Block = .{
-    //    .parent = null,
-    //    .sema = &sema,
-    //    .src_decl = decl,
-    //    .instructions = .{},
-    //    .inlining = null,
-    //    .is_comptime = false,
-    //};
-    //defer inner_block.instructions.deinit(mod.gpa);
-
-    //// AIR currently requires the arg parameters to be the first N instructions
-    //try inner_block.instructions.appendSlice(mod.gpa, param_inst_list);
-
-    //func.state = .in_progress;
-    //log.debug("set {s} to in_progress", .{decl.name});
-
-    //_ = try sema.root(&inner_block);
-
-    //const instructions = try arena.allocator.dupe(*ir.Inst, inner_block.instructions.items);
-    //func.state = .success;
-    //func.body = .{ .instructions = instructions };
-    //log.debug("set {s} to success", .{decl.name});
+    const zir = decl.namespace.file_scope.zir;
+
+    var sema: Sema = .{
+        .mod = mod,
+        .gpa = mod.gpa,
+        .arena = &arena.allocator,
+        .code = zir,
+        .inst_map = try mod.gpa.alloc(*ir.Inst, zir.instructions.len),
+        .owner_decl = decl,
+        .namespace = decl.namespace,
+        .func = func,
+        .owner_func = func,
+        .param_inst_list = param_inst_list,
+    };
+    defer mod.gpa.free(sema.inst_map);
+
+    var inner_block: Scope.Block = .{
+        .parent = null,
+        .sema = &sema,
+        .src_decl = decl,
+        .instructions = .{},
+        .inlining = null,
+        .is_comptime = false,
+    };
+    defer inner_block.instructions.deinit(mod.gpa);
+
+    // AIR currently requires the arg parameters to be the first N instructions
+    try inner_block.instructions.appendSlice(mod.gpa, param_inst_list);
+
+    func.state = .in_progress;
+    log.debug("set {s} to in_progress", .{decl.name});
+
+    try sema.analyzeFnBody(&inner_block, func.zir_body_inst);
+
+    const instructions = try arena.allocator.dupe(*ir.Inst, inner_block.instructions.items);
+    func.state = .success;
+    func.body = .{ .instructions = instructions };
+    log.debug("set {s} to success", .{decl.name});
 }
 
 fn markOutdatedDecl(mod: *Module, decl: *Decl) !void {
src/Sema.zig
@@ -65,6 +65,39 @@ const LazySrcLoc = Module.LazySrcLoc;
 const RangeSet = @import("RangeSet.zig");
 const AstGen = @import("AstGen.zig");
 
+pub fn analyzeFnBody(
+    sema: *Sema,
+    block: *Scope.Block,
+    fn_body_inst: Zir.Inst.Index,
+) InnerError!void {
+    const tags = sema.code.instructions.items(.tag);
+    const datas = sema.code.instructions.items(.data);
+    const body: []const Zir.Inst.Index = switch (tags[fn_body_inst]) {
+        .func, .func_inferred => blk: {
+            const inst_data = datas[fn_body_inst].pl_node;
+            const extra = sema.code.extraData(Zir.Inst.Func, inst_data.payload_index);
+            const param_types_len = extra.data.param_types_len;
+            const body = sema.code.extra[extra.end + param_types_len ..][0..extra.data.body_len];
+            break :blk body;
+        },
+        .extended => blk: {
+            const extended = datas[fn_body_inst].extended;
+            assert(extended.opcode == .func);
+            const extra = sema.code.extraData(Zir.Inst.ExtendedFunc, extended.operand);
+            const small = @bitCast(Zir.Inst.ExtendedFunc.Small, extended.small);
+            var extra_index: usize = extra.end;
+            extra_index += @boolToInt(small.has_lib_name);
+            extra_index += @boolToInt(small.has_cc);
+            extra_index += @boolToInt(small.has_align);
+            extra_index += extra.data.param_types_len;
+            const body = sema.code.extra[extra_index..][0..extra.data.body_len];
+            break :blk body;
+        },
+        else => unreachable,
+    };
+    _ = try sema.analyzeBody(block, body);
+}
+
 /// Returns only the result from the body that is specified.
 /// Only appropriate to call when it is determined at comptime that this body
 /// has no peers.
@@ -2088,11 +2121,9 @@ fn analyzeCall(
 
         try inline_sema.emitBackwardBranch(&child_block, call_src);
 
-        if (true) @panic("TODO re-implement inline function calls");
-
         // This will have return instructions analyzed as break instructions to
         // the block_inst above.
-        _ = try inline_sema.root(&child_block);
+        try inline_sema.analyzeFnBody(&child_block, module_fn.zir_body_inst);
 
         const result = try inline_sema.analyzeBlockBody(block, call_src, &child_block, merges);