Air: store interned values in Air.Inst.Ref

Previously, interned values were represented as AIR instructions using
the `interned` tag. Now, the AIR ref directly encodes the InternPool
index. The encoding works as follows:
* If the ref matches one of the static values, it corresponds to the same InternPool index.
* Otherwise, if the MSB is 0, the ref corresponds to an InternPool index.
* Otherwise, if the MSB is 1, the ref corresponds to an AIR instruction index (after removing the MSB).

Note that since most static InternPool indices are low values (the
exceptions being `.none` and `.var_args_param_type`), the first rule is
almost a nop.
This commit is contained in:
mlugg
2023-06-24 22:21:43 +01:00
committed by Andrew Kelley
parent dae516dbdf
commit ff37ccd298
13 changed files with 206 additions and 326 deletions

View File

@@ -53,7 +53,7 @@ const BlockData = struct {
result: CValue,
};
pub const CValueMap = std.AutoHashMap(Air.Inst.Index, CValue);
pub const CValueMap = std.AutoHashMap(Air.Inst.Ref, CValue);
pub const LazyFnKey = union(enum) {
tag_name: Decl.Index,
@@ -282,31 +282,29 @@ pub const Function = struct {
allocs: std.AutoArrayHashMapUnmanaged(LocalIndex, bool) = .{},
fn resolveInst(f: *Function, ref: Air.Inst.Ref) !CValue {
if (Air.refToIndex(ref)) |inst| {
const gop = try f.value_map.getOrPut(inst);
if (gop.found_existing) return gop.value_ptr.*;
const gop = try f.value_map.getOrPut(ref);
if (gop.found_existing) return gop.value_ptr.*;
const mod = f.object.dg.module;
const val = (try f.air.value(ref, mod)).?;
const ty = f.typeOf(ref);
const mod = f.object.dg.module;
const val = (try f.air.value(ref, mod)).?;
const ty = f.typeOf(ref);
const result: CValue = if (lowersToArray(ty, mod)) result: {
const writer = f.object.code_header.writer();
const alignment = 0;
const decl_c_value = try f.allocLocalValue(ty, alignment);
const gpa = f.object.dg.gpa;
try f.allocs.put(gpa, decl_c_value.new_local, false);
try writer.writeAll("static ");
try f.object.dg.renderTypeAndName(writer, ty, decl_c_value, Const, alignment, .complete);
try writer.writeAll(" = ");
try f.object.dg.renderValue(writer, ty, val, .StaticInitializer);
try writer.writeAll(";\n ");
break :result decl_c_value;
} else .{ .constant = ref };
const result: CValue = if (lowersToArray(ty, mod)) result: {
const writer = f.object.code_header.writer();
const alignment = 0;
const decl_c_value = try f.allocLocalValue(ty, alignment);
const gpa = f.object.dg.gpa;
try f.allocs.put(gpa, decl_c_value.new_local, false);
try writer.writeAll("static ");
try f.object.dg.renderTypeAndName(writer, ty, decl_c_value, Const, alignment, .complete);
try writer.writeAll(" = ");
try f.object.dg.renderValue(writer, ty, val, .StaticInitializer);
try writer.writeAll(";\n ");
break :result decl_c_value;
} else .{ .constant = ref };
gop.value_ptr.* = result;
return result;
} else return .{ .constant = ref };
gop.value_ptr.* = result;
return result;
}
fn wantSafety(f: *Function) bool {
@@ -2823,7 +2821,7 @@ fn genBodyInner(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail,
const result_value = switch (air_tags[inst]) {
// zig fmt: off
.inferred_alloc, .inferred_alloc_comptime, .interned => unreachable,
.inferred_alloc, .inferred_alloc_comptime => unreachable,
.arg => try airArg(f, inst),
@@ -3091,7 +3089,7 @@ fn genBodyInner(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail,
if (result_value == .new_local) {
log.debug("map %{d} to t{d}", .{ inst, result_value.new_local });
}
try f.value_map.putNoClobber(inst, switch (result_value) {
try f.value_map.putNoClobber(Air.indexToRef(inst), switch (result_value) {
.none => continue,
.new_local => |i| .{ .local = i },
else => result_value,
@@ -7439,7 +7437,7 @@ fn formatIntLiteral(
} else data.val.toBigInt(&int_buf, mod);
assert(int.fitsInTwosComp(data.int_info.signedness, data.int_info.bits));
const c_bits = @as(usize, @intCast(data.cty.byteSize(data.dg.ctypes.set, target) * 8));
const c_bits: usize = @intCast(data.cty.byteSize(data.dg.ctypes.set, target) * 8);
var one_limbs: [BigInt.calcLimbLen(1)]BigIntLimb = undefined;
const one = BigInt.Mutable.init(&one_limbs, 1).toConst();
@@ -7745,8 +7743,7 @@ fn reap(f: *Function, inst: Air.Inst.Index, operands: []const Air.Inst.Ref) !voi
fn die(f: *Function, inst: Air.Inst.Index, ref: Air.Inst.Ref) !void {
const ref_inst = Air.refToIndex(ref) orelse return;
assert(f.air.instructions.items(.tag)[ref_inst] != .interned);
const c_value = (f.value_map.fetchRemove(ref_inst) orelse return).value;
const c_value = (f.value_map.fetchRemove(ref) orelse return).value;
const local_index = switch (c_value) {
.local, .new_local => |l| l,
else => return,

View File

@@ -4557,7 +4557,7 @@ pub const FuncGen = struct {
.vector_store_elem => try self.airVectorStoreElem(inst),
.inferred_alloc, .inferred_alloc_comptime, .interned => unreachable,
.inferred_alloc, .inferred_alloc_comptime => unreachable,
.unreach => self.airUnreach(inst),
.dbg_stmt => self.airDbgStmt(inst),
@@ -5762,19 +5762,22 @@ pub const FuncGen = struct {
return self.loadByRef(elem_ptr, elem_ty, elem_ty.abiAlignment(mod), false);
} else {
const lhs_index = Air.refToIndex(bin_op.lhs).?;
const elem_llvm_ty = try o.lowerType(elem_ty);
if (self.air.instructions.items(.tag)[lhs_index] == .load) {
const load_data = self.air.instructions.items(.data)[lhs_index];
const load_ptr = load_data.ty_op.operand;
const load_ptr_tag = self.air.instructions.items(.tag)[Air.refToIndex(load_ptr).?];
switch (load_ptr_tag) {
.struct_field_ptr, .struct_field_ptr_index_0, .struct_field_ptr_index_1, .struct_field_ptr_index_2, .struct_field_ptr_index_3 => {
const load_ptr_inst = try self.resolveInst(load_ptr);
const gep = self.builder.buildInBoundsGEP(array_llvm_ty, load_ptr_inst, &indices, indices.len, "");
return self.builder.buildLoad(elem_llvm_ty, gep, "");
},
else => {},
if (Air.refToIndex(bin_op.lhs)) |lhs_index| {
if (self.air.instructions.items(.tag)[lhs_index] == .load) {
const load_data = self.air.instructions.items(.data)[lhs_index];
const load_ptr = load_data.ty_op.operand;
if (Air.refToIndex(load_ptr)) |load_ptr_index| {
const load_ptr_tag = self.air.instructions.items(.tag)[load_ptr_index];
switch (load_ptr_tag) {
.struct_field_ptr, .struct_field_ptr_index_0, .struct_field_ptr_index_1, .struct_field_ptr_index_2, .struct_field_ptr_index_3 => {
const load_ptr_inst = try self.resolveInst(load_ptr);
const gep = self.builder.buildInBoundsGEP(array_llvm_ty, load_ptr_inst, &indices, indices.len, "");
return self.builder.buildLoad(elem_llvm_ty, gep, "");
},
else => {},
}
}
}
}
const elem_ptr = self.builder.buildInBoundsGEP(array_llvm_ty, array_llvm_val, &indices, indices.len, "");