diff options
| author | Andrew Kelley <andrew@ziglang.org> | 2022-02-17 20:47:51 -0700 |
|---|---|---|
| committer | Andrew Kelley <andrew@ziglang.org> | 2022-02-17 20:48:09 -0700 |
| commit | 9ea253b9c4085b9f577c4d7634da69b2d40d6cce (patch) | |
| tree | 9c3b50e9ff50432b6d7b465e5e43803f4cc3c296 /src | |
| parent | 23567cdd984322c7428d43c8cbf8ecd40a2b7ec6 (diff) | |
| download | zig-9ea253b9c4085b9f577c4d7634da69b2d40d6cce.tar.gz zig-9ea253b9c4085b9f577c4d7634da69b2d40d6cce.zip | |
Sema: implement type info for structs
Diffstat (limited to 'src')
| -rw-r--r-- | src/Sema.zig | 105 |
1 files changed, 102 insertions, 3 deletions
diff --git a/src/Sema.zig b/src/Sema.zig index f939ebc912..a153be5119 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -9958,7 +9958,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai // layout: ContainerLayout, try Value.Tag.enum_field_index.create( sema.arena, - @enumToInt(std.builtin.TypeInfo.ContainerLayout.Auto), + @enumToInt(union_ty.containerLayout()), ), // tag_type: ?type, @@ -9977,13 +9977,112 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai }), ); }, - .Struct => return sema.fail(block, src, "TODO: implement zirTypeInfo for Struct", .{}), - .Opaque => { + .Struct => { // TODO: look into memoizing this result. var fields_anon_decl = try block.startAnonDecl(src); defer fields_anon_decl.deinit(); + const struct_field_ty = t: { + const struct_field_ty_decl = (try sema.namespaceLookup( + block, + src, + type_info_ty.getNamespace().?, + "StructField", + )).?; + try sema.mod.declareDeclDependency(sema.owner_decl, struct_field_ty_decl); + try sema.ensureDeclAnalyzed(struct_field_ty_decl); + var buffer: Value.ToTypeBuffer = undefined; + break :t try struct_field_ty_decl.val.toType(&buffer).copy(fields_anon_decl.arena()); + }; + + const struct_ty = try sema.resolveTypeFields(block, src, ty); + const struct_fields = struct_ty.structFields(); + const struct_field_vals = try fields_anon_decl.arena().alloc(Value, struct_fields.count()); + const layout = struct_ty.containerLayout(); + + for (struct_field_vals) |*field_val, i| { + const field = struct_fields.values()[i]; + const name = struct_fields.keys()[i]; + const name_val = v: { + var anon_decl = try block.startAnonDecl(src); + defer anon_decl.deinit(); + const bytes = try anon_decl.arena().dupeZ(u8, name); + const new_decl = try anon_decl.finish( + try Type.Tag.array_u8_sentinel_0.create(anon_decl.arena(), bytes.len), + try Value.Tag.bytes.create(anon_decl.arena(), bytes[0 .. bytes.len + 1]), + ); + break :v try Value.Tag.decl_ref.create(fields_anon_decl.arena(), new_decl); + }; + + const struct_field_fields = try fields_anon_decl.arena().create([5]Value); + const opt_default_val = if (field.default_val.tag() == .unreachable_value) + null + else + field.default_val; + const default_val_ptr = try sema.optRefValue(block, src, field.ty, opt_default_val); + const alignment = switch (layout) { + .Auto, .Extern => field.normalAlignment(target), + .Packed => field.packedAlignment(), + }; + + struct_field_fields.* = .{ + // name: []const u8, + name_val, + // field_type: type, + try Value.Tag.ty.create(fields_anon_decl.arena(), field.ty), + // default_value: ?*const anyopaque, + try default_val_ptr.copy(fields_anon_decl.arena()), + // is_comptime: bool, + Value.makeBool(field.is_comptime), + // alignment: comptime_int, + try Value.Tag.int_u64.create(fields_anon_decl.arena(), alignment), + }; + field_val.* = try Value.Tag.@"struct".create(fields_anon_decl.arena(), struct_field_fields); + } + + const fields_val = v: { + const new_decl = try fields_anon_decl.finish( + try Type.Tag.array.create(fields_anon_decl.arena(), .{ + .len = struct_field_vals.len, + .elem_type = struct_field_ty, + }), + try Value.Tag.array.create( + fields_anon_decl.arena(), + try fields_anon_decl.arena().dupe(Value, struct_field_vals), + ), + ); + break :v try Value.Tag.decl_ref.create(sema.arena, new_decl); + }; + + const decls_val = try sema.typeInfoDecls(block, src, type_info_ty, struct_ty.getNamespace()); + + const field_values = try sema.arena.create([4]Value); + field_values.* = .{ + // layout: ContainerLayout, + try Value.Tag.enum_field_index.create( + sema.arena, + @enumToInt(layout), + ), + // fields: []const StructField, + fields_val, + // decls: []const Declaration, + decls_val, + // is_tuple: bool, + Value.makeBool(struct_ty.isTuple()), + }; + + return sema.addConstant( + type_info_ty, + try Value.Tag.@"union".create(sema.arena, .{ + .tag = try Value.Tag.enum_field_index.create(sema.arena, @enumToInt(std.builtin.TypeId.Struct)), + .val = try Value.Tag.@"struct".create(sema.arena, field_values), + }), + ); + }, + .Opaque => { + // TODO: look into memoizing this result. + const opaque_ty = try sema.resolveTypeFields(block, src, ty); const decls_val = try sema.typeInfoDecls(block, src, type_info_ty, opaque_ty.getNamespace()); |
