Skip to content

Commit

Permalink
Issue #1132: Passing structs to function pointers
Browse files Browse the repository at this point in the history
  • Loading branch information
suborb committed Apr 14, 2019
1 parent f80bed2 commit 1e79ec0
Show file tree
Hide file tree
Showing 6 changed files with 95 additions and 47 deletions.
32 changes: 23 additions & 9 deletions lib/z80rules.1
Original file line number Diff line number Diff line change
Expand Up @@ -516,15 +516,6 @@
=
pop de

pop bc
ld hl,%1 ;const
add hl,sp
ld sp,hl
=
ld hl,%eval(%1 2 +) ;const
add hl,sp
ld sp,hl

exx
ld hl,%1 ;const
add hl,sp
Expand Down Expand Up @@ -4056,3 +4047,26 @@
ld de,0
ld a,h
or l

ld hl,%1
push hl
ld hl,%2 ;const
add hl,sp
ex de,hl
pop bc
=
ld hl,%eval(%2 2 -) ;const
add hl,sp
ex de,hl
ld bc,%1

ld hl,%1 ;const
add hl,sp
ld sp,hl
ld hl,%2 ;const
add hl,sp
ld sp,hl
=
ld hl,%eval(65536 %1 %2 + %) ;const
add hl,sp
ld sp,hl
23 changes: 2 additions & 21 deletions src/sccz80/callfunc.c
Original file line number Diff line number Diff line change
Expand Up @@ -288,27 +288,8 @@ void callfunction(SYMBOL *ptr, Type *fnptr_type)
if ( function_pointer_call == 0 || fnptr_type->kind == KIND_CPTR ) {
nargs += push_function_argument(expr, type, functype->flags & SDCCDECL && argnumber <= array_len(functype->parameters));
} else {
// Regular function pointer
if (expr == KIND_LONG || expr == KIND_CPTR) {
if ( tmpfiles[argnumber+1] != NULL ) {
swap(); /* MSW -> hl */
swapstk(); /* MSW -> stack, addr -> hl */
zpushde(); /* LSW -> stack, addr = hl */
}
nargs += 4;
last_argument_size = 4;
} else if (expr == KIND_DOUBLE) {
dpush_under(KIND_INT);
nargs += 6;
last_argument_size = 6;
mainpop();
} else {
if ( tmpfiles[argnumber+1] != NULL ) {
swapstk();
}
nargs += 2;
last_argument_size = 2;
}
last_argument_size = push_function_argument_fnptr(expr, type, functype->flags & SDCCDECL && argnumber <= array_len(functype->parameters), tmpfiles[argnumber+1] == NULL);
nargs += last_argument_size;
}
}
restore_input();
Expand Down
50 changes: 35 additions & 15 deletions src/sccz80/codegen.c
Original file line number Diff line number Diff line change
Expand Up @@ -703,25 +703,45 @@ int push_function_argument(Kind expr, Type *type, int push_sdccchar)
return 2;
}




/* Push structure onto stack - address located in hl */
void push_struct(Type *type)
/* Push an argument for a function pointer call */
int push_function_argument_fnptr(Kind expr, Type *type, int push_sdccchar, int is_last_argument)
{
swap(); /* de = stack address */
vconst(-type->size);
ol("add\thl,sp");
ol("ld\tsp,hl");
Zsp -= type->size;
swap();
outfmt("\tld\tbc,%d\n",type->size);
ol("ldir");
if (expr == KIND_LONG || expr == KIND_CPTR) {
if ( !is_last_argument ) {
swap(); /* MSW -> hl */
swapstk(); /* MSW -> stack, addr -> hl */
zpushde(); /* LSW -> stack, addr = hl */
}
return 4;
} else if (expr == KIND_DOUBLE) {
dpush_under(KIND_INT);
mainpop();
return 6;
} else if (expr == KIND_STRUCT ) {
// 13 bytes
swap(); // de = address of struct
ol("pop\tbc"); // return address
vconst(-type->size);
ol("add\thl,sp");
ol("ld\tsp,hl");
ol("push\tbc");
Zsp -= type->size;
swap();
outfmt("\tld\tbc,%d\n",type->size);
ol("ldir");
mainpop();
return type->size;
}
if ( !is_last_argument ) {
swapstk();
}
return 2;
}



/* Push the primary floating point register, preserving
the top value */

void dpush_under(int val_type)
{
if ( val_type == KIND_LONG ) {
Expand Down Expand Up @@ -845,7 +865,7 @@ void callstk(Type *type, int n, int isfarptr, int last_argument_size)
}
loadargc(n);
callrts("l_farcall");
} else if ( type->flags & FASTCALL && last_argument_size != 6 ) {
} else if ( type->flags & FASTCALL && last_argument_size < 6 ) {
int label = getlabel();
// TOS = address, dehl = parameter
// More than one argument, TOS = last parameter, hl = function
Expand Down
1 change: 1 addition & 0 deletions src/sccz80/codegen.h
Original file line number Diff line number Diff line change
Expand Up @@ -136,4 +136,5 @@ extern void zentercritical(void);
extern void zleavecritical(void);
extern int zcriticaloffset(void);
extern int push_function_argument(Kind expr, Type *type, int push_sdccchar);
extern int push_function_argument_fnptr(Kind expr, Type *type, int push_sdccchar, int is_last_argument);

11 changes: 11 additions & 0 deletions testsuite/Issue_1132_struct_parameter.c
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@



struct test {
char c[10];
int x;
int y;
};

typedef void *(*fptr)(struct test x);

static fptr fnptr;

void func(struct test x, int y)
{
Expand All @@ -25,3 +29,10 @@ void func_calling(void)
func(a, 10);
}


void func_fptr(void)
{
struct test a;

fnptr(a);
}
25 changes: 23 additions & 2 deletions testsuite/results/Issue_1132_struct_parameter.opt
Original file line number Diff line number Diff line change
Expand Up @@ -47,10 +47,29 @@
ld hl,10 ;const
push hl
call _func
ld hl,16 ;const
ld hl,30 ;const
add hl,sp
ld sp,hl
ret



._func_fptr
ld hl,65522 ;const
add hl,sp
ld sp,hl
ld hl,14 ;const
ex de,hl
ld bc,(_fnptr)
ld hl,65522 ;const
add hl,sp
ld sp,hl
push bc
ex de,hl
ld bc,14
ldir
pop hl
call l_jphl
ld hl,28 ;const
add hl,sp
ld sp,hl
ret
Expand All @@ -59,13 +78,15 @@


SECTION bss_compiler
._fnptr defs 2
SECTION code_compiler



GLOBAL _func
GLOBAL _func_callee
GLOBAL _func_calling
GLOBAL _func_fptr



Expand Down

0 comments on commit 1e79ec0

Please sign in to comment.