aboutsummaryrefslogtreecommitdiff
path: root/src/Module.zig
diff options
context:
space:
mode:
authorVeikka Tuominen <git@vexu.eu>2023-01-16 19:46:41 +0200
committerVeikka Tuominen <git@vexu.eu>2023-01-16 19:46:41 +0200
commit342bae02d86d9bd9f2db6ae9489021bab28595ae (patch)
tree8b50d7cffff029c135a17295c4c324603d2358b1 /src/Module.zig
parent31a2b8c3642f1240a70d78203d568051d4dbcd3f (diff)
downloadzig-342bae02d86d9bd9f2db6ae9489021bab28595ae.tar.gz
zig-342bae02d86d9bd9f2db6ae9489021bab28595ae.zip
Sema: automatically optimize order of struct fields
This is a simple starting version of the optimization described in #168 where the fields are just sorted by order of descending alignment.
Diffstat (limited to 'src/Module.zig')
-rw-r--r--src/Module.zig42
1 files changed, 41 insertions, 1 deletions
diff --git a/src/Module.zig b/src/Module.zig
index 558ed498ca..f2f51907cb 100644
--- a/src/Module.zig
+++ b/src/Module.zig
@@ -941,7 +941,8 @@ pub const Struct = struct {
owner_decl: Decl.Index,
/// Index of the struct_decl ZIR instruction.
zir_index: Zir.Inst.Index,
-
+ /// Indexes into `fields` sorted to be most memory efficient.
+ optimized_order: ?[*]u32 = null,
layout: std.builtin.Type.ContainerLayout,
/// If the layout is not packed, this is the noreturn type.
/// If the layout is packed, this is the backing integer type of the packed struct.
@@ -1023,6 +1024,10 @@ pub const Struct = struct {
}
};
+ /// Used in `optimized_order` to indicate field that is not present in the
+ /// runtime version of the struct.
+ pub const omitted_field = std.math.maxInt(u32);
+
pub fn getFullyQualifiedName(s: *Struct, mod: *Module) ![:0]u8 {
return mod.declPtr(s.owner_decl).getFullyQualifiedName(mod);
}
@@ -1098,6 +1103,39 @@ pub const Struct = struct {
}
unreachable; // index out of bounds
}
+
+ pub const RuntimeFieldIterator = struct {
+ struct_obj: *const Struct,
+ index: u32 = 0,
+
+ pub const FieldAndIndex = struct {
+ field: Field,
+ index: u32,
+ };
+
+ pub fn next(it: *RuntimeFieldIterator) ?FieldAndIndex {
+ while (true) {
+ var i = it.index;
+ it.index += 1;
+ if (it.struct_obj.fields.count() <= i)
+ return null;
+
+ if (it.struct_obj.optimized_order) |some| {
+ i = some[i];
+ if (i == Module.Struct.omitted_field) return null;
+ }
+ const field = it.struct_obj.fields.values()[i];
+
+ if (!field.is_comptime and field.ty.hasRuntimeBits()) {
+ return FieldAndIndex{ .index = i, .field = field };
+ }
+ }
+ }
+ };
+
+ pub fn runtimeFieldIterator(s: *const Struct) RuntimeFieldIterator {
+ return .{ .struct_obj = s };
+ }
};
/// Represents the data that an enum declaration provides, when the fields
@@ -6481,6 +6519,7 @@ pub const Feature = enum {
error_return_trace,
is_named_enum_value,
error_set_has_value,
+ field_reordering,
};
pub fn backendSupportsFeature(mod: Module, feature: Feature) bool {
@@ -6493,5 +6532,6 @@ pub fn backendSupportsFeature(mod: Module, feature: Feature) bool {
.error_return_trace => mod.comp.bin_file.options.use_llvm,
.is_named_enum_value => mod.comp.bin_file.options.use_llvm,
.error_set_has_value => mod.comp.bin_file.options.use_llvm,
+ .field_reordering => mod.comp.bin_file.options.use_llvm,
};
}