scc: turn arguments the right way round
authorAlan Cox <alan@linux.intel.com>
Wed, 30 Nov 2016 18:44:37 +0000 (18:44 +0000)
committerAlan Cox <alan@linux.intel.com>
Wed, 30 Nov 2016 18:44:37 +0000 (18:44 +0000)
Small C has an irritating design feature that means it stacks arguments left
to right not right to left. Rather than working around this use a spool file
so we can put the code fragments in right to left order.

This totally changes the ABI, which is fine because we aren't using it for
anything and the old ABI is a PITA. With this done we can actually write sane
syscall stubs.

Would benefit from optimisations to also use the internal buffer as a stack
not just flush to the spool file as we stack code fragments.

Needless to say all the old varargs gunge is now a) broken and b) not needed

Applications/SmallC/Makefile
Applications/SmallC/Makefile.linux
Applications/SmallC/data.c
Applications/SmallC/data.h
Applications/SmallC/gen.c
Applications/SmallC/main.c
Applications/SmallC/outstack.c [new file with mode: 0644]
Applications/SmallC/primary.c
Applications/SmallC/prototype.h

index 14870ce..b1bd2da 100644 (file)
@@ -5,7 +5,7 @@ CFLAGS = -DTINY
 COPT = -O2
 
 OBJS = initials.rel data.rel error.rel expr.rel function.rel gen.rel io.rel \
-       lex.rel main.rel preproc.rel primary.rel stmt.rel struct.rel sym.rel while.rel
+       lex.rel main.rel outstack.rel preproc.rel primary.rel stmt.rel struct.rel sym.rel while.rel
 
 OBJ_Z80 = codez80.rel
 OBJ_8080 = code8080.rel
index 977c595..a607df6 100644 (file)
@@ -3,7 +3,7 @@ CFLAGS = -DTINY -DINCDIR=\"includes/\"
 COPT = -O2
 
 OBJS = initials.o data.o error.o expr.o function.o gen.o io.o \
-       lex.o main.o preproc.o primary.o stmt.o struct.o sym.o while.o
+       lex.o main.o outstack.o preproc.o primary.o stmt.o struct.o sym.o while.o
 
 OBJ_Z80 = codez80.o
 OBJ_8080 = code8080.o
index d6c9740..26ead77 100644 (file)
@@ -43,7 +43,7 @@ int     nxtlab,
         cmode,
         lastst;
 
-int     input, input2, output;
+int     input, input2, output, target;
 int     inclstk[INCLSIZ] = {-1, -1, -1 };
 int     inclsp;
 char    fname[20];
index 2ca78fc..799cb71 100644 (file)
@@ -35,7 +35,7 @@ extern  int     nxtlab,
                 cmode,
                 lastst;
 
-extern  int     input, input2, output;
+extern  int     input, input2, output, target;
 extern  int     inclstk[];
 extern  int     inclsp;
 extern  char    fname[];
@@ -55,3 +55,5 @@ extern  int     uflag;  // undocumented 8085 instructions
 extern INITIALS initials_table[NUMBER_OF_GLOBALS];
 extern char initials_data_table[INITIALS_SIZE];      // 5kB space for initialisation data
 extern int initials_idx, initials_data_idx;
+
+extern char    obuf[];
index 46584db..5e1bc05 100644 (file)
@@ -10,7 +10,7 @@
 #include "defs.h"
 #include "data.h"
 
-static char obuf[512];
+char obuf[512];                /* Shared with outstack for defer uses */
 static char *optr = obuf;
 
 void oflush(void)
index e8f1865..800ff44 100644 (file)
@@ -15,7 +15,7 @@ int main(int argc, char *argv[]) {
     macptr = 0;
     ctext = 0;
     errs = 0;
-    aflag = 1;
+    aflag = 0;
     uflag = 0;
     
     for (i=1; i<argc; i++) {
@@ -26,8 +26,8 @@ int main(int argc, char *argv[]) {
                     case 't': case 'T': // output c source as asm comments
                         ctext = 1;
                         break;
-                    case 'a': case 'A': // no argument count in A to function calls
-                        aflag = 0;
+                    case 'a': case 'A': // argument count in A to function calls
+                        aflag = 1;
                         break;
                     case 'u': case 'U': // use undocumented 8085 instructions
                         uflag = 1;
@@ -92,6 +92,7 @@ void compile(char *file) {
         rglobal_table_index = global_table_index; //rglbptr = glbptr;
         //add_global("etext", ARRAY, CCHAR, 0, EXTERN);
         //add_global("edata", ARRAY, CCHAR, 0, EXTERN);
+        /* Eww FIXME when we do types!! */
         defmac("short\tint");
         initmac();
         // compiler body
@@ -103,6 +104,8 @@ void compile(char *file) {
             output = 1;
         } else if (!openout())
             return;
+        target = output;
+        defer_init();
         header();
         code_segment_gtext();
         parse();
diff --git a/Applications/SmallC/outstack.c b/Applications/SmallC/outstack.c
new file mode 100644 (file)
index 0000000..8c6724e
--- /dev/null
@@ -0,0 +1,69 @@
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <stdint.h>
+#include <fcntl.h>
+#include "defs.h"
+#include "data.h"
+
+#define MAX_DEFER      64
+
+static off_t offset_stack[MAX_DEFER];
+static uint8_t next_defer;
+static int defer;
+
+/* Stack chunks of assembler output to be pasted back into the file later.
+   We use this to put arguments in the right order while not having to use
+   tons of RAM */
+
+void defer_output(void)
+{
+    oflush();
+    if (next_defer == MAX_DEFER)
+        error("too many defers");
+    /* Remember where our block started */
+    offset_stack[next_defer++] = lseek(defer, 0L, 1);
+    output = defer;
+}
+
+static void copy_block(void)
+{
+    /* obuf is free at this point */
+    long p = offset_stack[next_defer];
+    long size = lseek(defer, 0L, 1) - p;
+    lseek(defer, p, 0);
+    
+    while (size) {
+        /* Can this ever really be over 64K ?? */
+        unsigned int n = size;
+        if (n > 512)
+            n = 512;
+        if (read(defer, obuf, n) != n)
+         error("rd");
+        if (write(target, obuf, n) !=n)
+         error("wr");
+        size -= n;
+    }
+    lseek(defer, p, 0);
+}
+
+void end_defer(void)
+{
+    --next_defer;
+    /* FIXME: we should fastpath the case of all the bits being in
+       the buffer - in which case we can just fire it at target */
+    oflush();
+    /* Copy from this position to the current position into the target
+       file */
+    copy_block();
+    /* We are back into the main flow, stop outputting via the defer file */
+    if (next_defer == 0)
+        output = target;
+}
+
+void defer_init(void)
+{
+    defer = open("scc-spool", O_RDWR|O_CREAT|O_TRUNC, 0600);
+//    unlink("scc-spool");
+}
index 1b443fe..1832aac 100644 (file)
@@ -350,8 +350,10 @@ int spechar(void) {
  */
 void callfunction(char *ptr) {
     int     nargs;
+    int     i;
 
     nargs = 0;
+
     blanks ();
     if (ptr == 0)
         gen_push (HL_REG);
@@ -361,19 +363,25 @@ void callfunction(char *ptr) {
         expression (NO);
         if (ptr == 0)
             gen_swap_stack ();
+        /* Worth making the first argument pass in HL ?? */
         gen_push (HL_REG);
-        nargs = nargs + INTSIZE;
+        nargs++;
+        /* Will need to track sizes later */
         if (!match (","))
             break;
     }
+    /* Now paste the argument generation blocks into the output
+       in reverse order so the stack is right */
+    for (i = 0; i < nargs; i++)
+        end_defer();
     needbrack (")");
     if (aflag)
-        gnargs(nargs / INTSIZE);
+        gnargs(nargs);
     if (ptr)
         gen_call (ptr);
     else
         callstk ();
-    stkp = gen_modify_stack (stkp + nargs);
+    stkp = gen_modify_stack (stkp + nargs * INTSIZE);
 }
 
 void needlval(void) {
index b9334d9..641e9ae 100644 (file)
@@ -227,3 +227,6 @@ extern WHILE *readwhile(void);
 extern WHILE *findwhile(void);
 extern WHILE *readswitch(void);
 extern void addcase(int val);
+extern void defer_output(void);
+extern void end_defer(void);
+extern void defer_init(void);