authorgravatar for mlugg@mlugg.co.ukMatthew Lugg <mlugg@mlugg.co.uk> 2023-03-07 22:24:50+00:00
committergravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2023-03-12 19:07:06+02:00
loga8bd55e0853f7f80c9cd843ec54813425e4276bc
tree43c45d380722b2f9b32a650d0b4e30a8d1788ff3
parentc93e0d86187cb589d6726acd36f741f3d87a96be

translate-c: translate extern unknown-length arrays using @extern

Resolves: #14743

3 files changed, 51 insertions(+), 1 deletions(-)

src/translate_c.zig+15-1
......@@ -784,9 +784,9 @@ fn visitVarDecl(c: *Context, var_decl: *const clang.VarDecl, mangled_name: ?[]co
784784
785785 const qual_type = var_decl.getTypeSourceInfo_getType();
786786 const storage_class = var_decl.getStorageClass();
787 const is_const = qual_type.isConstQualified();
788787 const has_init = var_decl.hasInit();
789788 const decl_init = var_decl.getInit();
789 var is_const = qual_type.isConstQualified();
790790
791791 // In C extern variables with initializers behave like Zig exports.
792792 // extern int foo = 2;
......@@ -843,6 +843,20 @@ fn visitVarDecl(c: *Context, var_decl: *const clang.VarDecl, mangled_name: ?[]co
843843
844844 // std.mem.zeroes(T)
845845 init_node = try Tag.std_mem_zeroes.create(c.arena, type_node);
846 } else if (qual_type.getTypeClass() == .IncompleteArray) {
847 // Oh no, an extern array of unknown size! These are really fun because there's no
848 // direct equivalent in Zig. To translate correctly, we'll have to create a C-pointer
849 // to the data initialized via @extern.
850
851 const name_str = try std.fmt.allocPrint(c.arena, "\"{s}\"", .{var_name});
852 init_node = try Tag.builtin_extern.create(c.arena, .{
853 .type = type_node,
854 .name = try Tag.string_literal.create(c.arena, name_str),
855 });
856
857 // Since this is really a pointer to the underlying data, we tweak a few properties.
858 is_extern = false;
859 is_const = true;
846860 }
847861
848862 const linksection_string = blk: {
src/translate_c/ast.zig+28
......@@ -158,6 +158,8 @@ pub const Node = extern union {
158158 vector_zero_init,
159159 /// @shuffle(type, a, b, mask)
160160 shuffle,
161 /// @extern(ty, .{ .name = n })
162 builtin_extern,
161163
162164 /// @import("std").zig.c_translation.MacroArithmetic.<op>(lhs, rhs)
163165 macro_arithmetic,
......@@ -373,6 +375,7 @@ pub const Node = extern union {
373375 .field_access => Payload.FieldAccess,
374376 .string_slice => Payload.StringSlice,
375377 .shuffle => Payload.Shuffle,
378 .builtin_extern => Payload.Extern,
376379 .macro_arithmetic => Payload.MacroArithmetic,
377380 };
378381 }
......@@ -718,6 +721,14 @@ pub const Payload = struct {
718721 },
719722 };
720723
724 pub const Extern = struct {
725 base: Payload,
726 data: struct {
727 type: Node,
728 name: Node,
729 },
730 };
731
721732 pub const MacroArithmetic = struct {
722733 base: Payload,
723734 data: struct {
......@@ -1409,6 +1420,22 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex {
14091420 payload.mask_vector,
14101421 });
14111422 },
1423 .builtin_extern => {
1424 const payload = node.castTag(.builtin_extern).?.data;
1425
1426 var info_inits: [1]Payload.ContainerInitDot.Initializer = .{
1427 .{ .name = "name", .value = payload.name },
1428 };
1429 var info_payload: Payload.ContainerInitDot = .{
1430 .base = .{ .tag = .container_init_dot },
1431 .data = &info_inits,
1432 };
1433
1434 return renderBuiltinCall(c, "@extern", &.{
1435 payload.type,
1436 .{ .ptr_otherwise = &info_payload.base },
1437 });
1438 },
14121439 .macro_arithmetic => {
14131440 const payload = node.castTag(.macro_arithmetic).?.data;
14141441 const op = @tagName(payload.op);
......@@ -2348,6 +2375,7 @@ fn renderNodeGrouped(c: *Context, node: Node) !NodeIndex {
23482375 .div_exact,
23492376 .offset_of,
23502377 .shuffle,
2378 .builtin_extern,
23512379 .static_local_var,
23522380 .mut_str,
23532381 .macro_arithmetic,
test/translate_c.zig+8
......@@ -3948,4 +3948,12 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
39483948 \\}
39493949 });
39503950 }
3951
3952 cases.add("extern array of unknown length",
3953 \\extern int foo[];
3954 , &[_][]const u8{
3955 \\const foo: [*c]c_int = @extern([*c]c_int, .{
3956 \\ .name = "foo",
3957 \\});
3958 });
39513959}