diff options
author | Matthew Sotoudeh <matthew@masot.net> | 2023-07-30 18:18:25 -0700 |
---|---|---|
committer | Matthew Sotoudeh <matthew@masot.net> | 2023-07-30 18:18:25 -0700 |
commit | 44662c62f444fc50fe523d987199f6a10c9a693c (patch) | |
tree | b52a68243ef283471c53d224fd3f0ae87f8c0d0f | |
parent | f2297c20b69d942fd1e8fdcdd8f4d142c71de662 (diff) |
add support for passing through sizeof & alignofs
-rw-r--r-- | README.txt | 26 | ||||
-rw-r--r-- | chibicc.h | 5 | ||||
-rw-r--r-- | codegen.c | 8 | ||||
-rw-r--r-- | main.c | 5 | ||||
-rw-r--r-- | parse.c | 16 | ||||
-rw-r--r-- | tests/keeping_sizeof.c | 4 |
6 files changed, 51 insertions, 13 deletions
@@ -42,14 +42,24 @@ Selling points: Known to be unsupported: -- dietC is ... optimistic about identifier conflicts with its generated - labels. It likely will not work if you run it on its own output. This is very - fixable, will do soon. -- chibicc does not have good support for long double; specifically, long - doubles cannot be used in constant expressions. This is fixable, but requires - non-trivial modifications to the chibicc side of the code. -- chibicc does not parse const, volatile, etc. type qualifiers. it would not be - too hard to support this if desired. + - dietC is ... optimistic about identifier conflicts with its generated + labels. It likely will not work if you run it on its own output. This is + very fixable, will do soon. + - chibicc does not have good support for long double; specifically, long + doubles cannot be used in constant expressions. This is fixable, but + requires non-trivial modifications to the chibicc side of the code. + - chibicc does not parse const, volatile, etc. type qualifiers. it would not + be too hard to support this if desired. + +Options: + + - Passing "--line-numbers" enables (very WIP) support for outputting #line + directives. The dietcc wrapper will attempt to automatically strip those + before calling passes & then re-insert them, so that it all happens + "automagically." Of course, it doesn't really. You'll probably find that it + has roughly the right file, but totally wrong line. + - Passing "--type-builtins" will output "sizeof(Type_%d)" and + "alignof(Type_%d)" instead of pre-computing these operations. Why not cilly? @@ -281,6 +281,10 @@ struct Node { // Numeric literal int64_t val; long double fval; + + // sizeof(...) or alignof(...) + Type *is_sizeof; + Type *is_alignof; }; Node *new_cast(Node *expr, Type *ty); @@ -465,6 +469,7 @@ void hashmap_test(void); extern bool opt_fpic; extern bool opt_fcommon; extern bool opt_line_numbers; +extern bool opt_type_builtins; extern char *base_file; // @@ -311,6 +311,14 @@ static void gen_addr(Node *node, int to_tmp) { // Generate code for a given node. static void gen_expr(Node *node, int to_tmp) { emit_line(node->tok); + if (opt_type_builtins && (node->is_sizeof || node->is_alignof)) { + decltmp(node->ty, to_tmp); + if (node->is_sizeof) printnoln("\tt%d = sizeof ( ", to_tmp); + else printnoln("\tt%d = alignof ( ", to_tmp); + print_type(node->is_sizeof); + println(" ) ;"); + return; + } switch (node->kind) { case ND_NULL_EXPR: return; @@ -10,6 +10,7 @@ StringArray include_paths; bool opt_fcommon = false; bool opt_fpic; bool opt_line_numbers; +bool opt_type_builtins; static FILE *open_file(char *path) { if (!path || strcmp(path, "-") == 0) @@ -68,9 +69,11 @@ int main(int argc, char **argv) { for (int i = 1; i < argc; i++) { if (!strcmp(argv[i], "--line-numbers")) { opt_line_numbers = 1; + } else if (!strcmp(argv[i], "--type-builtins")) { + opt_type_builtins = 1; } else { assert(!base_file); - base_file = argv[1]; + base_file = argv[i]; } } cc1(base_file); @@ -3020,7 +3020,9 @@ static Node *primary(Token **rest, Token *tok) { return new_binary(ND_COMMA, lhs, rhs, tok); } - return new_ulong(ty->size, start); + Node *res = new_ulong(ty->size, start); + res->is_sizeof = ty; + return res; } if (equal(tok, "sizeof")) { @@ -3028,19 +3030,25 @@ static Node *primary(Token **rest, Token *tok) { add_type(node); if (node->ty->kind == TY_VLA) return new_var_node(node->ty->vla_size, tok); - return new_ulong(node->ty->size, tok); + Node *res = new_ulong(node->ty->size, tok); + res->is_sizeof = node->ty; + return res; } if (equal(tok, "_Alignof") && equal(tok->next, "(") && is_typename(tok->next->next)) { Type *ty = typename(&tok, tok->next->next); *rest = skip(tok, ")"); - return new_ulong(ty->align, tok); + Node *res = new_ulong(ty->align, tok); + res->is_alignof = ty; + return res; } if (equal(tok, "_Alignof")) { Node *node = unary(rest, tok->next); add_type(node); - return new_ulong(node->ty->align, tok); + Node *res = new_ulong(node->ty->align, tok); + res->is_alignof = node->ty; + return res; } if (equal(tok, "_Generic")) diff --git a/tests/keeping_sizeof.c b/tests/keeping_sizeof.c new file mode 100644 index 0000000..caa34e9 --- /dev/null +++ b/tests/keeping_sizeof.c @@ -0,0 +1,4 @@ +int main() { + int x = sizeof(struct { int a; char b; }); + return 0; +} |