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:
+25
-33
@@ -778,44 +778,36 @@ 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");
|
||||||
StringBuilder_Append(&cbe.sb, "typedef enum {\n");
|
vi = 0;
|
||||||
vi = 0;
|
while vi < en.variantCount {
|
||||||
while vi < en.variantCount {
|
StringBuilder_Append(&cbe.sb, " ");
|
||||||
StringBuilder_Append(&cbe.sb, " ");
|
StringBuilder_Append(&cbe.sb, en.name);
|
||||||
StringBuilder_Append(&cbe.sb, en.name);
|
StringBuilder_Append(&cbe.sb, "_");
|
||||||
StringBuilder_Append(&cbe.sb, "_");
|
StringBuilder_Append(&cbe.sb, en.variants[vi].name);
|
||||||
StringBuilder_Append(&cbe.sb, en.variants[vi].name);
|
if vi < en.variantCount - 1 {
|
||||||
if vi < en.variantCount - 1 {
|
StringBuilder_Append(&cbe.sb, ",");
|
||||||
StringBuilder_Append(&cbe.sb, ",");
|
|
||||||
}
|
|
||||||
StringBuilder_Append(&cbe.sb, "\n");
|
|
||||||
vi = vi + 1;
|
|
||||||
}
|
}
|
||||||
|
StringBuilder_Append(&cbe.sb, "\n");
|
||||||
|
vi = vi + 1;
|
||||||
|
}
|
||||||
|
StringBuilder_Append(&cbe.sb, "} ");
|
||||||
|
StringBuilder_Append(&cbe.sb, en.name);
|
||||||
|
StringBuilder_Append(&cbe.sb, "_Tag;\n\n");
|
||||||
|
|
||||||
|
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, "} ");
|
||||||
StringBuilder_Append(&cbe.sb, en.name);
|
StringBuilder_Append(&cbe.sb, en.name);
|
||||||
StringBuilder_Append(&cbe.sb, ";\n\n");
|
StringBuilder_Append(&cbe.sb, ";\n\n");
|
||||||
} else {
|
} else {
|
||||||
// Algebraic enum: tag enum + data union + struct
|
// Algebraic enum: data union + struct (tag enum already emitted above)
|
||||||
// 1. Tag enum
|
// 1. Data union
|
||||||
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, "_Tag;\n\n");
|
|
||||||
// 2. 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 {
|
||||||
|
|||||||
Reference in New Issue
Block a user