summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndreas Baumann <mail@andreasbaumann.cc>2021-10-01 21:10:36 +0200
committerAndreas Baumann <mail@andreasbaumann.cc>2021-10-01 21:10:36 +0200
commit7f32ad51b0f08446d7f66e5403d69299d0d60021 (patch)
tree647f786b8f31bdc46b296f9b4b9d40c0375b583d
parentb0c6943121f186c79d2152694d209f82904ff1e1 (diff)
downloadcompilertests-7f32ad51b0f08446d7f66e5403d69299d0d60021.tar.gz
compilertests-7f32ad51b0f08446d7f66e5403d69299d0d60021.tar.bz2
c4: added strl* functions
cc: started peudo function parsing, currently for void main() only some philosophical thinking and testing around forward function declarations
-rw-r--r--miniany/README.html3
-rw-r--r--miniany/REQUIREMENTS10
-rw-r--r--miniany/c4.c77
-rw-r--r--miniany/cc.c27
-rw-r--r--miniany/cc.wg11
-rw-r--r--miniany/hello.c32
6 files changed, 113 insertions, 47 deletions
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 @@
<li>negative enum initializers</li>
<li>do/while loops</li>
<li>more C functions like <i>isspace</i>, <i>getc</i>, <i>strcmp</i></li>
-<li>some simplified functions for printing like <i>putstring</i>, <i>putint</i>, <i>putnl</i></li>
+<li>some simplified functions for printing like <i>putstring</i>, <i>putint</i>, <i>putnl </i>replacing printf-like functions</li>
+<li>BSD-style string functions like <i>strlcpy</i>, <i>strlcat</i></li>
<li>strict C89 conformance, mainly use standard comment blocks, also removed some warnings</li>
<li>some casts around malloc and memset to fit to non-void freestanding-libc</li>
<li>converted printf to putstring/putint/putnl and some helper functions for error reporting like error()</li>
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 <stdio.h>
+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;
}