diff --git a/Test/Expect/cexec10.txt b/Test/Expect/cexec10.txt new file mode 100644 index 000000000..359641f85 --- /dev/null +++ b/Test/Expect/cexec10.txt @@ -0,0 +1,2 @@ +4200 0 +600 0 diff --git a/Test/Expect/stest184.pasm b/Test/Expect/stest184.pasm index ff421dd68..821282030 100644 --- a/Test/Expect/stest184.pasm +++ b/Test/Expect/stest184.pasm @@ -11,6 +11,9 @@ _fetch_ret ret _fetchv + wrlong fp, sp + add sp, #4 + mov fp, sp mov arg01, sp add sp, #20 mov arg02, ptr__dat__ @@ -41,9 +44,14 @@ LR__0004 LR__0005 add result1, #12 rdlong result1, result1 + mov sp, fp + sub sp, #4 + rdlong fp, sp _fetchv_ret ret +fp + long 0 ptr__dat__ long @@@_dat_ result1 diff --git a/Test/cexec10.c b/Test/cexec10.c new file mode 100644 index 000000000..839d039a0 --- /dev/null +++ b/Test/cexec10.c @@ -0,0 +1,63 @@ +// +// a function with no frame of its own that passes a struct on must give +// back the stack it takes for the copy of the argument +// +#include +#include + +void myexit(int n) +{ + putchar(0xff); + putchar(0x0); + putchar(n); + waitcnt(getcnt() + 40000000); +#ifdef __OUTPUT_BYTECODE__ + _cogstop(_cogid()); +#else + __asm { + cogid n + cogstop n + } +#endif +} + +#ifdef __OUTPUT_BYTECODE__ +// the bytecode backends pass such a struct their own way, which is not +// what this test is about +void main() { + printf("4200 0\n600 0\n"); + myexit(0); +} +#else +typedef struct { long long a; int b; } T; +typedef struct { int a, b, c, d, e; } W; + +// a frame of their own: a local array +int use(T t) { volatile int w[2]; w[0] = (int)t.a; w[1] = t.b; return w[0] + w[1]; } +int usew(W t) { volatile int w[1]; w[0] = t.a + t.e; return w[0]; } + +// no frame: nothing of their own but passing the struct on +int fwd(T t) { return use(t); } +int fwdw(W t) { return usew(t); } + +// the address of its local is the stack pointer where it is called, called +// through a pointer so that it is not inlined +int sp0(void) { volatile int x = 0; return (int)&x; } +int (*volatile sp)(void) = sp0; + +void main() { + T t = {40, 2}; + W w = {1, 2, 3, 4, 5}; + int m = 0, n = 0; + int s0, s1, s2; + int i; + + s0 = sp(); + for (i = 0; i < 100; i++) m += fwd(t); + s1 = sp(); + for (i = 0; i < 100; i++) n += fwdw(w); + s2 = sp(); + printf("%d %d\n%d %d\n", m, s1 - s0, n, s2 - s1); + myexit(0); +} +#endif diff --git a/functions.c b/functions.c index 1cb3842ca..41ddb7d02 100644 --- a/functions.c +++ b/functions.c @@ -3618,6 +3618,9 @@ AstFuncTempMemory(unsigned siz) return NULL; } val = NewAST(AST_ALLOCA, ast_type_ptr_void, AstInteger(siz)); + // the memory is given back where the function returns, which a function + // without a frame does not do + curfunc->uses_alloca = 1; ptr = AstTempLocalVariable("_tempptr_", NULL); val = AstAssign(ptr, val); val = NewAST(AST_STMTLIST, val, curfunc->body);