Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Working function-pointers! #54

Merged
merged 5 commits into from
Oct 27, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion examples/asm/elmer/include/cdrom.asm
Original file line number Diff line number Diff line change
Expand Up @@ -1454,7 +1454,7 @@ cdr_cplay_next .proc

; Timeout, retry.

bra cdr_cplay_next
jmp cdr_cplay_next ; Not a BRA because a .proc!

; Process SCSI phases.

Expand Down
2 changes: 1 addition & 1 deletion examples/asm/elmer/include/ted2-fat32.asm
Original file line number Diff line number Diff line change
Expand Up @@ -1391,7 +1391,7 @@ f32_seek_cur .proc
sta <_ax + 0

bsr f32_next_frag ; Move forward to next fragment.
bra f32_seek_cur ; Try again.
jmp f32_seek_cur ; Try again.

; frag_len > seek_len

Expand Down
14 changes: 10 additions & 4 deletions include/hucc/hucc-codegen.asm
Original file line number Diff line number Diff line change
Expand Up @@ -318,13 +318,18 @@ __call .macro

; **************

__funcp.wr .macro
sta.l __func
sty.h __func
.endm

; **************

__callp .macro
sta.l __ptr
sty.h __ptr
jsr call_indirect
.endm

call_indirect: jmp [__ptr]
call_indirect: jmp [__func]



Expand All @@ -342,8 +347,9 @@ __enter .macro

; **************
; function epilog
; \1 == 0 if no return value

__leave .macro
__return .macro
.if (\1 != 0)
sta <__hucc_ret
.endif
Expand Down
4 changes: 4 additions & 0 deletions include/hucc/hucc.asm
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,10 @@ __ptr .ds 2

__poke = __si

; Used for indirect calls because __ptr could be overwritten.

__func = __si

; Data pointer used by SDCC for indirect indexed memory access.

DPTR = __ptr
Expand Down
8 changes: 6 additions & 2 deletions src/hucc/code.c
Original file line number Diff line number Diff line change
Expand Up @@ -412,6 +412,10 @@ void gen_code (INS *tmp)
nl();
break;

case I_FUNCP_WR:
ol("__funcp.wr");
break;

case I_CALLP:
ol("__callp");
break;
Expand All @@ -424,8 +428,8 @@ void gen_code (INS *tmp)
nl();
break;

case I_LEAVE:
ot("__leave\t\t");
case I_RETURN:
ot("__return\t\t");
outdec((int)data);
nl();
break;
Expand Down
8 changes: 2 additions & 6 deletions src/hucc/const.c
Original file line number Diff line number Diff line change
Expand Up @@ -59,15 +59,11 @@ void add_const (char typ)
* array initializer
*
*/
int array_initializer (char typ, char id, char stor)
int array_initializer (char typ, char id, char stor, int k)
{
int nb;
int k;
int nb = 0;
int i;

nb = 0;
k = needsub();

if (stor == CONST)
new_const();
if (match("=")) {
Expand Down
2 changes: 1 addition & 1 deletion src/hucc/const.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

void new_const (void);
void add_const (char typ);
int array_initializer (char typ, char id, char stor);
int array_initializer (char typ, char id, char stor, int k);
int scalar_initializer (char typ, char id, char stor);
int get_string_ptr (char typ);
int get_raw_value (char sep);
Expand Down
11 changes: 7 additions & 4 deletions src/hucc/defs.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,12 +38,13 @@ enum ICODE {

I_MACRO,
I_CALL,
I_FUNCP_WR,
I_CALLP,

/* i-codes for C functions and the C parameter stack */

I_ENTER,
I_LEAVE,
I_RETURN,
I_GETACC,
I_SAVESP,
I_LOADSP,
Expand Down Expand Up @@ -421,15 +422,17 @@ enum ICOMPARE {
typedef struct symbol {
char name[NAMEALLOC]; /* symbol name */
struct symbol *linked; /* HuC: linked local and global symbols */
int alloc_size;
char identity; /* variable, array, pointer, function */
char sym_type; /* char, int, uchar, unit */
char storage; /* public, auto, extern, static, lstatic, defauto*/
char far; /* HuC: 1 if array of data in far memory */
char ptr_order; /* HuC: 1 if array of data in far memory */
char funcptr_type; /* HuC: return type if function pointer */
char funcptr_order; /* HuC: return order if function pointer */
char arg_count; /* HuC: #arguments for function or function pointer */
short offset; /* offset*/
short tagidx; /* index of struct in tag table*/
short ptr_order;
short arg_count;
int alloc_size;
} SYMBOL;

/* Define the structure tag table parameters */
Expand Down
142 changes: 75 additions & 67 deletions src/hucc/expr.c
Original file line number Diff line number Diff line change
Expand Up @@ -196,7 +196,6 @@ int heir1 (LVALUE *lval, int comma)
int heir1a (LVALUE *lval, int comma)
{
int k, lab1, lab2;
LVALUE lval2[1] = {{0}};

k = heir1b(lval, comma);
blanks();
Expand All @@ -210,21 +209,21 @@ int heir1a (LVALUE *lval, int comma)
FOREVER
if (match("?")) {
testjump(lab1 = getlabel(), FALSE);
if (heir1b(lval2, comma))
rvalue(lval2);
if (lval2->val_type == CVOID)
void_value_error(lval2);
if (heir1b(lval, comma))
rvalue(lval);
if (lval->val_type == CVOID)
void_value_error(lval);
jump(lab2 = getlabel());
gnlabel(lab1);
blanks();
if (!match(":")) {
error("missing colon");
return (0);
}
if (heir1b(lval2, comma))
rvalue(lval2);
if (lval2->val_type == CVOID)
void_value_error(lval2);
if (heir1b(lval, comma))
rvalue(lval);
if (lval->val_type == CVOID)
void_value_error(lval);
gnlabel(lab2);
}
else
Expand Down Expand Up @@ -779,19 +778,22 @@ int heir10 (LVALUE *lval, int comma)
k = heir10(lval, comma);
indflg = 0;
ptr = lval->symbol;
if (ptr && ptr->funcptr_type && lval->ptr_order == 0) {
/* ignore optional dereference of a function pointer */
return (k);
}
if (k)
rvalue(lval);
if (lval->val_type == CVOID)
void_value_error(lval);
if (lval->ptr_order < 2)
lval->indirect = lval->ptr_type;
else
if (lval->ptr_order > 1) {
lval->indirect = CUINT;
/* XXX: what about multiple indirection? */
if (lval->ptr_order > 1)
lval->ptr_order--;
else {
lval->ptr_type = 0; /* flag as not pointer or array */
} else {
if (lval->ptr_type == 0)
error("not a pointer");
lval->indirect = lval->ptr_type;
lval->ptr_type = 0; /* flag as not pointer or array */
lval->ptr_order = 0;
}
return (1);
Expand All @@ -805,7 +807,9 @@ int heir10 (LVALUE *lval, int comma)
return (0);
}
if (k == 0) {
error("illegal address");
/* allow "&function" in function pointer assignment */
if (lval->symbol == NULL || lval->symbol->identity != FUNCTION)
error("illegal address");
return (0);
}
if (lval->symbol) {
Expand Down Expand Up @@ -885,11 +889,11 @@ int heir11 (LVALUE *lval, int comma)
if (lval->val_type == CVOID)
void_value_error(lval);
if (ptr == 0) {
if (lval->ptr_type) {
/* subscription of anonymous array
ATM this can only happen for a
string literal. */
if (lval->ptr_type != CCHAR)
if (lval->ptr_type && lval->ptr_order == 1) {
/* subscription of anonymous array which is currently
only supported for a string literal, primarily for
the testsuite, such as "921218-1.c". */
if (lval->ptr_type != ((user_signed_char) ? CCHAR : CUCHAR))
error("internal error: cannot subscript non-character literals");
/* Primary contains literal pointer, add subscript. */
gpush();
Expand All @@ -915,18 +919,18 @@ int heir11 (LVALUE *lval, int comma)
return (0);
}
}
else if (ptr->identity == POINTER)
rvalue(lval);
else if (ptr->identity != ARRAY) {
else if (ptr->identity != POINTER && ptr->identity != ARRAY) {
error("can't subscript");
k = 0;
}
if (k)
rvalue(lval);
if (!deferred && !ptr->far)
gpush();
expression(YES);
needbracket("]");
if (ptr->sym_type == CINT || ptr->sym_type == CUINT || lval->ptr_order > 1 ||
(ptr->identity == ARRAY && lval->ptr_order > 0))
if (ptr->sym_type == CINT || ptr->sym_type == CUINT ||
lval->ptr_order > ((ptr->identity == ARRAY) ? 0 : 1))
gaslint();
else if (ptr->sym_type == CSTRUCT) {
int size = tag_table[ptr->tagidx].size;
Expand All @@ -935,8 +939,6 @@ int heir11 (LVALUE *lval, int comma)
else if (size > 1)
gmult_imm(size);
}
if (!deferred && !ptr->far)
gadd(NULL, NULL);
if (deferred) {
#if ULI_NORECURSE
if ((ptr->storage & STORAGE) == AUTO && norecurse && glint(ptr) < 0) {
Expand All @@ -956,29 +958,21 @@ int heir11 (LVALUE *lval, int comma)
out_ins(I_ADD_WI, T_SYMBOL, (intptr_t)ptr);
deferred = false;
}
lval->symbol = 0;
if (lval->ptr_order > 1 || (ptr->identity == ARRAY && lval->ptr_order > 0))
lval->indirect = CUINT;
else
lval->indirect = ptr->sym_type;
if (lval->ptr_order > 1)
if (!ptr->far)
gadd(NULL, NULL);
if (lval->ptr_order > ((ptr->identity == ARRAY) ? 0 : 1)) {
lval->indirect = CUINT;
lval->ptr_order--;
}
else {
lval->indirect = lval->ptr_type;
lval->ptr_type = 0;
lval->ptr_order = 0;
blanks();
if (ptr->identity == ARRAY && ch() == '[') {
/* Back-to-back indexing: We loop
right inside this function, so
nobody else takes care of
actually loading the pointer. */
rvalue(lval);
lval->indirect = ptr->sym_type;
lval->ptr_type = ptr->sym_type;
lval->ptr_order = 0;
}
else {
// lval->val_type = lval->ptr_type;
lval->ptr_type = 0; // VARIABLE; /* David, bug patch ?? */
lval->ptr_order = 0;
if (ch() == '[') {
/* force an error in the next subscript attempt */
lval->symbol = NULL;
}
}
lval->symbol2 = ptr->far ? ptr : NULL;
Expand All @@ -989,30 +983,44 @@ int heir11 (LVALUE *lval, int comma)
void_value_error(lval);
if (ptr == 0) {
error("invalid or unsupported function call");
callfunction(0);
}
else if (ptr->identity != FUNCTION) {
rvalue(lval);
callfunction(0);
junk();
return (0);
}
else
callfunction(ptr->name);
k = 0;
/* Encode return type in lval. */
SYMBOL *s = lval->symbol;
if (s) {
if (s->sym_type == 0)
error("function return type is unknown");
if (s->ptr_order >= 1) {
lval->ptr_type = s->sym_type;
lval->ptr_order = s->ptr_order;
if (ptr->identity == FUNCTION) {
callfunction(ptr);
if (ptr->ptr_order) {
lval->val_type = 0;
lval->ptr_type = ptr->sym_type;
lval->ptr_order = ptr->ptr_order;
} else {
lval->val_type = ptr->sym_type;
lval->ptr_type = 0;
lval->ptr_order = 0;
}
if (ptr->sym_type == CSTRUCT)
lval->tagsym = &tag_table[ptr->tagidx];
}
else {
if (ptr->funcptr_type == 0 || lval->ptr_order != 0)
error("not a function pointer");
if (k)
rvalue(lval);
callfunction(ptr);
if (ptr->funcptr_order) {
lval->val_type = 0;
lval->ptr_type = ptr->funcptr_type;
lval->ptr_order = ptr->funcptr_order;
} else {
lval->val_type = s->sym_type;
lval->val_type = ptr->funcptr_type;
lval->ptr_type = 0;
lval->ptr_order = 0;
}
if (s->sym_type == CSTRUCT)
lval->tagsym = &tag_table[s->tagidx];
lval->symbol = 0;
if (ptr->funcptr_type == CSTRUCT)
lval->tagsym = &tag_table[ptr->tagidx];
}
k = 0;
lval->symbol = 0;
}
else if ((direct = match(".")) || match("->")) {
if (lval->val_type == CVOID)
Expand Down
Loading