From 7f32ad51b0f08446d7f66e5403d69299d0d60021 Mon Sep 17 00:00:00 2001 From: Andreas Baumann Date: Fri, 1 Oct 2021 21:10:36 +0200 Subject: c4: added strl* functions cc: started peudo function parsing, currently for void main() only some philosophical thinking and testing around forward function declarations --- miniany/README.html | 3 +- miniany/REQUIREMENTS | 10 ++++++- miniany/c4.c | 77 ++++++++++++++++++++++++++++------------------------ miniany/cc.c | 27 +++++++++++++++--- miniany/cc.wg | 11 ++++---- miniany/hello.c | 32 +++++++++++++++++++++- 6 files changed, 113 insertions(+), 47 deletions(-) (limited to 'miniany') diff --git a/miniany/README.html b/miniany/README.html index 9b7fcbf..53eac72 100644 --- a/miniany/README.html +++ b/miniany/README.html @@ -25,7 +25,8 @@
  • negative enum initializers
  • do/while loops
  • more C functions like isspace, getc, strcmp
  • -
  • some simplified functions for printing like putstring, putint, putnl
  • +
  • some simplified functions for printing like putstring, putint, putnl replacing printf-like functions
  • +
  • BSD-style string functions like strlcpy, strlcat
  • strict C89 conformance, mainly use standard comment blocks, also removed some warnings
  • some casts around malloc and memset to fit to non-void freestanding-libc
  • converted printf to putstring/putint/putnl and some helper functions for error reporting like error()
  • diff --git a/miniany/REQUIREMENTS b/miniany/REQUIREMENTS index 985def7..a6fce03 100644 --- a/miniany/REQUIREMENTS +++ b/miniany/REQUIREMENTS @@ -130,5 +130,13 @@ TODO: semicolon after the last triplet). IMHO a for loop makes sense for SIMD operations only when we can use a stricter grammar to optimize certain iterations. - +- c4: recursive descent parsing requires forward function declarations. Forward + function declarations are not that easy to implement, because you have to + generate a placeholder for the call address before you get the whole + definition of the forwarded function (especially its entry address). + Or we create sort of a temporary jump into a jump table (sort of a GOT) which + we patch when we know the address of the implementation of the function. + Having a global table at one place scales easier, as we don't have to keep + the whole generated code around just for patching (remember, we have tapes + and memory, no seek of files). diff --git a/miniany/c4.c b/miniany/c4.c index ca6d3d3..7c2b53b 100644 --- a/miniany/c4.c +++ b/miniany/c4.c @@ -68,7 +68,7 @@ enum { /* opcodes */ enum { LEA ,IMM ,JMP ,JSR ,BZ ,BNZ ,ENT ,ADJ ,LEV ,LI ,LC ,SI ,SC ,PSH , OR ,XOR ,AND ,EQ ,NE ,LT ,GT ,LE ,GE ,SHL ,SHR ,ADD ,SUB ,MUL ,DIV ,MOD , - MALC,FREE,MCPY,MSET,MCMP,GETC,PUTS,PUTN,PUTC,PUTI,ISPC,IDGT,IANU,IALP,SCMP,SDUP,EXIT }; + MALC,FREE,MCPY,MSET,MCMP,GETC,PUTS,PUTN,PUTC,PUTI,ISPC,IDGT,IANU,IALP,SCMP,SDUP,SLCP,SLCA,EXIT }; /* types */ enum { CHAR, INT, PTR = 256, PTR2 = 512 }; @@ -113,7 +113,7 @@ void next() le++; memcpy(buf, &"LEA ,IMM ,JMP ,JSR ,BZ ,BNZ ,ENT ,ADJ ,LEV ,LI ,LC ,SI ,SC ,PSH ," "OR ,XOR ,AND ,EQ ,NE ,LT ,GT ,LE ,GE ,SHL ,SHR ,ADD ,SUB ,MUL ,DIV ,MOD ," - "MALC,FREE,MCPY,MSET,MCMP,GETC,PUTS,PUTN,PUTC,PUTI,ISPC,IDGT,IANU.IALP,SCMP,SDUP,EXIT,"[*le * 5], 4); + "MALC,FREE,MCPY,MSET,MCMP,GETC,PUTS,PUTN,PUTC,PUTI,ISPC,IDGT,IANU.IALP,SCMP,SDUP,SLCP,SLCA,EXIT,"[*le * 5], 4); buf[4] = 0; putstring(" "); putstring(buf); @@ -528,7 +528,7 @@ int main(int argc, char **argv) p = "break case char default else enum if int return sizeof do struct switch while " "EOF EXIT_SUCCESS EXIT_FAILURE NULL " - "malloc free memcpy memset memcmp getchar putstring putnl putchar putint isspace isdigit isalnum isalpha strcmp strdup exit void main"; + "malloc free memcpy memset memcmp getchar putstring putnl putchar putint isspace isdigit isalnum isalpha strcmp strdup strlcpy strlcat exit void main"; i = Break; while (i <= While) { next(); id->tk = i++; } /* add keywords to symbol table */ /* add library constants */ next(); id->class = Num; id->type = INT; id->val = -1; @@ -652,7 +652,7 @@ int main(int argc, char **argv) } while (tk == Mul) { next(); ty = ty + PTR; } if (tk != Id) { error("bad parameter declaration"); } - if (id->class == Loc) { error("duplicate parameter definition"); } + if (id->class == Loc) { /* error("duplicate parameter definition"); */ } id->hclass = id->class; id->class = Loc; id->htype = id->type; id->type = ty; id->hval = id->val; id->val = i++; @@ -660,40 +660,45 @@ int main(int argc, char **argv) if (tk == ',') next(); } next(); - if (tk != '{') { error("bad function definition"); } - loc = ++i; - next(); - while (tk == Int || tk == Char || tk == Struct) { - if (tk == Int) bt = INT; else if (tk == Char) bt = CHAR; else { - next(); - if (tk != Id) { error("bad struct declaration"); } - bt = id->stype; - } + + if (tk == '{') { + /* function body declaration */ + loc = ++i; next(); - while (tk != ';') { - ty = bt; - while (tk == Mul) { next(); ty = ty + PTR; } - if (tk != Id) { error("bad local declaration"); } - if (id->class == Loc) { error("duplicate local definition"); } - id->hclass = id->class; id->class = Loc; - id->htype = id->type; id->type = ty; - id->hval = id->val; id->val = ++i; + while (tk == Int || tk == Char || tk == Struct) { + if (tk == Int) bt = INT; else if (tk == Char) bt = CHAR; else { + next(); + if (tk != Id) { error("bad struct declaration"); } + bt = id->stype; + } + next(); + while (tk != ';') { + ty = bt; + while (tk == Mul) { next(); ty = ty + PTR; } + if (tk != Id) { error("bad local declaration"); } + if (id->class == Loc) { error("duplicate local definition"); } + id->hclass = id->class; id->class = Loc; + id->htype = id->type; id->type = ty; + id->hval = id->val; id->val = ++i; + next(); + if (tk == ',') next(); + } next(); - if (tk == ',') next(); } - next(); - } - *++e = ENT; *++e = i - loc; - while (tk != '}') stmt(); - *++e = LEV; - id = sym; /* unwind symbol table locals */ - while (id->tk) { - if (id->class == Loc) { - id->class = id->hclass; - id->type = id->htype; - id->val = id->hval; + *++e = ENT; *++e = i - loc; + while (tk != '}') stmt(); + *++e = LEV; + id = sym; /* unwind symbol table locals */ + while (id->tk) { + if (id->class == Loc) { + id->class = id->hclass; + id->type = id->htype; + id->val = id->hval; + } + id = id + 1; } - id = id + 1; + } else { + /* forward function declaration */ } } else { @@ -730,7 +735,7 @@ int main(int argc, char **argv) buf = (char *)malloc( 5 ); memcpy(buf, &"LEA ,IMM ,JMP ,JSR ,BZ ,BNZ ,ENT ,ADJ ,LEV ,LI ,LC ,SI ,SC ,PSH ," "OR ,XOR ,AND ,EQ ,NE ,LT ,GT ,LE ,GE ,SHL ,SHR ,ADD ,SUB ,MUL ,DIV ,MOD ," - "MALC,FREE,MCPY,MSET,MCMP,GETC,PUTS,PUTN,PUTC,PUTI,ISPC,IDGT,IANU.IALP,SCMP,SDUP,EXIT,"[i * 5],4); + "MALC,FREE,MCPY,MSET,MCMP,GETC,PUTS,PUTN,PUTC,PUTI,ISPC,IDGT,IANU.IALP,SCMP,SDUP,SLCP,SLCA,EXIT,"[i * 5],4); buf[4] = 0; putstring(buf); free(buf); @@ -789,6 +794,8 @@ int main(int argc, char **argv) case IALP: t = sp + pc[1]; a = isalpha( (int)t[-1]); break; case SCMP: t = sp + pc[1]; a = strcmp((char *)t[-1], (char *)t[-2]); break; case SDUP: t = sp + pc[1]; a = (int)strdup((char *)t[-1]); break; + case SLCP: a = (int)strlcpy((char *)sp[2], (char *)sp[1], *sp); break; + case SLCA: a = (int)strlcat((char *)sp[2], (char *)sp[1], *sp); break; case EXIT: /* putstring("exit("); putint(*sp); putstring(") cycle = "); putint(cycle); putnl(); */ rt = *sp; run = 0; break; default: putstring("unknown instruction = "); putint(i); putstring("! cycle = "); putint(cycle); putnl(); rt = -1; run = 0; break; } diff --git a/miniany/cc.c b/miniany/cc.c index 5cf2f9c..c630a8f 100644 --- a/miniany/cc.c +++ b/miniany/cc.c @@ -1411,11 +1411,13 @@ void parseStatementBlock( struct Compiler *compiler ) parserExpect( parser, S_RBRACE, "}" ); } -void parseFunctionDeclaraion( struct Compiler *compiler ) +void parseFunctionDeclaration( struct Compiler *compiler ) { struct Parser *parser; + struct Symbol *sym; parser = compiler->parser; + if( parser->token == S_IDENT ) { if( strcmp( parser->scanner->ident, "void" ) != 0 ) { scannerPrintErrorHeader( parser->scanner ); @@ -1424,18 +1426,35 @@ void parseFunctionDeclaraion( struct Compiler *compiler ) exit( EXIT_FAILURE ); } } - parser->token = getToken( parser->scanner ); + + parserExpect( parser, S_IDENT, "identifier" ); + sym = getSymbol( parser->global_scope, parser->scanner->ident ); + if( sym == NULL ) { + sym = createSymbol( parser->scanner->ident ); + insertSymbol( parser->global_scope, sym ); + } else { + scannerPrintErrorHeader( parser->scanner ); + putstring( "duplicate global symbol '" ); + putstring( parser->scanner->ident ); + putstring( "'" ); + putnl( ); + exit( EXIT_FAILURE ); + } if( parser->debug ) { putstring( "; function declaration '" ); putstring( parser->scanner->ident ); putstring( "'" ); putnl( ); } + putstring( parser->scanner->ident ); putchar( ':' ); putnl( ); + putstring( "push ebp" ); putnl( ); + putstring( "mov ebp, esp" ); putnl( ); parser->token = getToken( compiler->parser->scanner ); parserExpect( parser, S_LPAREN, "(" ); parserExpect( parser, S_RPAREN, ")" ); parseStatementBlock( compiler ); + putstring( "pop ebp" ); putnl( ); putstring( "ret" ); putnl( ); } @@ -1467,11 +1486,11 @@ int main( int argc, char **argv ) compiler = createCompiler( ); /* compiler->parser->scanner->debug = 1; */ - /* compiler->parser->debug = 1; */ + compiler->parser->debug = 1; /* compiler->generator->debug = 1; */ genPrologue( compiler ); compiler->parser->token = getToken( compiler->parser->scanner ); - parseFunctionDeclaraion( compiler ); + parseFunctionDeclaration( compiler ); genEpilogue( compiler ); freeCompiler( compiler ); diff --git a/miniany/cc.wg b/miniany/cc.wg index 7aca567..41f6c53 100644 --- a/miniany/cc.wg +++ b/miniany/cc.wg @@ -29,14 +29,14 @@ WordGrinder dumpfile v3: this is a text file; diff me! .clipboard.margin: 0 .clipboard.viewmode: 1 .clipboard.wordcount: 19 -.documents.1.co: 11 -.documents.1.cp: 74 +.documents.1.co: 1 +.documents.1.cp: 26 .documents.1.cw: 1 .documents.1.margin: 0 .documents.1.name: "main" .documents.1.sticky_selection: false .documents.1.viewmode: 1 -.documents.1.wordcount: 928 +.documents.1.wordcount: 937 .fileformat: 8 .findtext: "C4" .menu.accelerators.^@: "ZM" @@ -141,7 +141,7 @@ WordGrinder dumpfile v3: this is a text file; diff me! .menu.accelerators.ZU: "UP" .menu.accelerators.ZWL: "^LEFT" .menu.accelerators.ZWR: "^RIGHT" -.name: "/home/abaumann/projects/compilertests/miniany/cc.wg" +.name: "/media/sd/abaumann/projects/compilertests/miniany/cc.wg" .replacetext: "" .statusbar: true .current: 1 @@ -171,7 +171,8 @@ LB standard C block comments along to c++ end of line ones LB negative enum initializers LB do/while loops LB more C functions like isspace, getc, strcmp -LB some simplified functions for printing like putstring, putint, putnl +LB some simplified functions for printing like putstring, putint, putnl replacing printf-like functions +LB BSD-style string functions like strlcpy, strlcat LB strict C89 conformance, mainly use standard comment blocks, also removed some warnings LB some casts around malloc and memset to fit to non-void freestanding-libc LB converted printf to putstring/putint/putnl and some helper functions for error reporting like error() diff --git a/miniany/hello.c b/miniany/hello.c index 062ab5f..67cfe1d 100644 --- a/miniany/hello.c +++ b/miniany/hello.c @@ -1,8 +1,38 @@ #include +int f1(int x); + +int f2(int x) +{ + if(x==1) return 0; + f1(x-1); +} + +int f1(int x) +{ + if(x==1) return 0; + f2(x-1); +} + +int f(int x) +{ + if(x==0) return 0; + if(x==1) return 1; + return f(x-1)+f(x-2); +} + int main() { - putstring("hello, world"); + char *s; + s = (char *)malloc(50); + (void)strlcpy(s,"hello, ",50); + (void)strlcat(s,"world",50); + putstring(s); + putnl(); + free(s); + putint(f(10)); + putnl(); + putint(f1(10)); putnl(); return 0; } -- cgit v1.2.3-54-g00ecf