Merge pull request #17690

Sema: move remaining anon decls to new mechanism
This commit is contained in:
Andrew Kelley 2023-10-26 03:49:16 -04:00 committed by GitHub
commit ba817fae8f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 425 additions and 522 deletions

View File

@ -3556,7 +3556,7 @@ fn processOneJob(comp: *Compilation, job: Job, prog_node: *std.Progress.Node) !v
.gpa = gpa,
.module = module,
.error_msg = null,
.decl_index = decl_index.toOptional(),
.pass = .{ .decl = decl_index },
.is_naked_fn = false,
.fwd_decl = fwd_decl.toManaged(gpa),
.ctypes = .{},

View File

@ -5466,21 +5466,30 @@ fn addStrLitNoAlias(sema: *Sema, bytes: []const u8) CompileError!Air.Inst.Ref {
.ty = array_ty.toIntern(),
.storage = .{ .bytes = bytes },
} });
const ptr_ty = try sema.ptrType(.{
.child = array_ty.toIntern(),
return anonDeclRef(sema, val);
}
fn anonDeclRef(sema: *Sema, val: InternPool.Index) CompileError!Air.Inst.Ref {
return Air.internedToRef(try refValue(sema, val));
}
fn refValue(sema: *Sema, val: InternPool.Index) CompileError!InternPool.Index {
const mod = sema.mod;
const ptr_ty = (try sema.ptrType(.{
.child = mod.intern_pool.typeOf(val),
.flags = .{
.alignment = .none,
.is_const = true,
.address_space = .generic,
},
});
return Air.internedToRef((try mod.intern(.{ .ptr = .{
.ty = ptr_ty.toIntern(),
})).toIntern();
return mod.intern(.{ .ptr = .{
.ty = ptr_ty,
.addr = .{ .anon_decl = .{
.val = val,
.orig_ty = ptr_ty.toIntern(),
.orig_ty = ptr_ty,
} },
} })));
} });
}
fn zirInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
@ -10740,7 +10749,7 @@ const SwitchProngAnalysis = struct {
return block.addStructFieldVal(spa.operand, field_index, field_ty);
}
} else if (capture_byref) {
return sema.addConstantMaybeRef(block, operand_ty, item_val, true);
return anonDeclRef(sema, item_val.toIntern());
} else {
return inline_case_capture;
}
@ -13765,10 +13774,10 @@ fn zirArrayCat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
const coerced_elem_val = try sema.resolveConstValue(block, .unneeded, coerced_elem_val_inst, undefined);
element_vals[elem_i] = try coerced_elem_val.intern(resolved_elem_ty, mod);
}
return sema.addConstantMaybeRef(block, result_ty, (try mod.intern(.{ .aggregate = .{
return sema.addConstantMaybeRef(try mod.intern(.{ .aggregate = .{
.ty = result_ty.toIntern(),
.storage = .{ .elems = element_vals },
} })).toValue(), ptr_addrspace != null);
} }), ptr_addrspace != null);
} else break :rs rhs_src;
} else lhs_src;
@ -14034,7 +14043,7 @@ fn zirArrayMul(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
.storage = .{ .elems = element_vals },
} });
};
return sema.addConstantMaybeRef(block, result_ty, val.toValue(), ptr_addrspace != null);
return sema.addConstantMaybeRef(val, ptr_addrspace != null);
}
try sema.requireRuntimeBlock(block, src, lhs_src);
@ -16724,54 +16733,49 @@ fn zirBuiltinSrc(
const src = LazySrcLoc.nodeOffset(extra.node);
if (sema.func_index == .none) return sema.fail(block, src, "@src outside function", .{});
const fn_owner_decl = mod.funcOwnerDeclPtr(sema.func_index);
const ip = &mod.intern_pool;
const gpa = sema.gpa;
const func_name_val = blk: {
var anon_decl = try block.startAnonDecl();
defer anon_decl.deinit();
// TODO: write something like getCoercedInts to avoid needing to dupe
const name = try sema.arena.dupe(u8, mod.intern_pool.stringToSlice(fn_owner_decl.name));
const new_decl_ty = try mod.arrayType(.{
.len = name.len,
const func_name_val = v: {
// This dupe prevents InternPool string pool memory from being reallocated
// while a reference exists.
const bytes = try sema.arena.dupe(u8, ip.stringToSlice(fn_owner_decl.name));
const array_ty = try ip.get(gpa, .{ .array_type = .{
.len = bytes.len,
.sentinel = .zero_u8,
.child = .u8_type,
});
const new_decl = try anon_decl.finish(
new_decl_ty,
(try mod.intern(.{ .aggregate = .{
.ty = new_decl_ty.toIntern(),
.storage = .{ .bytes = name },
} })).toValue(),
.none, // default alignment
);
break :blk try mod.intern(.{ .ptr = .{
} });
break :v try ip.get(gpa, .{ .ptr = .{
.ty = .slice_const_u8_sentinel_0_type,
.addr = .{ .decl = new_decl },
.len = (try mod.intValue(Type.usize, name.len)).toIntern(),
.len = (try mod.intValue(Type.usize, bytes.len)).toIntern(),
.addr = .{ .anon_decl = .{
.orig_ty = .slice_const_u8_sentinel_0_type,
.val = try ip.get(gpa, .{ .aggregate = .{
.ty = array_ty,
.storage = .{ .bytes = bytes },
} }),
} },
} });
};
const file_name_val = blk: {
var anon_decl = try block.startAnonDecl();
defer anon_decl.deinit();
const file_name_val = v: {
// The compiler must not call realpath anywhere.
const name = try fn_owner_decl.getFileScope(mod).fullPathZ(sema.arena);
const new_decl_ty = try mod.arrayType(.{
.len = name.len,
const bytes = try fn_owner_decl.getFileScope(mod).fullPathZ(sema.arena);
const array_ty = try ip.get(gpa, .{ .array_type = .{
.len = bytes.len,
.sentinel = .zero_u8,
.child = .u8_type,
});
const new_decl = try anon_decl.finish(
new_decl_ty,
(try mod.intern(.{ .aggregate = .{
.ty = new_decl_ty.toIntern(),
.storage = .{ .bytes = name },
} })).toValue(),
.none, // default alignment
);
break :blk try mod.intern(.{ .ptr = .{
} });
break :v try ip.get(gpa, .{ .ptr = .{
.ty = .slice_const_u8_sentinel_0_type,
.addr = .{ .decl = new_decl },
.len = (try mod.intValue(Type.usize, name.len)).toIntern(),
.len = (try mod.intValue(Type.usize, bytes.len)).toIntern(),
.addr = .{ .anon_decl = .{
.orig_ty = .slice_const_u8_sentinel_0_type,
.val = try ip.get(gpa, .{ .aggregate = .{
.ty = array_ty,
.storage = .{ .bytes = bytes },
} }),
} },
} });
};
@ -16818,10 +16822,6 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
.val = .void_value,
} }))),
.Fn => {
// TODO: look into memoizing this result.
var params_anon_decl = try block.startAnonDecl();
defer params_anon_decl.deinit();
const fn_info_decl_index = (try sema.namespaceLookup(
block,
src,
@ -16878,23 +16878,23 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
.len = param_vals.len,
.child = param_info_ty.toIntern(),
});
const new_decl = try params_anon_decl.finish(
new_decl_ty,
(try mod.intern(.{ .aggregate = .{
.ty = new_decl_ty.toIntern(),
.storage = .{ .elems = param_vals },
} })).toValue(),
.none, // default alignment
);
const new_decl_val = try mod.intern(.{ .aggregate = .{
.ty = new_decl_ty.toIntern(),
.storage = .{ .elems = param_vals },
} });
const ptr_ty = (try sema.ptrType(.{
.child = param_info_ty.toIntern(),
.flags = .{
.size = .Slice,
.is_const = true,
},
})).toIntern();
break :v try mod.intern(.{ .ptr = .{
.ty = (try sema.ptrType(.{
.child = param_info_ty.toIntern(),
.flags = .{
.size = .Slice,
.is_const = true,
},
})).toIntern(),
.addr = .{ .decl = new_decl },
.ty = ptr_ty,
.addr = .{ .anon_decl = .{
.orig_ty = ptr_ty,
.val = new_decl_val,
} },
.len = (try mod.intValue(Type.usize, param_vals.len)).toIntern(),
} });
};
@ -17035,7 +17035,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
// is_allowzero: bool,
Value.makeBool(info.flags.is_allowzero).toIntern(),
// sentinel: ?*const anyopaque,
(try sema.optRefValue(block, info.child.toType(), switch (info.sentinel) {
(try sema.optRefValue(switch (info.sentinel) {
.none => null,
else => info.sentinel.toValue(),
})).toIntern(),
@ -17070,7 +17070,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
// child: type,
info.elem_type.toIntern(),
// sentinel: ?*const anyopaque,
(try sema.optRefValue(block, info.elem_type, info.sentinel)).toIntern(),
(try sema.optRefValue(info.sentinel)).toIntern(),
};
return Air.internedToRef((try mod.intern(.{ .un = .{
.ty = type_info_ty.toIntern(),
@ -17139,9 +17139,6 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
} })));
},
.ErrorSet => {
var fields_anon_decl = try block.startAnonDecl();
defer fields_anon_decl.deinit();
// Get the Error type
const error_field_ty = t: {
const set_field_ty_decl_index = (try sema.namespaceLookup(
@ -17170,23 +17167,20 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
// TODO: write something like getCoercedInts to avoid needing to dupe
const name = try sema.arena.dupe(u8, ip.stringToSlice(names.get(ip)[i]));
const name_val = v: {
var anon_decl = try block.startAnonDecl();
defer anon_decl.deinit();
const new_decl_ty = try mod.arrayType(.{
.len = name.len,
.child = .u8_type,
});
const new_decl = try anon_decl.finish(
new_decl_ty,
(try mod.intern(.{ .aggregate = .{
.ty = new_decl_ty.toIntern(),
.storage = .{ .bytes = name },
} })).toValue(),
.none, // default alignment
);
const new_decl_val = try mod.intern(.{ .aggregate = .{
.ty = new_decl_ty.toIntern(),
.storage = .{ .bytes = name },
} });
break :v try mod.intern(.{ .ptr = .{
.ty = .slice_const_u8_type,
.addr = .{ .decl = new_decl },
.addr = .{ .anon_decl = .{
.val = new_decl_val,
.orig_ty = .slice_const_u8_type,
} },
.len = (try mod.intValue(Type.usize, name.len)).toIntern(),
} });
};
@ -17219,17 +17213,16 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
.len = vals.len,
.child = error_field_ty.toIntern(),
});
const new_decl = try fields_anon_decl.finish(
array_errors_ty,
(try mod.intern(.{ .aggregate = .{
.ty = array_errors_ty.toIntern(),
.storage = .{ .elems = vals },
} })).toValue(),
.none, // default alignment
);
const new_decl_val = try mod.intern(.{ .aggregate = .{
.ty = array_errors_ty.toIntern(),
.storage = .{ .elems = vals },
} });
break :v try mod.intern(.{ .ptr = .{
.ty = slice_errors_ty.toIntern(),
.addr = .{ .decl = new_decl },
.addr = .{ .anon_decl = .{
.orig_ty = slice_errors_ty.toIntern(),
.val = new_decl_val,
} },
.len = (try mod.intValue(Type.usize, vals.len)).toIntern(),
} });
} else .none;
@ -17275,12 +17268,8 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
} })));
},
.Enum => {
// TODO: look into memoizing this result.
const is_exhaustive = Value.makeBool(ip.indexToKey(ty.toIntern()).enum_type.tag_mode != .nonexhaustive);
var fields_anon_decl = try block.startAnonDecl();
defer fields_anon_decl.deinit();
const enum_field_ty = t: {
const enum_field_ty_decl_index = (try sema.namespaceLookup(
block,
@ -17308,23 +17297,20 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
// TODO: write something like getCoercedInts to avoid needing to dupe
const name = try sema.arena.dupe(u8, ip.stringToSlice(enum_type.names.get(ip)[i]));
const name_val = v: {
var anon_decl = try block.startAnonDecl();
defer anon_decl.deinit();
const new_decl_ty = try mod.arrayType(.{
.len = name.len,
.child = .u8_type,
});
const new_decl = try anon_decl.finish(
new_decl_ty,
(try mod.intern(.{ .aggregate = .{
.ty = new_decl_ty.toIntern(),
.storage = .{ .bytes = name },
} })).toValue(),
.none, // default alignment
);
const new_decl_val = try mod.intern(.{ .aggregate = .{
.ty = new_decl_ty.toIntern(),
.storage = .{ .bytes = name },
} });
break :v try mod.intern(.{ .ptr = .{
.ty = .slice_const_u8_type,
.addr = .{ .decl = new_decl },
.addr = .{ .anon_decl = .{
.val = new_decl_val,
.orig_ty = .slice_const_u8_type,
} },
.len = (try mod.intValue(Type.usize, name.len)).toIntern(),
} });
};
@ -17346,23 +17332,23 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
.len = enum_field_vals.len,
.child = enum_field_ty.toIntern(),
});
const new_decl = try fields_anon_decl.finish(
fields_array_ty,
(try mod.intern(.{ .aggregate = .{
.ty = fields_array_ty.toIntern(),
.storage = .{ .elems = enum_field_vals },
} })).toValue(),
.none, // default alignment
);
const new_decl_val = try mod.intern(.{ .aggregate = .{
.ty = fields_array_ty.toIntern(),
.storage = .{ .elems = enum_field_vals },
} });
const ptr_ty = (try sema.ptrType(.{
.child = enum_field_ty.toIntern(),
.flags = .{
.size = .Slice,
.is_const = true,
},
})).toIntern();
break :v try mod.intern(.{ .ptr = .{
.ty = (try sema.ptrType(.{
.child = enum_field_ty.toIntern(),
.flags = .{
.size = .Slice,
.is_const = true,
},
})).toIntern(),
.addr = .{ .decl = new_decl },
.ty = ptr_ty,
.addr = .{ .anon_decl = .{
.val = new_decl_val,
.orig_ty = ptr_ty,
} },
.len = (try mod.intValue(Type.usize, enum_field_vals.len)).toIntern(),
} });
};
@ -17402,11 +17388,6 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
} })));
},
.Union => {
// TODO: look into memoizing this result.
var fields_anon_decl = try block.startAnonDecl();
defer fields_anon_decl.deinit();
const type_union_ty = t: {
const type_union_ty_decl_index = (try sema.namespaceLookup(
block,
@ -17444,23 +17425,20 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
// TODO: write something like getCoercedInts to avoid needing to dupe
const name = try sema.arena.dupe(u8, ip.stringToSlice(union_obj.field_names.get(ip)[i]));
const name_val = v: {
var anon_decl = try block.startAnonDecl();
defer anon_decl.deinit();
const new_decl_ty = try mod.arrayType(.{
.len = name.len,
.child = .u8_type,
});
const new_decl = try anon_decl.finish(
new_decl_ty,
(try mod.intern(.{ .aggregate = .{
.ty = new_decl_ty.toIntern(),
.storage = .{ .bytes = name },
} })).toValue(),
.none, // default alignment
);
const new_decl_val = try mod.intern(.{ .aggregate = .{
.ty = new_decl_ty.toIntern(),
.storage = .{ .bytes = name },
} });
break :v try mod.intern(.{ .ptr = .{
.ty = .slice_const_u8_type,
.addr = .{ .decl = new_decl },
.addr = .{ .anon_decl = .{
.val = new_decl_val,
.orig_ty = .slice_const_u8_type,
} },
.len = (try mod.intValue(Type.usize, name.len)).toIntern(),
} });
};
@ -17490,23 +17468,23 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
.len = union_field_vals.len,
.child = union_field_ty.toIntern(),
});
const new_decl = try fields_anon_decl.finish(
array_fields_ty,
(try mod.intern(.{ .aggregate = .{
.ty = array_fields_ty.toIntern(),
.storage = .{ .elems = union_field_vals },
} })).toValue(),
.none, // default alignment
);
const new_decl_val = try mod.intern(.{ .aggregate = .{
.ty = array_fields_ty.toIntern(),
.storage = .{ .elems = union_field_vals },
} });
const ptr_ty = (try sema.ptrType(.{
.child = union_field_ty.toIntern(),
.flags = .{
.size = .Slice,
.is_const = true,
},
})).toIntern();
break :v try mod.intern(.{ .ptr = .{
.ty = (try sema.ptrType(.{
.child = union_field_ty.toIntern(),
.flags = .{
.size = .Slice,
.is_const = true,
},
})).toIntern(),
.addr = .{ .decl = new_decl },
.ty = ptr_ty,
.addr = .{ .anon_decl = .{
.orig_ty = ptr_ty,
.val = new_decl_val,
} },
.len = (try mod.intValue(Type.usize, union_field_vals.len)).toIntern(),
} });
};
@ -17552,11 +17530,6 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
} })));
},
.Struct => {
// TODO: look into memoizing this result.
var fields_anon_decl = try block.startAnonDecl();
defer fields_anon_decl.deinit();
const type_struct_ty = t: {
const type_struct_ty_decl_index = (try sema.namespaceLookup(
block,
@ -17596,8 +17569,6 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
const field_ty = anon_struct_type.types.get(ip)[i];
const field_val = anon_struct_type.values.get(ip)[i];
const name_val = v: {
var anon_decl = try block.startAnonDecl();
defer anon_decl.deinit();
// TODO: write something like getCoercedInts to avoid needing to dupe
const bytes = if (tuple.names.len != 0)
// https://github.com/ziglang/zig/issues/15709
@ -17608,17 +17579,16 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
.len = bytes.len,
.child = .u8_type,
});
const new_decl = try anon_decl.finish(
new_decl_ty,
(try mod.intern(.{ .aggregate = .{
.ty = new_decl_ty.toIntern(),
.storage = .{ .bytes = bytes },
} })).toValue(),
.none, // default alignment
);
const new_decl_val = try mod.intern(.{ .aggregate = .{
.ty = new_decl_ty.toIntern(),
.storage = .{ .bytes = bytes },
} });
break :v try mod.intern(.{ .ptr = .{
.ty = .slice_const_u8_type,
.addr = .{ .decl = new_decl },
.addr = .{ .anon_decl = .{
.val = new_decl_val,
.orig_ty = .slice_const_u8_type,
} },
.len = (try mod.intValue(Type.usize, bytes.len)).toIntern(),
} });
};
@ -17627,7 +17597,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
const is_comptime = field_val != .none;
const opt_default_val = if (is_comptime) field_val.toValue() else null;
const default_val_ptr = try sema.optRefValue(block, field_ty.toType(), opt_default_val);
const default_val_ptr = try sema.optRefValue(opt_default_val);
const struct_field_fields = .{
// name: []const u8,
name_val,
@ -17662,29 +17632,26 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
const field_init = struct_type.fieldInit(ip, i);
const field_is_comptime = struct_type.fieldIsComptime(ip, i);
const name_val = v: {
var anon_decl = try block.startAnonDecl();
defer anon_decl.deinit();
const new_decl_ty = try mod.arrayType(.{
.len = name.len,
.child = .u8_type,
});
const new_decl = try anon_decl.finish(
new_decl_ty,
(try mod.intern(.{ .aggregate = .{
.ty = new_decl_ty.toIntern(),
.storage = .{ .bytes = name },
} })).toValue(),
.none, // default alignment
);
const new_decl_val = try mod.intern(.{ .aggregate = .{
.ty = new_decl_ty.toIntern(),
.storage = .{ .bytes = name },
} });
break :v try mod.intern(.{ .ptr = .{
.ty = .slice_const_u8_type,
.addr = .{ .decl = new_decl },
.addr = .{ .anon_decl = .{
.val = new_decl_val,
.orig_ty = .slice_const_u8_type,
} },
.len = (try mod.intValue(Type.usize, name.len)).toIntern(),
} });
};
const opt_default_val = if (field_init == .none) null else field_init.toValue();
const default_val_ptr = try sema.optRefValue(block, field_ty, opt_default_val);
const default_val_ptr = try sema.optRefValue(opt_default_val);
const alignment = switch (struct_type.layout) {
.Packed => .none,
else => try sema.structFieldAlignment(
@ -17718,23 +17685,23 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
.len = struct_field_vals.len,
.child = struct_field_ty.toIntern(),
});
const new_decl = try fields_anon_decl.finish(
array_fields_ty,
(try mod.intern(.{ .aggregate = .{
.ty = array_fields_ty.toIntern(),
.storage = .{ .elems = struct_field_vals },
} })).toValue(),
.none, // default alignment
);
const new_decl_val = try mod.intern(.{ .aggregate = .{
.ty = array_fields_ty.toIntern(),
.storage = .{ .elems = struct_field_vals },
} });
const ptr_ty = (try sema.ptrType(.{
.child = struct_field_ty.toIntern(),
.flags = .{
.size = .Slice,
.is_const = true,
},
})).toIntern();
break :v try mod.intern(.{ .ptr = .{
.ty = (try sema.ptrType(.{
.child = struct_field_ty.toIntern(),
.flags = .{
.size = .Slice,
.is_const = true,
},
})).toIntern(),
.addr = .{ .decl = new_decl },
.ty = ptr_ty,
.addr = .{ .anon_decl = .{
.orig_ty = ptr_ty,
.val = new_decl_val,
} },
.len = (try mod.intValue(Type.usize, struct_field_vals.len)).toIntern(),
} });
};
@ -17786,8 +17753,6 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
} })));
},
.Opaque => {
// TODO: look into memoizing this result.
const type_opaque_ty = t: {
const type_opaque_ty_decl_index = (try sema.namespaceLookup(
block,
@ -17832,9 +17797,6 @@ fn typeInfoDecls(
const mod = sema.mod;
const gpa = sema.gpa;
var decls_anon_decl = try block.startAnonDecl();
defer decls_anon_decl.deinit();
const declaration_ty = t: {
const declaration_ty_decl_index = (try sema.namespaceLookup(
block,
@ -17864,23 +17826,23 @@ fn typeInfoDecls(
.len = decl_vals.items.len,
.child = declaration_ty.toIntern(),
});
const new_decl = try decls_anon_decl.finish(
array_decl_ty,
(try mod.intern(.{ .aggregate = .{
.ty = array_decl_ty.toIntern(),
.storage = .{ .elems = decl_vals.items },
} })).toValue(),
.none, // default alignment
);
const new_decl_val = try mod.intern(.{ .aggregate = .{
.ty = array_decl_ty.toIntern(),
.storage = .{ .elems = decl_vals.items },
} });
const ptr_ty = (try sema.ptrType(.{
.child = declaration_ty.toIntern(),
.flags = .{
.size = .Slice,
.is_const = true,
},
})).toIntern();
return try mod.intern(.{ .ptr = .{
.ty = (try sema.ptrType(.{
.child = declaration_ty.toIntern(),
.flags = .{
.size = .Slice,
.is_const = true,
},
})).toIntern(),
.addr = .{ .decl = new_decl },
.ty = ptr_ty,
.addr = .{ .anon_decl = .{
.orig_ty = ptr_ty,
.val = new_decl_val,
} },
.len = (try mod.intValue(Type.usize, decl_vals.items.len)).toIntern(),
} });
}
@ -17909,25 +17871,22 @@ fn typeInfoNamespaceDecls(
}
if (decl.kind != .named or !decl.is_pub) continue;
const name_val = v: {
var anon_decl = try block.startAnonDecl();
defer anon_decl.deinit();
// TODO: write something like getCoercedInts to avoid needing to dupe
const name = try sema.arena.dupe(u8, ip.stringToSlice(decl.name));
const new_decl_ty = try mod.arrayType(.{
.len = name.len,
.child = .u8_type,
});
const new_decl = try anon_decl.finish(
new_decl_ty,
(try mod.intern(.{ .aggregate = .{
.ty = new_decl_ty.toIntern(),
.storage = .{ .bytes = name },
} })).toValue(),
.none, // default alignment
);
const new_decl_val = try mod.intern(.{ .aggregate = .{
.ty = new_decl_ty.toIntern(),
.storage = .{ .bytes = name },
} });
break :v try mod.intern(.{ .ptr = .{
.ty = .slice_const_u8_type,
.addr = .{ .decl = new_decl },
.addr = .{ .anon_decl = .{
.orig_ty = .slice_const_u8_type,
.val = new_decl_val,
} },
.len = (try mod.intValue(Type.usize, name.len)).toIntern(),
} });
};
@ -19072,10 +19031,7 @@ fn zirStructInitEmptyResult(sema: *Sema, block: *Block, inst: Zir.Inst.Index, is
if (is_byref) {
const init_val = (try sema.resolveValue(init_ref)).?;
var anon_decl = try block.startAnonDecl();
defer anon_decl.deinit();
const decl = try anon_decl.finish(init_ty, init_val, .none);
return sema.analyzeDeclRef(decl);
return anonDeclRef(sema, init_val.toIntern());
} else {
return init_ref;
}
@ -19298,7 +19254,7 @@ fn zirStructInit(
} })).toValue();
const final_val_inst = try sema.coerce(block, result_ty, Air.internedToRef(struct_val.toIntern()), src);
const final_val = (try sema.resolveValue(final_val_inst)).?;
return sema.addConstantMaybeRef(block, resolved_ty, final_val, is_ref);
return sema.addConstantMaybeRef(final_val.toIntern(), is_ref);
}
if (try sema.typeRequiresComptime(resolved_ty)) {
@ -19458,7 +19414,7 @@ fn finishStructInit(
} });
const final_val_inst = try sema.coerce(block, result_ty, Air.internedToRef(struct_val), init_src);
const final_val = (try sema.resolveValue(final_val_inst)).?;
return sema.addConstantMaybeRef(block, result_ty, final_val, is_ref);
return sema.addConstantMaybeRef(final_val.toIntern(), is_ref);
};
if (try sema.typeRequiresComptime(struct_ty)) {
@ -19611,7 +19567,7 @@ fn structInitAnon(
.ty = tuple_ty,
.storage = .{ .elems = values },
} });
return sema.addConstantMaybeRef(block, tuple_ty.toType(), tuple_val.toValue(), is_ref);
return sema.addConstantMaybeRef(tuple_val, is_ref);
};
sema.requireRuntimeBlock(block, .unneeded, null) catch |err| switch (err) {
@ -19777,7 +19733,8 @@ fn zirArrayInit(
.storage = .{ .elems = elem_vals },
} });
const result_ref = try sema.coerce(block, result_ty, Air.internedToRef(arr_val), src);
return sema.addConstantMaybeRef(block, result_ty, (try sema.resolveValue(result_ref)).?, is_ref);
const result_val = (try sema.resolveValue(result_ref)).?;
return sema.addConstantMaybeRef(result_val.toIntern(), is_ref);
};
sema.requireRuntimeBlock(block, .unneeded, null) catch |err| switch (err) {
@ -19896,7 +19853,7 @@ fn arrayInitAnon(
.ty = tuple_ty,
.storage = .{ .elems = values },
} });
return sema.addConstantMaybeRef(block, tuple_ty.toType(), tuple_val.toValue(), is_ref);
return sema.addConstantMaybeRef(tuple_val, is_ref);
};
try sema.requireRuntimeBlock(block, src, runtime_src);
@ -19931,23 +19888,8 @@ fn arrayInitAnon(
return block.addAggregateInit(tuple_ty.toType(), element_refs);
}
fn addConstantMaybeRef(
sema: *Sema,
block: *Block,
ty: Type,
val: Value,
is_ref: bool,
) !Air.Inst.Ref {
if (!is_ref) return Air.internedToRef(val.toIntern());
var anon_decl = try block.startAnonDecl();
defer anon_decl.deinit();
const decl = try anon_decl.finish(
ty,
val,
.none, // default alignment
);
return sema.analyzeDeclRef(decl);
fn addConstantMaybeRef(sema: *Sema, val: InternPool.Index, is_ref: bool) !Air.Inst.Ref {
return if (is_ref) anonDeclRef(sema, val) else Air.internedToRef(val);
}
fn zirFieldTypeRef(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
@ -21429,28 +21371,9 @@ fn zirTypeName(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
const ty_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node };
const ty = try sema.resolveType(block, ty_src, inst_data.operand);
var anon_decl = try block.startAnonDecl();
defer anon_decl.deinit();
var bytes = std.ArrayList(u8).init(sema.arena);
defer bytes.deinit();
try ty.print(bytes.writer(), mod);
const decl_ty = try mod.arrayType(.{
.len = bytes.items.len,
.sentinel = .zero_u8,
.child = .u8_type,
});
const new_decl = try anon_decl.finish(
decl_ty,
(try mod.intern(.{ .aggregate = .{
.ty = decl_ty.toIntern(),
.storage = .{ .bytes = bytes.items },
} })).toValue(),
.none, // default alignment
);
return sema.analyzeDeclRef(new_decl);
return addStrLitNoAlias(sema, bytes.items);
}
fn zirFrameType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
@ -26333,13 +26256,8 @@ fn fieldPtr(
switch (inner_ty.zigTypeTag(mod)) {
.Array => {
if (ip.stringEqlSlice(field_name, "len")) {
var anon_decl = try block.startAnonDecl();
defer anon_decl.deinit();
return sema.analyzeDeclRef(try anon_decl.finish(
Type.usize,
try mod.intValue(Type.usize, inner_ty.arrayLen(mod)),
.none, // default alignment
));
const int_val = try mod.intValue(Type.usize, inner_ty.arrayLen(mod));
return anonDeclRef(sema, int_val.toIntern());
} else {
return sema.fail(
block,
@ -26448,20 +26366,14 @@ fn fieldPtr(
else => unreachable,
}
var anon_decl = try block.startAnonDecl();
defer anon_decl.deinit();
const error_set_type = if (!child_type.isAnyError(mod))
child_type
else
try mod.singleErrorSetType(field_name);
return sema.analyzeDeclRef(try anon_decl.finish(
error_set_type,
(try mod.intern(.{ .err = .{
.ty = error_set_type.toIntern(),
.name = field_name,
} })).toValue(),
.none, // default alignment
));
return anonDeclRef(sema, try mod.intern(.{ .err = .{
.ty = error_set_type.toIntern(),
.name = field_name,
} }));
},
.Union => {
if (child_type.getNamespaceIndex(mod).unwrap()) |namespace| {
@ -26473,13 +26385,8 @@ fn fieldPtr(
if (child_type.unionTagType(mod)) |enum_ty| {
if (enum_ty.enumFieldIndex(field_name, mod)) |field_index| {
const field_index_u32: u32 = @intCast(field_index);
var anon_decl = try block.startAnonDecl();
defer anon_decl.deinit();
return sema.analyzeDeclRef(try anon_decl.finish(
enum_ty,
try mod.enumValueFieldIndex(enum_ty, field_index_u32),
.none, // default alignment
));
const idx_val = try mod.enumValueFieldIndex(enum_ty, field_index_u32);
return anonDeclRef(sema, idx_val.toIntern());
}
}
return sema.failWithBadMemberAccess(block, child_type, field_name_src, field_name);
@ -26494,13 +26401,8 @@ fn fieldPtr(
return sema.failWithBadMemberAccess(block, child_type, field_name_src, field_name);
};
const field_index_u32: u32 = @intCast(field_index);
var anon_decl = try block.startAnonDecl();
defer anon_decl.deinit();
return sema.analyzeDeclRef(try anon_decl.finish(
child_type,
try mod.enumValueFieldIndex(child_type, field_index_u32),
.none, // default alignment
));
const idx_val = try mod.enumValueFieldIndex(child_type, field_index_u32);
return anonDeclRef(sema, idx_val.toIntern());
},
.Struct, .Opaque => {
if (child_type.getNamespaceIndex(mod).unwrap()) |namespace| {
@ -31669,31 +31571,13 @@ fn ensureFuncBodyAnalyzed(sema: *Sema, func: InternPool.Index) CompileError!void
};
}
fn refValue(sema: *Sema, block: *Block, ty: Type, val: Value) !Value {
const mod = sema.mod;
var anon_decl = try block.startAnonDecl();
defer anon_decl.deinit();
const decl = try anon_decl.finish(
ty,
val,
.none, // default alignment
);
try sema.maybeQueueFuncBodyAnalysis(decl);
try mod.declareDeclDependency(sema.owner_decl_index, decl);
const result = try mod.intern(.{ .ptr = .{
.ty = (try mod.singleConstPtrType(ty)).toIntern(),
.addr = .{ .decl = decl },
} });
return result.toValue();
}
fn optRefValue(sema: *Sema, block: *Block, ty: Type, opt_val: ?Value) !Value {
fn optRefValue(sema: *Sema, opt_val: ?Value) !Value {
const mod = sema.mod;
const ptr_anyopaque_ty = try mod.singleConstPtrType(Type.anyopaque);
return (try mod.intern(.{ .opt = .{
.ty = (try mod.optionalType(ptr_anyopaque_ty.toIntern())).toIntern(),
.val = if (opt_val) |val| (try mod.getCoerced(
try sema.refValue(block, ty, val),
(try sema.refValue(val.toIntern())).toValue(),
ptr_anyopaque_ty,
)).toIntern() else .none,
} })).toValue();
@ -31755,15 +31639,8 @@ fn analyzeRef(
switch (mod.intern_pool.indexToKey(val.toIntern())) {
.extern_func => |extern_func| return sema.analyzeDeclRef(extern_func.decl),
.func => |func| return sema.analyzeDeclRef(func.owner_decl),
else => {},
else => return anonDeclRef(sema, val.toIntern()),
}
var anon_decl = try block.startAnonDecl();
defer anon_decl.deinit();
return sema.analyzeDeclRef(try anon_decl.finish(
operand_ty,
val,
.none, // default alignment
));
}
try sema.requireRuntimeBlock(block, src, null);
@ -36848,7 +36725,7 @@ fn analyzeComptimeAlloc(
},
});
var anon_decl = try block.startAnonDecl();
var anon_decl = try block.startAnonDecl(); // TODO: comptime value mutation without Decl
defer anon_decl.deinit();
const decl_index = try anon_decl.finish(

View File

@ -522,7 +522,7 @@ pub const Object = struct {
pub const DeclGen = struct {
gpa: mem.Allocator,
module: *Module,
decl_index: Decl.OptionalIndex,
pass: Pass,
is_naked_fn: bool,
/// This is a borrowed reference from `link.C`.
fwd_decl: std.ArrayList(u8),
@ -533,10 +533,16 @@ pub const DeclGen = struct {
anon_decl_deps: std.AutoArrayHashMapUnmanaged(InternPool.Index, C.DeclBlock),
aligned_anon_decls: std.AutoArrayHashMapUnmanaged(InternPool.Index, Alignment),
pub const Pass = union(enum) {
decl: Decl.Index,
anon: InternPool.Index,
flush,
};
fn fail(dg: *DeclGen, comptime format: []const u8, args: anytype) error{ AnalysisFail, OutOfMemory } {
@setCold(true);
const mod = dg.module;
const decl_index = dg.decl_index.unwrap().?;
const decl_index = dg.pass.decl;
const decl = mod.declPtr(decl_index);
const src = LazySrcLoc.nodeOffset(0);
const src_loc = src.toSrcLoc(decl, mod);
@ -1284,11 +1290,14 @@ pub const DeclGen = struct {
var index: usize = 0;
while (index < ai.len) : (index += 1) {
const elem_val = try val.elemValue(mod, index);
const elem_val_u8 = if (elem_val.isUndef(mod)) undefPattern(u8) else @as(u8, @intCast(elem_val.toUnsignedInt(mod)));
const elem_val_u8: u8 = if (elem_val.isUndef(mod))
undefPattern(u8)
else
@intCast(elem_val.toUnsignedInt(mod));
try literal.writeChar(elem_val_u8);
}
if (ai.sentinel) |s| {
const s_u8 = @as(u8, @intCast(s.toUnsignedInt(mod)));
const s_u8: u8 = @intCast(s.toUnsignedInt(mod));
if (s_u8 != 0) try literal.writeChar(s_u8);
}
try literal.end();
@ -1298,7 +1307,10 @@ pub const DeclGen = struct {
while (index < ai.len) : (index += 1) {
if (index != 0) try writer.writeByte(',');
const elem_val = try val.elemValue(mod, index);
const elem_val_u8 = if (elem_val.isUndef(mod)) undefPattern(u8) else @as(u8, @intCast(elem_val.toUnsignedInt(mod)));
const elem_val_u8: u8 = if (elem_val.isUndef(mod))
undefPattern(u8)
else
@intCast(elem_val.toUnsignedInt(mod));
try writer.print("'\\x{x}'", .{elem_val_u8});
}
if (ai.sentinel) |s| {
@ -1566,18 +1578,11 @@ pub const DeclGen = struct {
else => unreachable,
}
}
if (fn_decl.val.getFunction(mod)) |func| if (func.analysis(ip).is_cold) try w.writeAll("zig_cold ");
if (fn_decl.val.getFunction(mod)) |func| if (func.analysis(ip).is_cold)
try w.writeAll("zig_cold ");
if (fn_info.return_type == .noreturn_type) try w.writeAll("zig_noreturn ");
const trailing = try renderTypePrefix(
dg.decl_index,
store.*,
mod,
w,
fn_cty_idx,
.suffix,
.{},
);
const trailing = try renderTypePrefix(dg.pass, store.*, mod, w, fn_cty_idx, .suffix, .{});
try w.print("{}", .{trailing});
if (toCallingConvention(fn_info.cc)) |call_conv| {
@ -1597,7 +1602,7 @@ pub const DeclGen = struct {
}
try renderTypeSuffix(
dg.decl_index,
dg.pass,
store.*,
mod,
w,
@ -1652,8 +1657,8 @@ pub const DeclGen = struct {
fn renderCType(dg: *DeclGen, w: anytype, idx: CType.Index) error{ OutOfMemory, AnalysisFail }!void {
const store = &dg.ctypes.set;
const mod = dg.module;
_ = try renderTypePrefix(dg.decl_index, store.*, mod, w, idx, .suffix, .{});
try renderTypeSuffix(dg.decl_index, store.*, mod, w, idx, .suffix, .{});
_ = try renderTypePrefix(dg.pass, store.*, mod, w, idx, .suffix, .{});
try renderTypeSuffix(dg.pass, store.*, mod, w, idx, .suffix, .{});
}
const IntCastContext = union(enum) {
@ -1799,11 +1804,10 @@ pub const DeclGen = struct {
.gt => try w.print("zig_align({}) ", .{alignas.toByteUnits()}),
}
const trailing =
try renderTypePrefix(dg.decl_index, store.*, mod, w, cty_idx, .suffix, qualifiers);
const trailing = try renderTypePrefix(dg.pass, store.*, mod, w, cty_idx, .suffix, qualifiers);
try w.print("{}", .{trailing});
try dg.writeCValue(w, name);
try renderTypeSuffix(dg.decl_index, store.*, mod, w, cty_idx, .suffix, .{});
try renderTypeSuffix(dg.pass, store.*, mod, w, cty_idx, .suffix, .{});
}
fn declIsGlobal(dg: *DeclGen, tv: TypedValue) bool {
@ -2070,7 +2074,7 @@ fn renderTypeName(
}
}
fn renderTypePrefix(
decl: Decl.OptionalIndex,
pass: DeclGen.Pass,
store: CType.Store.Set,
mod: *Module,
w: anytype,
@ -2128,7 +2132,7 @@ fn renderTypePrefix(
=> |tag| {
const child_idx = cty.cast(CType.Payload.Child).?.data;
const child_trailing = try renderTypePrefix(
decl,
pass,
store,
mod,
w,
@ -2152,15 +2156,8 @@ fn renderTypePrefix(
.vector,
=> {
const child_idx = cty.cast(CType.Payload.Sequence).?.data.elem_type;
const child_trailing = try renderTypePrefix(
decl,
store,
mod,
w,
child_idx,
.suffix,
qualifiers,
);
const child_trailing =
try renderTypePrefix(pass, store, mod, w, child_idx, .suffix, qualifiers);
switch (parent_fix) {
.prefix => {
try w.print("{}(", .{child_trailing});
@ -2172,10 +2169,11 @@ fn renderTypePrefix(
.fwd_anon_struct,
.fwd_anon_union,
=> if (decl.unwrap()) |decl_index|
try w.print("anon__{d}_{d}", .{ @intFromEnum(decl_index), idx })
else
try renderTypeName(mod, w, idx, cty, ""),
=> switch (pass) {
.decl => |decl_index| try w.print("decl__{d}_{d}", .{ @intFromEnum(decl_index), idx }),
.anon => |anon_decl| try w.print("anon__{d}_{d}", .{ @intFromEnum(anon_decl), idx }),
.flush => try renderTypeName(mod, w, idx, cty, ""),
},
.fwd_struct,
.fwd_union,
@ -2201,7 +2199,7 @@ fn renderTypePrefix(
.packed_struct,
.packed_union,
=> return renderTypePrefix(
decl,
pass,
store,
mod,
w,
@ -2214,7 +2212,7 @@ fn renderTypePrefix(
.varargs_function,
=> {
const child_trailing = try renderTypePrefix(
decl,
pass,
store,
mod,
w,
@ -2241,7 +2239,7 @@ fn renderTypePrefix(
return trailing;
}
fn renderTypeSuffix(
decl: Decl.OptionalIndex,
pass: DeclGen.Pass,
store: CType.Store.Set,
mod: *Module,
w: anytype,
@ -2295,7 +2293,7 @@ fn renderTypeSuffix(
.pointer_volatile,
.pointer_const_volatile,
=> try renderTypeSuffix(
decl,
pass,
store,
mod,
w,
@ -2314,7 +2312,7 @@ fn renderTypeSuffix(
try w.print("[{}]", .{cty.cast(CType.Payload.Sequence).?.data.len});
try renderTypeSuffix(
decl,
pass,
store,
mod,
w,
@ -2356,9 +2354,9 @@ fn renderTypeSuffix(
if (need_comma) try w.writeAll(", ");
need_comma = true;
const trailing =
try renderTypePrefix(decl, store, mod, w, param_type, .suffix, qualifiers);
try renderTypePrefix(pass, store, mod, w, param_type, .suffix, qualifiers);
if (qualifiers.contains(.@"const")) try w.print("{}a{d}", .{ trailing, param_i });
try renderTypeSuffix(decl, store, mod, w, param_type, .suffix, .{});
try renderTypeSuffix(pass, store, mod, w, param_type, .suffix, .{});
}
switch (tag) {
.function => {},
@ -2372,7 +2370,7 @@ fn renderTypeSuffix(
if (!need_comma) try w.writeAll("void");
try w.writeByte(')');
try renderTypeSuffix(decl, store, mod, w, data.return_type, .suffix, .{});
try renderTypeSuffix(pass, store, mod, w, data.return_type, .suffix, .{});
},
}
}
@ -2392,9 +2390,9 @@ fn renderAggregateFields(
.eq => {},
.gt => try writer.print("zig_align({}) ", .{field.alignas.toByteUnits()}),
}
const trailing = try renderTypePrefix(.none, store, mod, writer, field.type, .suffix, .{});
const trailing = try renderTypePrefix(.flush, store, mod, writer, field.type, .suffix, .{});
try writer.print("{}{ }", .{ trailing, fmtIdent(mem.span(field.name)) });
try renderTypeSuffix(.none, store, mod, writer, field.type, .suffix, .{});
try renderTypeSuffix(.flush, store, mod, writer, field.type, .suffix, .{});
try writer.writeAll(";\n");
}
try writer.writeByteNTimes(' ', indent);
@ -2406,18 +2404,18 @@ pub fn genTypeDecl(
writer: anytype,
global_store: CType.Store.Set,
global_idx: CType.Index,
decl: Decl.OptionalIndex,
pass: DeclGen.Pass,
decl_store: CType.Store.Set,
decl_idx: CType.Index,
found_existing: bool,
) !void {
const global_cty = global_store.indexToCType(global_idx);
switch (global_cty.tag()) {
.fwd_anon_struct => if (decl != .none) {
.fwd_anon_struct => if (pass != .flush) {
try writer.writeAll("typedef ");
_ = try renderTypePrefix(.none, global_store, mod, writer, global_idx, .suffix, .{});
_ = try renderTypePrefix(.flush, global_store, mod, writer, global_idx, .suffix, .{});
try writer.writeByte(' ');
_ = try renderTypePrefix(decl, decl_store, mod, writer, decl_idx, .suffix, .{});
_ = try renderTypePrefix(pass, decl_store, mod, writer, decl_idx, .suffix, .{});
try writer.writeAll(";\n");
},
@ -2435,7 +2433,15 @@ pub fn genTypeDecl(
.fwd_union,
=> {
const owner_decl = global_cty.cast(CType.Payload.FwdDecl).?.data;
_ = try renderTypePrefix(.none, global_store, mod, writer, global_idx, .suffix, .{});
_ = try renderTypePrefix(
.flush,
global_store,
mod,
writer,
global_idx,
.suffix,
.{},
);
try writer.writeAll("; // ");
try mod.declPtr(owner_decl).renderFullyQualifiedName(mod, writer);
try writer.writeByte('\n');
@ -2552,7 +2558,7 @@ fn genExports(o: *Object) !void {
const mod = o.dg.module;
const ip = &mod.intern_pool;
const decl_index = o.dg.decl_index.unwrap().?;
const decl_index = o.dg.pass.decl;
const decl = mod.declPtr(decl_index);
const tv: TypedValue = .{ .ty = decl.ty, .val = (try decl.internValue(mod)).toValue() };
const fwd = o.dg.fwd_decl.writer();
@ -2692,7 +2698,7 @@ pub fn genFunc(f: *Function) !void {
const o = &f.object;
const mod = o.dg.module;
const gpa = o.dg.gpa;
const decl_index = o.dg.decl_index.unwrap().?;
const decl_index = o.dg.pass.decl;
const decl = mod.declPtr(decl_index);
const tv: TypedValue = .{
.ty = decl.ty,
@ -2779,7 +2785,7 @@ pub fn genDecl(o: *Object) !void {
defer tracy.end();
const mod = o.dg.module;
const decl_index = o.dg.decl_index.unwrap().?;
const decl_index = o.dg.pass.decl;
const decl = mod.declPtr(decl_index);
const tv: TypedValue = .{ .ty = decl.ty, .val = (try decl.internValue(mod)).toValue() };
@ -2825,13 +2831,13 @@ pub fn genDeclValue(
alignment: Alignment,
link_section: InternPool.OptionalNullTerminatedString,
) !void {
const mod = o.dg.module;
const fwd_decl_writer = o.dg.fwd_decl.writer();
try fwd_decl_writer.writeAll(if (is_global) "zig_extern " else "static ");
try o.dg.renderTypeAndName(fwd_decl_writer, tv.ty, decl_c_value, Const, alignment, .complete);
try fwd_decl_writer.writeAll(";\n");
const mod = o.dg.module;
const w = o.writer();
if (!is_global) try w.writeAll("static ");
if (mod.intern_pool.stringToSliceUnwrap(link_section)) |s|
@ -2848,7 +2854,7 @@ pub fn genHeader(dg: *DeclGen) error{ AnalysisFail, OutOfMemory }!void {
defer tracy.end();
const mod = dg.module;
const decl_index = dg.decl_index.unwrap().?;
const decl_index = dg.pass.decl;
const decl = mod.declPtr(decl_index);
const tv: TypedValue = .{
.ty = decl.ty,
@ -2861,7 +2867,7 @@ pub fn genHeader(dg: *DeclGen) error{ AnalysisFail, OutOfMemory }!void {
const is_global = dg.declIsGlobal(tv);
if (is_global) {
try writer.writeAll("zig_extern ");
try dg.renderFunctionSignature(writer, dg.decl_index.unwrap().?, .complete, .{ .export_index = 0 });
try dg.renderFunctionSignature(writer, dg.pass.decl, .complete, .{ .export_index = 0 });
try dg.fwd_decl.appendSlice(";\n");
}
},
@ -7279,7 +7285,7 @@ fn airMulAdd(f: *Function, inst: Air.Inst.Index) !CValue {
fn airCVaStart(f: *Function, inst: Air.Inst.Index) !CValue {
const mod = f.object.dg.module;
const inst_ty = f.typeOfIndex(inst);
const decl_index = f.object.dg.decl_index.unwrap().?;
const decl_index = f.object.dg.pass.decl;
const decl = mod.declPtr(decl_index);
const fn_cty = try f.typeToCType(decl.ty, .complete);
const param_len = fn_cty.castTag(.varargs_function).?.data.param_types.len;

View File

@ -158,9 +158,7 @@ pub fn updateFunc(
const decl_index = func.owner_decl;
const decl = module.declPtr(decl_index);
const gop = try self.decl_table.getOrPut(gpa, decl_index);
if (!gop.found_existing) {
gop.value_ptr.* = .{};
}
if (!gop.found_existing) gop.value_ptr.* = .{};
const ctypes = &gop.value_ptr.ctypes;
const lazy_fns = &gop.value_ptr.lazy_fns;
const fwd_decl = &self.fwd_decl_buf;
@ -180,7 +178,7 @@ pub fn updateFunc(
.gpa = gpa,
.module = module,
.error_msg = null,
.decl_index = decl_index.toOptional(),
.pass = .{ .decl = decl_index },
.is_naked_fn = decl.ty.fnCallingConvention(module) == .Naked,
.fwd_decl = fwd_decl.toManaged(gpa),
.ctypes = ctypes.*,
@ -235,7 +233,7 @@ fn updateAnonDecl(self: *C, module: *Module, i: usize) !void {
.gpa = gpa,
.module = module,
.error_msg = null,
.decl_index = .none,
.pass = .{ .anon = anon_decl },
.is_naked_fn = false,
.fwd_decl = fwd_decl.toManaged(gpa),
.ctypes = .{},
@ -302,7 +300,7 @@ pub fn updateDecl(self: *C, module: *Module, decl_index: Module.Decl.Index) !voi
.gpa = gpa,
.module = module,
.error_msg = null,
.decl_index = decl_index.toOptional(),
.pass = .{ .decl = decl_index },
.is_naked_fn = false,
.fwd_decl = fwd_decl.toManaged(gpa),
.ctypes = ctypes.*,
@ -438,14 +436,14 @@ pub fn flushModule(self: *C, _: *Compilation, prog_node: *std.Progress.Node) !vo
// We need to flush lazy ctypes after flushing all decls but before flushing any decl ctypes.
// This ensures that every lazy CType.Index exactly matches the global CType.Index.
assert(f.ctypes.count() == 0);
try self.flushCTypes(&f, .none, f.lazy_ctypes);
try self.flushCTypes(&f, .flush, f.lazy_ctypes);
for (self.anon_decls.values()) |decl_block| {
try self.flushCTypes(&f, .none, decl_block.ctypes);
for (self.anon_decls.keys(), self.anon_decls.values()) |anon_decl, decl_block| {
try self.flushCTypes(&f, .{ .anon = anon_decl }, decl_block.ctypes);
}
for (self.decl_table.keys(), self.decl_table.values()) |decl_index, decl_block| {
try self.flushCTypes(&f, decl_index.toOptional(), decl_block.ctypes);
try self.flushCTypes(&f, .{ .decl = decl_index }, decl_block.ctypes);
}
}
@ -516,7 +514,7 @@ const FlushDeclError = error{
fn flushCTypes(
self: *C,
f: *Flush,
decl_index: Module.Decl.OptionalIndex,
pass: codegen.DeclGen.Pass,
decl_ctypes: codegen.CType.Store,
) FlushDeclError!void {
const gpa = self.base.allocator;
@ -591,7 +589,7 @@ fn flushCTypes(
writer,
global_ctypes.set,
global_idx,
decl_index,
pass,
decl_ctypes.set,
decl_idx,
gop.found_existing,
@ -610,7 +608,7 @@ fn flushErrDecls(self: *C, ctypes: *codegen.CType.Store) FlushDeclError!void {
.gpa = gpa,
.module = self.base.options.module.?,
.error_msg = null,
.decl_index = .none,
.pass = .flush,
.is_naked_fn = false,
.fwd_decl = fwd_decl.toManaged(gpa),
.ctypes = ctypes.*,
@ -652,7 +650,7 @@ fn flushLazyFn(
.gpa = gpa,
.module = self.base.options.module.?,
.error_msg = null,
.decl_index = .none,
.pass = .flush,
.is_naked_fn = false,
.fwd_decl = fwd_decl.toManaged(gpa),
.ctypes = ctypes.*,

View File

@ -1737,46 +1737,51 @@ pub fn getDeclVAddr(self: *Coff, decl_index: Module.Decl.Index, reloc_info: link
return 0;
}
pub fn lowerAnonDecl(self: *Coff, decl_val: InternPool.Index, decl_align: InternPool.Alignment, src_loc: Module.SrcLoc) !codegen.Result {
// This is basically the same as lowerUnnamedConst.
// example:
// const ty = mod.intern_pool.typeOf(decl_val).toType();
// const val = decl_val.toValue();
// The symbol name can be something like `__anon_{d}` with `@intFromEnum(decl_val)`.
// It doesn't have an owner decl because it's just an unnamed constant that might
// be used by more than one function, however, its address is being used so we need
// to put it in some location.
// ...
pub fn lowerAnonDecl(
self: *Coff,
decl_val: InternPool.Index,
explicit_alignment: InternPool.Alignment,
src_loc: Module.SrcLoc,
) !codegen.Result {
const gpa = self.base.allocator;
const mod = self.base.options.module.?;
const ty = mod.intern_pool.typeOf(decl_val).toType();
const gop = try self.anon_decls.getOrPut(gpa, decl_val);
const required_alignment = switch (decl_align) {
const decl_alignment = switch (explicit_alignment) {
.none => ty.abiAlignment(mod),
else => decl_align,
else => explicit_alignment,
};
if (!gop.found_existing or
!required_alignment.check(self.getAtom(gop.value_ptr.*).getSymbol(self).value))
{
const val = decl_val.toValue();
const tv = TypedValue{ .ty = ty, .val = val };
const name = try std.fmt.allocPrint(gpa, "__anon_{d}", .{@intFromEnum(decl_val)});
defer gpa.free(name);
const res = self.lowerConst(name, tv, required_alignment, self.rdata_section_index.?, src_loc) catch |err| switch (err) {
else => {
// TODO improve error message
const em = try Module.ErrorMsg.create(gpa, src_loc, "lowerAnonDecl failed with error: {s}", .{
@errorName(err),
});
return .{ .fail = em };
},
};
const atom_index = switch (res) {
.ok => |atom_index| atom_index,
.fail => |em| return .{ .fail = em },
};
gop.value_ptr.* = atom_index;
if (self.anon_decls.get(decl_val)) |atom_index| {
const existing_addr = self.getAtom(atom_index).getSymbol(self).value;
if (decl_alignment.check(existing_addr))
return .ok;
}
const val = decl_val.toValue();
const tv = TypedValue{ .ty = ty, .val = val };
var name_buf: [32]u8 = undefined;
const name = std.fmt.bufPrint(&name_buf, "__anon_{d}", .{
@intFromEnum(decl_val),
}) catch unreachable;
const res = self.lowerConst(
name,
tv,
decl_alignment,
self.rdata_section_index.?,
src_loc,
) catch |err| switch (err) {
error.OutOfMemory => return error.OutOfMemory,
else => |e| return .{ .fail = try Module.ErrorMsg.create(
gpa,
src_loc,
"lowerAnonDecl failed with error: {s}",
.{@errorName(e)},
) },
};
const atom_index = switch (res) {
.ok => |atom_index| atom_index,
.fail => |em| return .{ .fail = em },
};
try self.anon_decls.put(gpa, decl_val, atom_index);
return .ok;
}

View File

@ -484,46 +484,51 @@ pub fn getDeclVAddr(self: *Elf, decl_index: Module.Decl.Index, reloc_info: link.
return vaddr;
}
pub fn lowerAnonDecl(self: *Elf, decl_val: InternPool.Index, decl_align: InternPool.Alignment, src_loc: Module.SrcLoc) !codegen.Result {
// This is basically the same as lowerUnnamedConst.
// example:
// const ty = mod.intern_pool.typeOf(decl_val).toType();
// const val = decl_val.toValue();
// The symbol name can be something like `__anon_{d}` with `@intFromEnum(decl_val)`.
// It doesn't have an owner decl because it's just an unnamed constant that might
// be used by more than one function, however, its address is being used so we need
// to put it in some location.
// ...
pub fn lowerAnonDecl(
self: *Elf,
decl_val: InternPool.Index,
explicit_alignment: InternPool.Alignment,
src_loc: Module.SrcLoc,
) !codegen.Result {
const gpa = self.base.allocator;
const mod = self.base.options.module.?;
const ty = mod.intern_pool.typeOf(decl_val).toType();
const gop = try self.anon_decls.getOrPut(gpa, decl_val);
const required_alignment = switch (decl_align) {
const decl_alignment = switch (explicit_alignment) {
.none => ty.abiAlignment(mod),
else => decl_align,
else => explicit_alignment,
};
if (!gop.found_existing or
required_alignment.order(self.symbol(gop.value_ptr.*).atom(self).?.alignment).compare(.gt))
{
const val = decl_val.toValue();
const tv = TypedValue{ .ty = ty, .val = val };
const name = try std.fmt.allocPrint(gpa, "__anon_{d}", .{@intFromEnum(decl_val)});
defer gpa.free(name);
const res = self.lowerConst(name, tv, required_alignment, self.zig_rodata_section_index.?, src_loc) catch |err| switch (err) {
else => {
// TODO improve error message
const em = try Module.ErrorMsg.create(gpa, src_loc, "lowerAnonDecl failed with error: {s}", .{
@errorName(err),
});
return .{ .fail = em };
},
};
const sym_index = switch (res) {
.ok => |sym_index| sym_index,
.fail => |em| return .{ .fail = em },
};
gop.value_ptr.* = sym_index;
if (self.anon_decls.get(decl_val)) |sym_index| {
const existing_alignment = self.symbol(sym_index).atom(self).?.alignment;
if (decl_alignment.order(existing_alignment).compare(.lte))
return .ok;
}
const val = decl_val.toValue();
const tv = TypedValue{ .ty = ty, .val = val };
var name_buf: [32]u8 = undefined;
const name = std.fmt.bufPrint(&name_buf, "__anon_{d}", .{
@intFromEnum(decl_val),
}) catch unreachable;
const res = self.lowerConst(
name,
tv,
decl_alignment,
self.zig_rodata_section_index.?,
src_loc,
) catch |err| switch (err) {
error.OutOfMemory => return error.OutOfMemory,
else => |e| return .{ .fail = try Module.ErrorMsg.create(
gpa,
src_loc,
"unable to lower constant value: {s}",
.{@errorName(e)},
) },
};
const sym_index = switch (res) {
.ok => |sym_index| sym_index,
.fail => |em| return .{ .fail = em },
};
try self.anon_decls.put(gpa, decl_val, sym_index);
return .ok;
}

View File

@ -2866,46 +2866,51 @@ pub fn getDeclVAddr(self: *MachO, decl_index: Module.Decl.Index, reloc_info: Fil
return 0;
}
pub fn lowerAnonDecl(self: *MachO, decl_val: InternPool.Index, decl_align: InternPool.Alignment, src_loc: Module.SrcLoc) !codegen.Result {
// This is basically the same as lowerUnnamedConst.
// example:
// const ty = mod.intern_pool.typeOf(decl_val).toType();
// const val = decl_val.toValue();
// The symbol name can be something like `__anon_{d}` with `@intFromEnum(decl_val)`.
// It doesn't have an owner decl because it's just an unnamed constant that might
// be used by more than one function, however, its address is being used so we need
// to put it in some location.
// ...
pub fn lowerAnonDecl(
self: *MachO,
decl_val: InternPool.Index,
explicit_alignment: InternPool.Alignment,
src_loc: Module.SrcLoc,
) !codegen.Result {
const gpa = self.base.allocator;
const mod = self.base.options.module.?;
const ty = mod.intern_pool.typeOf(decl_val).toType();
const gop = try self.anon_decls.getOrPut(gpa, decl_val);
const required_alignment = switch (decl_align) {
const decl_alignment = switch (explicit_alignment) {
.none => ty.abiAlignment(mod),
else => decl_align,
else => explicit_alignment,
};
if (!gop.found_existing or
!required_alignment.check(self.getAtom(gop.value_ptr.*).getSymbol(self).n_value))
{
const val = decl_val.toValue();
const tv = TypedValue{ .ty = ty, .val = val };
const name = try std.fmt.allocPrint(gpa, "__anon_{d}", .{@intFromEnum(decl_val)});
defer gpa.free(name);
const res = self.lowerConst(name, tv, required_alignment, self.data_const_section_index.?, src_loc) catch |err| switch (err) {
else => {
// TODO improve error message
const em = try Module.ErrorMsg.create(gpa, src_loc, "lowerAnonDecl failed with error: {s}", .{
@errorName(err),
});
return .{ .fail = em };
},
};
const atom_index = switch (res) {
.ok => |atom_index| atom_index,
.fail => |em| return .{ .fail = em },
};
gop.value_ptr.* = atom_index;
if (self.anon_decls.get(decl_val)) |atom_index| {
const existing_addr = self.getAtom(atom_index).getSymbol(self).n_value;
if (decl_alignment.check(existing_addr))
return .ok;
}
const val = decl_val.toValue();
const tv = TypedValue{ .ty = ty, .val = val };
var name_buf: [32]u8 = undefined;
const name = std.fmt.bufPrint(&name_buf, "__anon_{d}", .{
@intFromEnum(decl_val),
}) catch unreachable;
const res = self.lowerConst(
name,
tv,
decl_alignment,
self.data_const_section_index.?,
src_loc,
) catch |err| switch (err) {
error.OutOfMemory => return error.OutOfMemory,
else => |e| return .{ .fail = try Module.ErrorMsg.create(
gpa,
src_loc,
"unable to lower constant value: {s}",
.{@errorName(e)},
) },
};
const atom_index = switch (res) {
.ok => |atom_index| atom_index,
.fail => |em| return .{ .fail = em },
};
try self.anon_decls.put(gpa, decl_val, atom_index);
return .ok;
}

View File

@ -1702,27 +1702,34 @@ pub fn getDeclVAddr(
return target_symbol_index;
}
pub fn lowerAnonDecl(wasm: *Wasm, decl_val: InternPool.Index, decl_align: Alignment, src_loc: Module.SrcLoc) !codegen.Result {
pub fn lowerAnonDecl(
wasm: *Wasm,
decl_val: InternPool.Index,
explicit_alignment: Alignment,
src_loc: Module.SrcLoc,
) !codegen.Result {
const gop = try wasm.anon_decls.getOrPut(wasm.base.allocator, decl_val);
if (!gop.found_existing) {
const mod = wasm.base.options.module.?;
const ty = mod.intern_pool.typeOf(decl_val).toType();
const tv: TypedValue = .{ .ty = ty, .val = decl_val.toValue() };
const name = try std.fmt.allocPrintZ(wasm.base.allocator, "__anon_{d}", .{@intFromEnum(decl_val)});
defer wasm.base.allocator.free(name);
var name_buf: [32]u8 = undefined;
const name = std.fmt.bufPrint(&name_buf, "__anon_{d}", .{
@intFromEnum(decl_val),
}) catch unreachable;
switch (try wasm.lowerConst(name, tv, src_loc)) {
.ok => |atom_index| gop.value_ptr.* = atom_index,
.ok => |atom_index| wasm.anon_decls.values()[gop.index] = atom_index,
.fail => |em| return .{ .fail = em },
}
}
const atom = wasm.getAtomPtr(gop.value_ptr.*);
const atom = wasm.getAtomPtr(wasm.anon_decls.values()[gop.index]);
atom.alignment = switch (atom.alignment) {
.none => decl_align,
else => switch (decl_align) {
.none => explicit_alignment,
else => switch (explicit_alignment) {
.none => atom.alignment,
else => atom.alignment.maxStrict(decl_align),
else => atom.alignment.maxStrict(explicit_alignment),
},
};
return .ok;