Skip to content

Commit 98a2e34

Browse files
committed
Add va_list typedef and variadic function support
This commit implements comprehensive support for variadic functions, including: - Add built-in va_list typedef (int *) for variadic argument handling - Fix typedef pointer level preservation in parser - Add proper array indexing support for typedef pointers - Support pointer arithmetic with typedef pointers - Add expression dereferencing support: *(++p) This enables both traditional pointer arithmetic access to variadic arguments and modern va_list typedef forwarding between functions. Close #202
1 parent 351a058 commit 98a2e34

File tree

4 files changed

+388
-18
lines changed

4 files changed

+388
-18
lines changed

lib/c.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,9 @@
4545

4646
typedef int FILE;
4747

48+
/* va_list support for variadic functions */
49+
typedef int *va_list;
50+
4851
void abort(void);
4952

5053
int strlen(char *str)

src/defs.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -372,6 +372,7 @@ struct type {
372372
int size;
373373
var_t fields[MAX_FIELDS];
374374
int num_fields;
375+
int is_ptr; /* pointer level for typedef pointer types */
375376
};
376377

377378
/* lvalue details */

src/parser.c

Lines changed: 74 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -657,7 +657,9 @@ void read_parameter_list_decl(func_t *func, int anon);
657657
void read_inner_var_decl(var_t *vd, int anon, int is_param)
658658
{
659659
vd->init_val = 0;
660-
vd->is_ptr = 0;
660+
/* Preserve typedef pointer level - don't reset if already inherited */
661+
int base_ptr_level = vd->is_ptr;
662+
vd->is_ptr = base_ptr_level;
661663

662664
while (lex_accept(T_asterisk))
663665
vd->is_ptr++;
@@ -715,6 +717,11 @@ void read_full_var_decl(var_t *vd, int anon, int is_param)
715717
}
716718

717719
vd->type = type;
720+
721+
/* Inherit pointer level from typedef */
722+
if (type->is_ptr > 0)
723+
vd->is_ptr = type->is_ptr;
724+
718725
read_inner_var_decl(vd, anon, is_param);
719726
}
720727

@@ -963,21 +970,33 @@ void read_expr_operand(block_t *parent, basic_block_t **bb)
963970
lvalue_t lvalue;
964971

965972
int open_bracket = lex_accept(T_open_bracket);
966-
lex_peek(T_identifier, token);
967-
var_t *var = find_var(token, parent);
968-
read_lvalue(&lvalue, var, parent, bb, true, OP_generic);
969-
if (open_bracket)
973+
if (open_bracket) {
974+
/* Handle expressions like *(++p) */
975+
read_expr(parent, bb);
970976
lex_expect(T_close_bracket);
977+
rs1 = opstack_pop();
978+
/* Create a temporary variable for the dereferenced result */
979+
vd = require_var(parent);
980+
vd->type = TY_int; /* Default to int type for now */
981+
vd->is_ptr = 0;
982+
gen_name_to(vd->var_name);
983+
opstack_push(vd);
984+
add_insn(parent, *bb, OP_read, vd, rs1, NULL, vd->type->size, NULL);
985+
} else {
986+
lex_peek(T_identifier, token);
987+
var_t *var = find_var(token, parent);
988+
read_lvalue(&lvalue, var, parent, bb, true, OP_generic);
971989

972-
rs1 = opstack_pop();
973-
vd = require_deref_var(parent, var->type, var->is_ptr);
974-
if (lvalue.is_ptr > 1)
975-
sz = PTR_SIZE;
976-
else
977-
sz = lvalue.type->size;
978-
gen_name_to(vd->var_name);
979-
opstack_push(vd);
980-
add_insn(parent, *bb, OP_read, vd, rs1, NULL, sz, NULL);
990+
rs1 = opstack_pop();
991+
vd = require_deref_var(parent, var->type, var->is_ptr);
992+
if (lvalue.is_ptr > 1)
993+
sz = PTR_SIZE;
994+
else
995+
sz = lvalue.type->size;
996+
gen_name_to(vd->var_name);
997+
opstack_push(vd);
998+
add_insn(parent, *bb, OP_read, vd, rs1, NULL, sz, NULL);
999+
}
9811000
} else if (lex_accept(T_open_bracket)) {
9821001
read_expr(parent, bb);
9831002
read_ternary_operation(parent, bb);
@@ -1374,8 +1393,31 @@ void read_lvalue(lvalue_t *lvalue,
13741393
error("Cannot apply square operator to non-pointer");
13751394

13761395
/* if nested pointer, still pointer */
1377-
if (var->is_ptr <= 1 && var->array_size == 0)
1378-
lvalue->size = lvalue->type->size;
1396+
if (var->is_ptr <= 1 && var->array_size == 0) {
1397+
/* For typedef pointers, get the size of the base type that the
1398+
* pointer points to
1399+
*/
1400+
if (lvalue->type->is_ptr > 0) {
1401+
/* This is a typedef pointer, get base type size */
1402+
switch (lvalue->type->base_type) {
1403+
case TYPE_char:
1404+
lvalue->size = TY_char->size;
1405+
break;
1406+
case TYPE_int:
1407+
lvalue->size = TY_int->size;
1408+
break;
1409+
case TYPE_void:
1410+
/* void pointers treated as byte pointers */
1411+
lvalue->size = 1;
1412+
break;
1413+
default:
1414+
lvalue->size = lvalue->type->size;
1415+
break;
1416+
}
1417+
} else {
1418+
lvalue->size = lvalue->type->size;
1419+
}
1420+
}
13791421

13801422
read_expr(parent, bb);
13811423

@@ -1529,7 +1571,12 @@ void read_lvalue(lvalue_t *lvalue,
15291571
if (prefix_op != OP_generic) {
15301572
vd = require_var(parent);
15311573
gen_name_to(vd->var_name);
1532-
vd->init_val = 1;
1574+
/* For pointer arithmetic, increment by the size of pointed-to type
1575+
*/
1576+
if (lvalue->is_ptr)
1577+
vd->init_val = lvalue->type->size;
1578+
else
1579+
vd->init_val = 1;
15331580
opstack_push(vd);
15341581
add_insn(parent, *bb, OP_load_constant, vd, NULL, NULL, 0, NULL);
15351582

@@ -1550,6 +1597,8 @@ void read_lvalue(lvalue_t *lvalue,
15501597
*/
15511598
add_insn(parent, *bb, OP_write, NULL, vd, rs1, lvalue->size,
15521599
NULL);
1600+
/* Push the new value onto the operand stack */
1601+
opstack_push(rs1);
15531602
} else {
15541603
rs1 = vd;
15551604
vd = operand_stack[operand_stack_idx - 1];
@@ -3037,6 +3086,14 @@ void read_global_statement(void)
30373086
type->base_type = base->base_type;
30383087
type->size = base->size;
30393088
type->num_fields = 0;
3089+
type->is_ptr = 0;
3090+
3091+
/* Handle pointer types in typedef: typedef char *string; */
3092+
while (lex_accept(T_asterisk)) {
3093+
type->is_ptr++;
3094+
type->size = PTR_SIZE;
3095+
}
3096+
30403097
lex_ident(T_identifier, type->type_name);
30413098
lex_expect(T_semicolon);
30423099
}

0 commit comments

Comments
 (0)