Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion src/analyze.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1454,7 +1454,9 @@ static bool type_allowed_in_extern(CodeGen *g, TypeTableEntry *type_entry) {
case TypeTableEntryIdFn:
return type_entry->data.fn.fn_type_id.cc == CallingConventionC;
case TypeTableEntryIdPointer:
return type_allowed_in_extern(g, type_entry->data.pointer.child_type);
if (type_size(g, type_entry) == 0)
return false;
return true;
case TypeTableEntryIdStruct:
return type_entry->data.structure.layout == ContainerLayoutExtern || type_entry->data.structure.layout == ContainerLayoutPacked;
case TypeTableEntryIdOptional:
Expand Down
81 changes: 45 additions & 36 deletions src/codegen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7508,51 +7508,60 @@ static void gen_h_file(CodeGen *g) {
case TypeTableEntryIdPromise:
zig_unreachable();
case TypeTableEntryIdEnum:
assert(type_entry->data.enumeration.layout == ContainerLayoutExtern);
fprintf(out_h, "enum %s {\n", buf_ptr(&type_entry->name));
for (uint32_t field_i = 0; field_i < type_entry->data.enumeration.src_field_count; field_i += 1) {
TypeEnumField *enum_field = &type_entry->data.enumeration.fields[field_i];
Buf *value_buf = buf_alloc();
bigint_append_buf(value_buf, &enum_field->value, 10);
fprintf(out_h, " %s = %s", buf_ptr(enum_field->name), buf_ptr(value_buf));
if (field_i != type_entry->data.enumeration.src_field_count - 1) {
fprintf(out_h, ",");
if (type_entry->data.enumeration.layout == ContainerLayoutExtern) {
fprintf(out_h, "enum %s {\n", buf_ptr(&type_entry->name));
for (uint32_t field_i = 0; field_i < type_entry->data.enumeration.src_field_count; field_i += 1) {
TypeEnumField *enum_field = &type_entry->data.enumeration.fields[field_i];
Buf *value_buf = buf_alloc();
bigint_append_buf(value_buf, &enum_field->value, 10);
fprintf(out_h, " %s = %s", buf_ptr(enum_field->name), buf_ptr(value_buf));
if (field_i != type_entry->data.enumeration.src_field_count - 1) {
fprintf(out_h, ",");
}
fprintf(out_h, "\n");
}
fprintf(out_h, "\n");
fprintf(out_h, "};\n\n");
} else {
fprintf(out_h, "enum %s;\n", buf_ptr(&type_entry->name));
}
fprintf(out_h, "};\n\n");
break;
case TypeTableEntryIdStruct:
assert(type_entry->data.structure.layout == ContainerLayoutExtern);
fprintf(out_h, "struct %s {\n", buf_ptr(&type_entry->name));
for (uint32_t field_i = 0; field_i < type_entry->data.structure.src_field_count; field_i += 1) {
TypeStructField *struct_field = &type_entry->data.structure.fields[field_i];

Buf *type_name_buf = buf_alloc();
get_c_type(g, gen_h, struct_field->type_entry, type_name_buf);

if (struct_field->type_entry->id == TypeTableEntryIdArray) {
fprintf(out_h, " %s %s[%" ZIG_PRI_u64 "];\n", buf_ptr(type_name_buf),
buf_ptr(struct_field->name),
struct_field->type_entry->data.array.len);
} else {
fprintf(out_h, " %s %s;\n", buf_ptr(type_name_buf), buf_ptr(struct_field->name));
}
if (type_entry->data.structure.layout == ContainerLayoutExtern) {
fprintf(out_h, "struct %s {\n", buf_ptr(&type_entry->name));
for (uint32_t field_i = 0; field_i < type_entry->data.structure.src_field_count; field_i += 1) {
TypeStructField *struct_field = &type_entry->data.structure.fields[field_i];

Buf *type_name_buf = buf_alloc();
get_c_type(g, gen_h, struct_field->type_entry, type_name_buf);

if (struct_field->type_entry->id == TypeTableEntryIdArray) {
fprintf(out_h, " %s %s[%" ZIG_PRI_u64 "];\n", buf_ptr(type_name_buf),
buf_ptr(struct_field->name),
struct_field->type_entry->data.array.len);
} else {
fprintf(out_h, " %s %s;\n", buf_ptr(type_name_buf), buf_ptr(struct_field->name));
}

}
fprintf(out_h, "};\n\n");
} else {
fprintf(out_h, "struct %s;\n", buf_ptr(&type_entry->name));
}
fprintf(out_h, "};\n\n");
break;
case TypeTableEntryIdUnion:
assert(type_entry->data.unionation.layout == ContainerLayoutExtern);
fprintf(out_h, "union %s {\n", buf_ptr(&type_entry->name));
for (uint32_t field_i = 0; field_i < type_entry->data.unionation.src_field_count; field_i += 1) {
TypeUnionField *union_field = &type_entry->data.unionation.fields[field_i];

Buf *type_name_buf = buf_alloc();
get_c_type(g, gen_h, union_field->type_entry, type_name_buf);
fprintf(out_h, " %s %s;\n", buf_ptr(type_name_buf), buf_ptr(union_field->name));
if (type_entry->data.unionation.layout == ContainerLayoutExtern) {
fprintf(out_h, "union %s {\n", buf_ptr(&type_entry->name));
for (uint32_t field_i = 0; field_i < type_entry->data.unionation.src_field_count; field_i += 1) {
TypeUnionField *union_field = &type_entry->data.unionation.fields[field_i];

Buf *type_name_buf = buf_alloc();
get_c_type(g, gen_h, union_field->type_entry, type_name_buf);
fprintf(out_h, " %s %s;\n", buf_ptr(type_name_buf), buf_ptr(union_field->name));
}
fprintf(out_h, "};\n\n");
} else {
fprintf(out_h, "union %s;\n", buf_ptr(&type_entry->name));
}
fprintf(out_h, "};\n\n");
break;
case TypeTableEntryIdOpaque:
fprintf(out_h, "struct %s;\n\n", buf_ptr(&type_entry->name));
Expand Down
47 changes: 47 additions & 0 deletions test/gen_h.zig
Original file line number Diff line number Diff line change
Expand Up @@ -76,4 +76,51 @@ pub fn addCases(cases: *tests.GenHContext) void {
\\TEST_EXPORT void entry(struct Foo foo, uint8_t bar[]);
\\
);

cases.add("ptr to zig struct",
\\const S = struct {
\\ a: u8,
\\};
\\
\\export fn a(s: *S) u8 {
\\ return s.a;
\\}

,
\\struct S;
\\TEST_EXPORT uint8_t a(struct S * s);
\\
);

cases.add("ptr to zig union",
\\const U = union(enum) {
\\ A: u8,
\\ B: u16,
\\};
\\
\\export fn a(s: *U) u8 {
\\ return s.A;
\\}

,
\\union U;
\\TEST_EXPORT uint8_t a(union U * s);
\\
);

cases.add("ptr to zig enum",
\\const E = enum(u8) {
\\ A,
\\ B,
\\};
\\
\\export fn a(s: *E) u8 {
\\ return @enumToInt(s.*);
\\}

,
\\enum E;
\\TEST_EXPORT uint8_t a(enum E * s);
\\
);
}