Last active
March 19, 2026 03:32
-
-
Save rexim/583aee92d0d1003da8c4a196d753c1bc to your computer and use it in GitHub Desktop.
Patches for Chibicc extentions developed on https://www.youtube.com/watch?v=_dVchhnO_KI
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| From a5648cbc9db69a87f77db5f3a463880d6e8eeb44 Mon Sep 17 00:00:00 2001 | |
| From: rexim <reximkut@gmail.com> | |
| Date: Sun, 15 Mar 2026 21:17:18 +0700 | |
| Subject: [PATCH 1/2] Autoderef for structs and unions | |
| --- | |
| parse.c | 11 +++++++++-- | |
| 1 file changed, 9 insertions(+), 2 deletions(-) | |
| diff --git a/parse.c b/parse.c | |
| index 6acaeb8..c83cf3a 100644 | |
| --- a/parse.c | |
| +++ b/parse.c | |
| @@ -2768,8 +2768,15 @@ static Member *get_struct_member(Type *ty, Token *tok) { | |
| // This function takes care of anonymous structs. | |
| static Node *struct_ref(Node *node, Token *tok) { | |
| add_type(node); | |
| - if (node->ty->kind != TY_STRUCT && node->ty->kind != TY_UNION) | |
| - error_tok(node->tok, "not a struct nor a union"); | |
| + | |
| + if (node->ty->kind == TY_PTR && (node->ty->base->kind == TY_STRUCT || node->ty->base->kind == TY_UNION)) { | |
| + node = new_unary(ND_DEREF, node, tok); | |
| + add_type(node); | |
| + } | |
| + | |
| + if (node->ty->kind != TY_STRUCT && node->ty->kind != TY_UNION) { | |
| + error_tok(node->tok, "not a struct nor a union nor it is a pointer to a struct or a union"); | |
| + } | |
| Type *ty = node->ty; | |
| -- | |
| 2.52.0 | |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| From 7623edb6e02ac2d7c95ac8bf11fb049ff8327372 Mon Sep 17 00:00:00 2001 | |
| From: rexim <reximkut@gmail.com> | |
| Date: Sun, 15 Mar 2026 21:20:04 +0700 | |
| Subject: [PATCH 2/2] Lambda functions | |
| --- | |
| parse.c | 76 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ | |
| tokenize.c | 2 +- | |
| 2 files changed, 77 insertions(+), 1 deletion(-) | |
| diff --git a/parse.c b/parse.c | |
| index c83cf3a..fdd2017 100644 | |
| --- a/parse.c | |
| +++ b/parse.c | |
| @@ -171,6 +171,15 @@ static void leave_scope(void) { | |
| } | |
| // Find a variable by name. | |
| +static VarScope *find_var_cstr(char *name) { | |
| + for (Scope *sc = scope; sc; sc = sc->next) { | |
| + VarScope *sc2 = hashmap_get2(&sc->vars, name, strlen(name)); | |
| + if (sc2) | |
| + return sc2; | |
| + } | |
| + return NULL; | |
| +} | |
| + | |
| static VarScope *find_var(Token *tok) { | |
| for (Scope *sc = scope; sc; sc = sc->next) { | |
| VarScope *sc2 = hashmap_get2(&sc->vars, tok->loc, tok->len); | |
| @@ -2975,6 +2984,9 @@ static Node *generic_selection(Token **rest, Token *tok) { | |
| return ret; | |
| } | |
| +static void create_param_lvars(Type *param); | |
| +static void resolve_goto_labels(void); | |
| + | |
| // primary = "(" "{" stmt+ "}" ")" | |
| // | "(" expr ")" | |
| // | "sizeof" "(" type-name ")" | |
| @@ -3020,6 +3032,70 @@ static Node *primary(Token **rest, Token *tok) { | |
| return new_ulong(ty->size, start); | |
| } | |
| + if (equal(tok, "lambda")) { | |
| + tok = tok->next; | |
| + Type *return_ty = declspec(&tok, tok, NULL); | |
| + tok = skip(tok, "("); | |
| + Type *ty = func_params(&tok, tok, return_ty); | |
| + | |
| + static size_t lambda_count = 0; | |
| + | |
| + size_t name_len = snprintf(NULL, 0, "lambda.%zu", lambda_count) + 1; | |
| + char *name = malloc(name_len); | |
| + snprintf(name, name_len, "lambda.%zu", lambda_count); | |
| + lambda_count += 1; | |
| + | |
| + Obj *fn = new_gvar(name, ty); | |
| + fn->is_function = true; | |
| + fn->is_definition = true; | |
| + fn->is_static = true; | |
| + fn->is_root = true; | |
| + | |
| + Obj *saved_fn = current_fn; | |
| + Obj *saved_locals = locals; | |
| + current_fn = fn; | |
| + locals = NULL; | |
| + enter_scope(); | |
| + create_param_lvars(ty->params); | |
| + | |
| + // A buffer for a struct/union return value is passed | |
| + // as the hidden first parameter. | |
| + Type *rty = ty->return_ty; | |
| + if ((rty->kind == TY_STRUCT || rty->kind == TY_UNION) && rty->size > 16) | |
| + new_lvar("", pointer_to(rty)); | |
| + | |
| + fn->params = locals; | |
| + | |
| + if (ty->is_variadic) | |
| + fn->va_area = new_lvar("__va_area__", array_of(ty_char, 136)); | |
| + fn->alloca_bottom = new_lvar("__alloca_size__", pointer_to(ty_char)); | |
| + | |
| + tok = skip(tok, "{"); | |
| + | |
| + // [https://www.sigbus.info/n1570#6.4.2.2p1] "__func__" is | |
| + // automatically defined as a local variable containing the | |
| + // current function name. | |
| + push_scope("__func__")->var = | |
| + new_string_literal(fn->name, array_of(ty_char, strlen(fn->name) + 1)); | |
| + | |
| + // [GNU] __FUNCTION__ is yet another name of __func__. | |
| + push_scope("__FUNCTION__")->var = | |
| + new_string_literal(fn->name, array_of(ty_char, strlen(fn->name) + 1)); | |
| + | |
| + fn->body = compound_stmt(&tok, tok); | |
| + fn->locals = locals; | |
| + leave_scope(); | |
| + resolve_goto_labels(); | |
| + | |
| + current_fn = saved_fn; | |
| + locals = saved_locals; | |
| + | |
| + *rest = tok; | |
| + | |
| + VarScope *sc = find_var_cstr(name); | |
| + return new_unary(ND_ADDR, new_var_node(sc->var, tok), tok); | |
| + } | |
| + | |
| if (equal(tok, "sizeof")) { | |
| Node *node = unary(rest, tok->next); | |
| add_type(node); | |
| diff --git a/tokenize.c b/tokenize.c | |
| index 5c49c02..2744c19 100644 | |
| --- a/tokenize.c | |
| +++ b/tokenize.c | |
| @@ -160,7 +160,7 @@ static bool is_keyword(Token *tok) { | |
| if (map.capacity == 0) { | |
| static char *kw[] = { | |
| - "return", "if", "else", "for", "while", "int", "sizeof", "char", | |
| + "return", "if", "else", "for", "while", "int", "sizeof", "char", "lambda", | |
| "struct", "union", "short", "long", "void", "typedef", "_Bool", | |
| "enum", "static", "goto", "break", "continue", "switch", "case", | |
| "default", "extern", "_Alignof", "_Alignas", "do", "signed", | |
| -- | |
| 2.52.0 | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment