summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--README.md7
-rw-r--r--README_ES.md7
-rw-r--r--README_IT.md7
-rw-r--r--README_ZH_CN.md7
-rw-r--r--README_ZH_TW.md7
-rw-r--r--src/codegen/codegen.c55
-rw-r--r--src/codegen/codegen_utils.c60
-rw-r--r--src/parser/parser_stmt.c35
-rw-r--r--tests/features/test_asm_clobber.zc20
9 files changed, 163 insertions, 42 deletions
diff --git a/README.md b/README.md
index 2f0832f..87f95af 100644
--- a/README.md
+++ b/README.md
@@ -997,12 +997,13 @@ Zen C simplifies the complex GCC constraint syntax with named bindings.
// Syntax: : out(variable) : in(variable) : clobber(reg)
// Uses {variable} placeholder syntax for readability
-fn add(a: int, b: int) -> int {
+fn add_five(x: int) -> int {
let result: int;
asm {
- "add {result}, {a}, {b}"
+ "mov {x}, {result}"
+ "add $5, {result}"
: out(result)
- : in(a), in(b)
+ : in(x)
: clobber("cc")
}
return result;
diff --git a/README_ES.md b/README_ES.md
index 2feb762..11c4d89 100644
--- a/README_ES.md
+++ b/README_ES.md
@@ -997,12 +997,13 @@ Zen C simplifica la compleja sintaxis de restricciones de GCC con vinculaciones
// Sintaxis: : out(variable) : in(variable) : clobber(reg)
// Usa la sintaxis de marcador de posición {variable} para legibilidad
-fn sumar(a: int, b: int) -> int {
+fn sumar(x: int) -> int {
let resultado: int;
asm {
- "add {resultado}, {a}, {b}"
+ "mov {x}, {resultado}"
+ "add $5, {resultado}"
: out(resultado)
- : in(a), in(b)
+ : in(x)
: clobber("cc")
}
return resultado;
diff --git a/README_IT.md b/README_IT.md
index ba49e46..9bf804e 100644
--- a/README_IT.md
+++ b/README_IT.md
@@ -993,12 +993,13 @@ Zen C semplifica la sintassi complessa dei vincoli di GCC con dei binding nomina
// Sintassi: : out(variable) : in(variable) : clobber(reg)
// Usa una sintassi placeholder (`{variabile}`) per la leggibilità
-fn somma(a: int, b: int) -> int {
+fn aggiungi_cinque(x: int) -> int {
let risultato: int;
asm {
- "add {risultato}, {a}, {b}"
+ "mov {x}, {risultato}"
+ "add $5, {risultato}"
: out(risultato)
- : in(a), in(b)
+ : in(x)
: clobber("cc")
}
return risultato;
diff --git a/README_ZH_CN.md b/README_ZH_CN.md
index 796eb66..aa1130b 100644
--- a/README_ZH_CN.md
+++ b/README_ZH_CN.md
@@ -996,12 +996,13 @@ Zen C 通过命名绑定简化了复杂的 GCC 约束语法。
// 语法: : out(变量) : in(变量) : clobber(寄存器)
// 使用 {变量} 占位符语法以提高可读性
-fn add(a: int, b: int) -> int {
+fn add_five(x: int) -> int {
let result: int;
asm {
- "add {result}, {a}, {b}"
+ "mov {x}, {result}"
+ "add $5, {result}"
: out(result)
- : in(a), in(b)
+ : in(x)
: clobber("cc")
}
return result;
diff --git a/README_ZH_TW.md b/README_ZH_TW.md
index 5b4d484..5d85a76 100644
--- a/README_ZH_TW.md
+++ b/README_ZH_TW.md
@@ -996,12 +996,13 @@ Zen C 通過命名綁定簡化了複雜的 GCC 約束語法。
// 語法: : out(變量) : in(變量) : clobber(寄存器)
// 使用 {變量} 佔位符語法以提高可讀性
-fn add(a: int, b: int) -> int {
+fn add_five(x: int) -> int {
let result: int;
asm {
- "add {result}, {a}, {b}"
+ "mov {x}, {result}"
+ "add $5, {result}"
: out(result)
- : in(a), in(b)
+ : in(x)
: clobber("cc")
}
return result;
diff --git a/src/codegen/codegen.c b/src/codegen/codegen.c
index 37415c2..0496a46 100644
--- a/src/codegen/codegen.c
+++ b/src/codegen/codegen.c
@@ -225,8 +225,9 @@ void codegen_expression(ParserContext *ctx, ASTNode *node, FILE *out)
int is_basic = IS_BASIC_TYPE(t1);
ASTNode *def = t1 ? find_struct_def(ctx, t1) : NULL;
-
- if (t1 && def && (def->type == NODE_STRUCT || def->type == NODE_ENUM) && !is_basic && !is_ptr)
+
+ if (t1 && def && (def->type == NODE_STRUCT || def->type == NODE_ENUM) && !is_basic &&
+ !is_ptr)
{
char *base = t1;
if (strncmp(base, "struct ", 7) == 0)
@@ -335,7 +336,10 @@ void codegen_expression(ParserContext *ctx, ASTNode *node, FILE *out)
codegen_expression(ctx, node->binary.right, out);
fprintf(out, ")");
}
- if (t1) free(t1);
+ if (t1)
+ {
+ free(t1);
+ }
}
else
{
@@ -413,7 +417,8 @@ void codegen_expression(ParserContext *ctx, ASTNode *node, FILE *out)
fprintf(out, ", ");
}
- Type *param_t = (arg_idx < sig->total_args) ? sig->arg_types[arg_idx] : NULL;
+ Type *param_t =
+ (arg_idx < sig->total_args) ? sig->arg_types[arg_idx] : NULL;
if (param_t && param_t->kind == TYPE_STRUCT &&
strncmp(param_t->name, "Tuple_", 6) == 0 && sig->total_args == 1 &&
@@ -528,13 +533,13 @@ void codegen_expression(ParserContext *ctx, ASTNode *node, FILE *out)
{
char trait_mangled[256];
snprintf(trait_mangled, sizeof(trait_mangled), "%s__%s_%s", base,
- ref->node->impl_trait.trait_name, method);
+ ref->node->impl_trait.trait_name, method);
if (find_func(ctx, trait_mangled))
{
- size_t suffix_len = strlen(ref->node->impl_trait.trait_name) +
- strlen(method) + 2;
+ size_t suffix_len = strlen(ref->node->impl_trait.trait_name) +
+ strlen(method) + 2;
char *suffix = xmalloc(suffix_len);
- snprintf(suffix, suffix_len, "%s_%s",
+ snprintf(suffix, suffix_len, "%s_%s",
ref->node->impl_trait.trait_name, method);
resolved_method_suffix = suffix;
break;
@@ -553,8 +558,8 @@ void codegen_expression(ParserContext *ctx, ASTNode *node, FILE *out)
{
tname = it->impl_node->impl_trait.trait_name;
char trait_mangled[512];
- snprintf(trait_mangled, sizeof(trait_mangled),
- "%s__%s_%s", base, tname, method);
+ snprintf(trait_mangled, sizeof(trait_mangled), "%s__%s_%s",
+ base, tname, method);
if (find_func(ctx, trait_mangled))
{
size_t suffix_len = strlen(tname) + strlen(method) + 2;
@@ -580,7 +585,7 @@ void codegen_expression(ParserContext *ctx, ASTNode *node, FILE *out)
for (int k = 0; k < def->strct.used_struct_count; k++)
{
char mixin_check[128];
- snprintf(mixin_check, sizeof(mixin_check), "%s__%s",
+ snprintf(mixin_check, sizeof(mixin_check), "%s__%s",
def->strct.used_structs[k], method);
if (find_func(ctx, mixin_check))
{
@@ -611,7 +616,7 @@ void codegen_expression(ParserContext *ctx, ASTNode *node, FILE *out)
arg = arg->next;
}
fprintf(out, ")");
-
+
if (resolved_method_suffix)
{
free(resolved_method_suffix);
@@ -621,9 +626,12 @@ void codegen_expression(ParserContext *ctx, ASTNode *node, FILE *out)
free(type);
return;
}
- if (type) free(type);
+ if (type)
+ {
+ free(type);
+ }
}
-
+
if (node->call.callee->type == NODE_EXPR_VAR)
{
ASTNode *def = find_struct_def(ctx, node->call.callee->var_ref.name);
@@ -807,8 +815,11 @@ void codegen_expression(ParserContext *ctx, ASTNode *node, FILE *out)
{
actually_ptr = 1;
}
- if (lt) free(lt);
-
+ if (lt)
+ {
+ free(lt);
+ }
+
char *field = node->member.field;
if (field && field[0] >= '0' && field[0] <= '9')
{
@@ -831,7 +842,7 @@ void codegen_expression(ParserContext *ctx, ASTNode *node, FILE *out)
is_slice_struct = 1;
}
}
-
+
if (!is_slice_struct && node->index.array->resolved_type)
{
if (strncmp(node->index.array->resolved_type, "Slice_", 6) == 0)
@@ -847,7 +858,10 @@ void codegen_expression(ParserContext *ctx, ASTNode *node, FILE *out)
{
is_slice_struct = 1;
}
- if (inferred) free(inferred);
+ if (inferred)
+ {
+ free(inferred);
+ }
}
if (is_slice_struct)
@@ -962,7 +976,10 @@ void codegen_expression(ParserContext *ctx, ASTNode *node, FILE *out)
fprintf(out, "(Slice_%s){ .data = _arr + _start, .len = _len, .cap = _len }; })",
tname);
}
- if (tname && strcmp(tname, "unknown") != 0) free(tname);
+ if (tname && strcmp(tname, "unknown") != 0)
+ {
+ free(tname);
+ }
break;
}
case NODE_BLOCK:
diff --git a/src/codegen/codegen_utils.c b/src/codegen/codegen_utils.c
index 08707cc..92c5395 100644
--- a/src/codegen/codegen_utils.c
+++ b/src/codegen/codegen_utils.c
@@ -193,6 +193,7 @@ char *infer_type(ParserContext *ctx, ASTNode *node)
{
return NULL;
}
+
if (node->resolved_type && strcmp(node->resolved_type, "unknown") != 0 &&
strcmp(node->resolved_type, "void*") != 0)
{
@@ -326,6 +327,65 @@ char *infer_type(ParserContext *ctx, ASTNode *node)
return extracted;
}
}
+
+ // Find the struct/enum definition and look for "Ok" or "val"
+ char *search_name = inner_type;
+ if (strncmp(search_name, "struct ", 7) == 0)
+ {
+ search_name += 7;
+ }
+
+ ASTNode *def = find_struct_def_codegen(ctx, search_name);
+ if (!def)
+ {
+ // check enums list explicitly if not found in instantiated list
+ StructRef *er = ctx->parsed_enums_list;
+ while (er)
+ {
+ if (er->node && er->node->type == NODE_ENUM &&
+ strcmp(er->node->enm.name, search_name) == 0)
+ {
+ def = er->node;
+ break;
+ }
+ er = er->next;
+ }
+ }
+
+ if (def)
+ {
+ if (def->type == NODE_ENUM)
+ {
+ // Look for "Ok" variant
+ ASTNode *var = def->enm.variants;
+ while (var)
+ {
+ if (var->variant.name && strcmp(var->variant.name, "Ok") == 0)
+ {
+ if (var->variant.payload)
+ {
+ return codegen_type_to_string(var->variant.payload);
+ }
+ // Ok with no payload? Then it's void/u0.
+ return "void";
+ }
+ var = var->next;
+ }
+ }
+ else if (def->type == NODE_STRUCT)
+ {
+ // Look for "val" field
+ ASTNode *field = def->strct.fields;
+ while (field)
+ {
+ if (field->field.name && strcmp(field->field.name, "val") == 0)
+ {
+ return xstrdup(field->field.type);
+ }
+ field = field->next;
+ }
+ }
+ }
}
}
diff --git a/src/parser/parser_stmt.c b/src/parser/parser_stmt.c
index 0677cf5..ae16243 100644
--- a/src/parser/parser_stmt.c
+++ b/src/parser/parser_stmt.c
@@ -842,7 +842,7 @@ ASTNode *parse_asm(ParserContext *ctx, Lexer *l)
}
}
- // Parse clobbers (: "eax", "memory")
+ // Parse clobbers (: "eax", "memory" OR : clobber("eax"), clobber("memory"))
char **clobbers = NULL;
int num_clobbers = 0;
@@ -865,17 +865,36 @@ ASTNode *parse_asm(ParserContext *ctx, Lexer *l)
continue;
}
- if (t.type == TOK_STRING)
+ // check for clobber("...")
+ if (t.type == TOK_IDENT && strncmp(t.start, "clobber", 7) == 0)
{
- lexer_next(l);
- // Extract string content
- char *clob = xmalloc(t.len);
- strncpy(clob, t.start + 1, t.len - 2);
- clob[t.len - 2] = 0;
- clobbers[num_clobbers++] = clob;
+ lexer_next(l); // eat clobber
+ if (lexer_peek(l).type != TOK_LPAREN)
+ {
+ zpanic_at(lexer_peek(l), "Expected ( after clobber");
+ }
+ lexer_next(l); // eat (
+
+ Token clob = lexer_next(l);
+ if (clob.type != TOK_STRING)
+ {
+ zpanic_at(clob, "Expected string literal for clobber");
+ }
+
+ if (lexer_peek(l).type != TOK_RPAREN)
+ {
+ zpanic_at(lexer_peek(l), "Expected ) after clobber string");
+ }
+ lexer_next(l); // eat )
+
+ char *c = xmalloc(clob.len);
+ strncpy(c, clob.start + 1, clob.len - 2);
+ c[clob.len - 2] = 0;
+ clobbers[num_clobbers++] = c;
}
else
{
+ zpanic_at(t, "Expected 'clobber(\"...\")' in clobber list");
break;
}
}
diff --git a/tests/features/test_asm_clobber.zc b/tests/features/test_asm_clobber.zc
new file mode 100644
index 0000000..2ba74da
--- /dev/null
+++ b/tests/features/test_asm_clobber.zc
@@ -0,0 +1,20 @@
+fn add(a: int, b: int) -> int {
+ let result: int;
+ asm {
+ "mov {a}, {result}"
+ "add {b}, {result}"
+ : out(result)
+ : in(a), in(b)
+ : clobber("cc")
+ }
+ return result;
+}
+
+test "asm_clobber" {
+ let res = add(10, 20);
+ if (res != 30) {
+ println "Failed: Expected 30, got {res}";
+ exit(1);
+ }
+ println "Success: asm with clobber works properly";
+}