aboutsummaryrefslogtreecommitdiff
path: root/src/Sema.zig
diff options
context:
space:
mode:
authorAndrew Kelley <andrew@ziglang.org>2021-05-17 17:39:52 -0700
committerAndrew Kelley <andrew@ziglang.org>2021-05-17 17:39:52 -0700
commit67f5a28257b50e72750f51a03d6ce9ee27ad1439 (patch)
treee2a205ff1e748ded4bfc848e0a841ac5cef3622a /src/Sema.zig
parent5cacc446c4ff5591b7a9c506952f4eb9ae5efdd1 (diff)
downloadzig-67f5a28257b50e72750f51a03d6ce9ee27ad1439.tar.gz
zig-67f5a28257b50e72750f51a03d6ce9ee27ad1439.zip
Sema: use a hash map for ZIR->AIR mapping
Previously, ZIR was per-function so we could simply allocate a slice for all ZIR instructions. However now ZIR is whole-file, so we need a sparse mapping of ZIR to AIR instructions in order to not waste memory.
Diffstat (limited to 'src/Sema.zig')
-rw-r--r--src/Sema.zig22
1 files changed, 15 insertions, 7 deletions
diff --git a/src/Sema.zig b/src/Sema.zig
index 4070eedc75..a707785b17 100644
--- a/src/Sema.zig
+++ b/src/Sema.zig
@@ -12,7 +12,7 @@ gpa: *Allocator,
arena: *Allocator,
code: Zir,
/// Maps ZIR to AIR.
-inst_map: []*Inst,
+inst_map: InstMap = .{},
/// When analyzing an inline function call, owner_decl is the Decl of the caller
/// and `src_decl` of `Scope.Block` is the `Decl` of the callee.
/// This `Decl` owns the arena memory of this `Sema`.
@@ -65,6 +65,13 @@ const LazySrcLoc = Module.LazySrcLoc;
const RangeSet = @import("RangeSet.zig");
const target_util = @import("target.zig");
+pub const InstMap = std.AutoHashMapUnmanaged(Zir.Inst.Index, *ir.Inst);
+
+pub fn deinit(sema: *Sema) void {
+ sema.inst_map.deinit(sema.gpa);
+ sema.* = undefined;
+}
+
pub fn analyzeFnBody(
sema: *Sema,
block: *Scope.Block,
@@ -129,7 +136,7 @@ pub fn analyzeBody(
) InnerError!Zir.Inst.Index {
// No tracy calls here, to avoid interfering with the tail call mechanism.
- const map = block.sema.inst_map;
+ const map = &block.sema.inst_map;
const tags = block.sema.code.instructions.items(.tag);
const datas = block.sema.code.instructions.items(.data);
@@ -142,7 +149,7 @@ pub fn analyzeBody(
var i: usize = 0;
while (true) : (i += 1) {
const inst = body[i];
- map[inst] = switch (tags[inst]) {
+ const air_inst = switch (tags[inst]) {
// zig fmt: off
.arg => try sema.zirArg(block, inst),
.alloc => try sema.zirAlloc(block, inst),
@@ -500,8 +507,9 @@ pub fn analyzeBody(
}
},
};
- if (map[inst].ty.isNoReturn())
+ if (air_inst.ty.isNoReturn())
return always_noreturn;
+ try map.putNoClobber(sema.gpa, inst, air_inst);
}
}
@@ -556,7 +564,7 @@ pub fn resolveInst(sema: *Sema, zir_ref: Zir.Inst.Ref) error{OutOfMemory}!*ir.In
i -= Zir.Inst.Ref.typed_value_map.len;
// Finally, the last section of indexes refers to the map of ZIR=>AIR.
- return sema.inst_map[i];
+ return sema.inst_map.get(@intCast(u32, i)).?;
}
fn resolveConstString(
@@ -2244,9 +2252,9 @@ fn analyzeCall(
defer sema.code = parent_zir;
const parent_inst_map = sema.inst_map;
- sema.inst_map = try sema.gpa.alloc(*ir.Inst, sema.code.instructions.len);
+ sema.inst_map = .{};
defer {
- sema.gpa.free(sema.inst_map);
+ sema.inst_map.deinit(sema.gpa);
sema.inst_map = parent_inst_map;
}