Skip to content

Commit

Permalink
Allow pointers to anything in extern/exported declarations (#1258)
Browse files Browse the repository at this point in the history
* type_allowed_in_extern accepts all ptr not size 0

* Generate correct headers for none extern structs/unions/enums
  • Loading branch information
Hejsil authored and andrewrk committed Jul 18, 2018
1 parent c393a39 commit fd3a41d
Show file tree
Hide file tree
Showing 3 changed files with 95 additions and 37 deletions.
4 changes: 3 additions & 1 deletion src/analyze.cpp
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
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
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);
\\
);
}

0 comments on commit fd3a41d

Please sign in to comment.