fix(selfhost/c_backend): emit _Tag + struct wrapper for all enums

Simple enums were emitted as plain C enums, but the rest of the codegen
(and source code) expected them to have a .tag field like algebraic enums.
This caused C compilation errors:
- 'request for member tag in something not a structure or union'
- 'field name not in record or union initializer'

Fix: always emit the _Tag typedef + struct wrapper for every enum.
For simple enums, the struct only contains the tag (no _Data union).
For algebraic enums, keep the existing _Data union + struct behavior.

This matches the bootstrap compiler's enum codegen.
This commit is contained in:
2026-06-08 20:00:58 +03:00
parent 2cb971a483
commit d253a01aa9
+14 -22
View File
@@ -778,27 +778,7 @@ func CBackend_Generate(mod: *HirModule) -> String {
} }
vi = vi + 1; vi = vi + 1;
} }
if !hasData { // Emit tag enum for all enums (simple and algebraic)
// Simple enum: typedef enum { A, B } Name;
StringBuilder_Append(&cbe.sb, "typedef enum {\n");
vi = 0;
while vi < en.variantCount {
StringBuilder_Append(&cbe.sb, " ");
StringBuilder_Append(&cbe.sb, en.name);
StringBuilder_Append(&cbe.sb, "_");
StringBuilder_Append(&cbe.sb, en.variants[vi].name);
if vi < en.variantCount - 1 {
StringBuilder_Append(&cbe.sb, ",");
}
StringBuilder_Append(&cbe.sb, "\n");
vi = vi + 1;
}
StringBuilder_Append(&cbe.sb, "} ");
StringBuilder_Append(&cbe.sb, en.name);
StringBuilder_Append(&cbe.sb, ";\n\n");
} else {
// Algebraic enum: tag enum + data union + struct
// 1. Tag enum
StringBuilder_Append(&cbe.sb, "typedef enum {\n"); StringBuilder_Append(&cbe.sb, "typedef enum {\n");
vi = 0; vi = 0;
while vi < en.variantCount { while vi < en.variantCount {
@@ -815,7 +795,19 @@ func CBackend_Generate(mod: *HirModule) -> String {
StringBuilder_Append(&cbe.sb, "} "); StringBuilder_Append(&cbe.sb, "} ");
StringBuilder_Append(&cbe.sb, en.name); StringBuilder_Append(&cbe.sb, en.name);
StringBuilder_Append(&cbe.sb, "_Tag;\n\n"); StringBuilder_Append(&cbe.sb, "_Tag;\n\n");
// 2. Data union
if !hasData {
// Simple enum: struct wrapper with only tag
StringBuilder_Append(&cbe.sb, "typedef struct {\n");
StringBuilder_Append(&cbe.sb, " ");
StringBuilder_Append(&cbe.sb, en.name);
StringBuilder_Append(&cbe.sb, "_Tag tag;\n");
StringBuilder_Append(&cbe.sb, "} ");
StringBuilder_Append(&cbe.sb, en.name);
StringBuilder_Append(&cbe.sb, ";\n\n");
} else {
// Algebraic enum: data union + struct (tag enum already emitted above)
// 1. Data union
StringBuilder_Append(&cbe.sb, "typedef union {\n"); StringBuilder_Append(&cbe.sb, "typedef union {\n");
vi = 0; vi = 0;
while vi < en.variantCount { while vi < en.variantCount {