aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authornsfisis <nsfisis@gmail.com>2025-05-04 14:53:01 +0900
committernsfisis <nsfisis@gmail.com>2025-05-04 14:53:01 +0900
commit1a224ae3f0e9565e0740288c176967659d856928 (patch)
tree0a06574947a04da88355a74ca3b430791fb011a6
parentc383c4874262761cf4b1e8aa4eb21e47c0c78bc5 (diff)
downloadP4Dcc-1a224ae3f0e9565e0740288c176967659d856928.tar.gz
P4Dcc-1a224ae3f0e9565e0740288c176967659d856928.tar.zst
P4Dcc-1a224ae3f0e9565e0740288c176967659d856928.zip
sizeof
-rw-r--r--main.c94
-rw-r--r--tests/023.sh39
2 files changed, 99 insertions, 34 deletions
diff --git a/main.c b/main.c
index 9af25c7..ee6f631 100644
--- a/main.c
+++ b/main.c
@@ -279,10 +279,28 @@ TYPE* type_new_ptr(TYPE* to) {
return ty;
}
-int type_is_valid_for_var(TYPE* ty) {
+int type_is_unsized_type(TYPE* ty) {
return ty->kind != TY_VOID;
}
+int type_sizeof(TYPE* ty) {
+ if (!type_is_unsized_type(ty)) {
+ fatal_error("type_sizeof: type size cannot be determined");
+ }
+
+ if (ty->kind == TY_PTR) {
+ return 8;
+ } else if (ty->kind == TY_CHAR) {
+ return 1;
+ } else if (ty->kind == TY_INT) {
+ return 4;
+ } else if (ty->kind == TY_LONG) {
+ return 8;
+ } else {
+ todo();
+ }
+}
+
#define AST_UNKNOWN 0
#define AST_ARG_LIST 1
@@ -510,6 +528,37 @@ AST* parse_postfix_expr(PARSER* p) {
return ret;
}
+int is_type_token(int token_kind) {
+ return token_kind == TK_K_INT || token_kind == TK_K_LONG || token_kind == TK_K_CHAR || token_kind == TK_K_VOID;
+}
+
+TYPE* parse_type(PARSER* p) {
+ TOKEN* t = next_token(p);
+ if (!is_type_token(t->kind)) {
+ fatal_error("parse_type: unknown type");
+ }
+ TYPE* ty = type_new(TY_UNKNOWN);
+ if (t->kind == TK_K_INT) {
+ ty->kind = TY_INT;
+ } else if (t->kind == TK_K_LONG) {
+ ty->kind = TY_LONG;
+ } else if (t->kind == TK_K_CHAR) {
+ ty->kind = TY_CHAR;
+ } else if (t->kind == TK_K_VOID) {
+ ty->kind = TY_VOID;
+ }
+ while (1) {
+ TOKEN* t2 = peek_token(p);
+ if (t2->kind == TK_STAR) {
+ next_token(p);
+ ty = type_new_ptr(ty);
+ } else {
+ break;
+ }
+ }
+ return ty;
+}
+
AST* parse_prefix_expr(PARSER* p) {
int op = peek_token(p)->kind;
if (op == TK_MINUS) {
@@ -530,6 +579,14 @@ AST* parse_prefix_expr(PARSER* p) {
AST* e = ast_new(AST_DEREF_EXPR);
e->expr1 = operand;
return e;
+ } else if (op == TK_K_SIZEOF) {
+ next_token(p);
+ expect(p, TK_PAREN_L);
+ TYPE* ty = parse_type(p);
+ expect(p, TK_PAREN_R);
+ AST* e = ast_new(AST_INT_LIT_EXPR);
+ e->int_value = type_sizeof(ty);
+ return e;
}
return parse_postfix_expr(p);
}
@@ -681,40 +738,9 @@ AST* parse_continue_stmt(PARSER* p) {
return ast_new(AST_CONTINUE_STMT);
}
-int is_type_token(int token_kind) {
- return token_kind == TK_K_INT || token_kind == TK_K_LONG || token_kind == TK_K_CHAR || token_kind == TK_K_VOID;
-}
-
-TYPE* parse_type(PARSER* p) {
- TOKEN* t = next_token(p);
- if (!is_type_token(t->kind)) {
- fatal_error("parse_type: unknown type");
- }
- TYPE* ty = type_new(TY_UNKNOWN);
- if (t->kind == TK_K_INT) {
- ty->kind = TY_INT;
- } else if (t->kind == TK_K_LONG) {
- ty->kind = TY_LONG;
- } else if (t->kind == TK_K_CHAR) {
- ty->kind = TY_CHAR;
- } else if (t->kind == TK_K_VOID) {
- ty->kind = TY_VOID;
- }
- while (1) {
- TOKEN* t2 = peek_token(p);
- if (t2->kind == TK_STAR) {
- next_token(p);
- ty = type_new_ptr(ty);
- } else {
- break;
- }
- }
- return ty;
-}
-
AST* parse_var_decl(PARSER* p) {
TYPE* ty = parse_type(p);
- if (!type_is_valid_for_var(ty)) {
+ if (!type_is_unsized_type(ty)) {
fatal_error("parse_var_decl: invalid type for variable");
}
char* name = parse_ident(p);
@@ -791,7 +817,7 @@ void parse_register_params(PARSER* p, AST* params) {
AST* parse_param(PARSER* p) {
TYPE* ty = parse_type(p);
- if (!type_is_valid_for_var(ty)) {
+ if (!type_is_unsized_type(ty)) {
fatal_error("parse_param: invalid type for variable");
}
char* name = parse_ident(p);
diff --git a/tests/023.sh b/tests/023.sh
new file mode 100644
index 0000000..86e2aa6
--- /dev/null
+++ b/tests/023.sh
@@ -0,0 +1,39 @@
+set -e
+
+cat <<'EOF' > expected
+sizeof(int) = 4
+sizeof(int*) = 8
+sizeof(char) = 1
+sizeof(char*) = 8
+sizeof(long) = 8
+sizeof(long*) = 8
+sizeof(void*) = 8
+sizeof(int**) = 8
+sizeof(char**) = 8
+sizeof(long**) = 8
+sizeof(void**) = 8
+sizeof(int***) = 8
+sizeof(char***) = 8
+sizeof(long***) = 8
+sizeof(void***) = 8
+EOF
+bash ../../test_diff.sh <<'EOF'
+int main() {
+ printf("sizeof(int) = %d\n", sizeof(int));
+ printf("sizeof(int*) = %d\n", sizeof(int*));
+ printf("sizeof(char) = %d\n", sizeof(char));
+ printf("sizeof(char*) = %d\n", sizeof(char*));
+ printf("sizeof(long) = %d\n", sizeof(long));
+ printf("sizeof(long*) = %d\n", sizeof(long*));
+ printf("sizeof(void*) = %d\n", sizeof(void*));
+ printf("sizeof(int**) = %d\n", sizeof(int**));
+ printf("sizeof(char**) = %d\n", sizeof(char**));
+ printf("sizeof(long**) = %d\n", sizeof(long**));
+ printf("sizeof(void**) = %d\n", sizeof(void**));
+ printf("sizeof(int***) = %d\n", sizeof(int***));
+ printf("sizeof(char***) = %d\n", sizeof(char***));
+ printf("sizeof(long***) = %d\n", sizeof(long***));
+ printf("sizeof(void***) = %d\n", sizeof(void***));
+ return 0;
+}
+EOF