Skip to content

Commit

Permalink
Merge pull request #54 from jbrandwood/master
Browse files Browse the repository at this point in the history
Working function-pointers!
  • Loading branch information
jbrandwood authored Oct 27, 2024
2 parents 3797c4c + d88e464 commit ed32900
Show file tree
Hide file tree
Showing 22 changed files with 591 additions and 229 deletions.
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

0 comments on commit ed32900

Please sign in to comment.