From b0c6943121f186c79d2152694d209f82904ff1e1 Mon Sep 17 00:00:00 2001 From: Andreas Baumann Date: Thu, 30 Sep 2021 17:03:17 +0200 Subject: cc: rearanged for a pseudo-main --- miniany/Makefile | 3 +++ miniany/README.html | 11 +++++--- miniany/build.sh | 3 +++ miniany/cc.c | 77 ++++++++++++++++++++++++++++++++++++----------------- miniany/cc.wg | 13 +++++---- miniany/test1.c | 1 + 6 files changed, 75 insertions(+), 33 deletions(-) diff --git a/miniany/Makefile b/miniany/Makefile index 7ebaf6c..38d36e8 100644 --- a/miniany/Makefile +++ b/miniany/Makefile @@ -11,4 +11,7 @@ README.html: cc.md cc.md: cc.wg wordgrinder -c cc.wg cc.md sed -i 's/`/\n```\n/g' cc.md + sed -i 's/\\/>/g' cc.md + \ No newline at end of file diff --git a/miniany/README.html b/miniany/README.html index 40c9c49..9b7fcbf 100644 --- a/miniany/README.html +++ b/miniany/README.html @@ -38,7 +38,7 @@

Compiled in either hosted (host libc) or freestanding (our own libc, currently IA-32 Linux kernel only syscalls):

./build.sh cc hostcc hosted d
 ./build.sh cc hostcc freestanding d
-./cc \< test1.c \> test1.asm
+./cc < test1.c > test1.asm
 

Create a plain binary from the assembly code:

fasm test1.asm test1.bin
@@ -54,12 +54,12 @@
 

Here again you can choose the host compiler for compiling C4.

Then we have to create the standard input for C4 using:

-
echo -n -e "\034" \> EOF
+
echo -n -e "\034" > EOF
 cat cc.c EOF hello.c | ./c4
 cat c4.c EOF cc.c EOF hello.c | ./c4
 cat c4.c4 EOF c4.c EOF cc.c EOF hello.c | ./c4
 
-

EOF contains the traditional FS (file separator) character in the ASCII character set. Every time c4/c4.c is invoked it reads exacly one input file up to the first FS character (or stops at the end of stdin).

+

EOF contains the traditional FS (file separator) character in the ASCII character set. Every time c4 is invoked it reads exacly one input file up to the first FS character (or stops at the end of stdin).

We can also use -s, or -d on every level as follows:

cat cc.c EOF hello.c | ./c4 -d
 
@@ -89,3 +89,8 @@ cat c4.c4 EOF c4.c EOF cc.c EOF hello.c | ./c4
  • https://github.com/felipensp/assembly/blob/master/x86/itoa.s, for putint (early debugging keyword)
  • https://baptiste-wicht.com/posts/2011/11/print-strings-integers-intel-assembly.htm (earldy debugging keyword)
  • +

    Documentation:

    + diff --git a/miniany/build.sh b/miniany/build.sh index 5891613..7944eaf 100755 --- a/miniany/build.sh +++ b/miniany/build.sh @@ -78,6 +78,9 @@ case "${COMPILER}:${MODE}" in pcc:hosted) CFLAGS+=" -Wl,-emain" ;; +esac + +case "${COMPILER}:${MODE}" in *:hosted) CFLAGS+=" -lbsd" ;; diff --git a/miniany/cc.c b/miniany/cc.c index cef1af2..5cf2f9c 100644 --- a/miniany/cc.c +++ b/miniany/cc.c @@ -487,6 +487,7 @@ struct Parser { int token; struct Scanner *scanner; struct Scope *global_scope; + int debug; }; struct Generator { @@ -940,6 +941,10 @@ int generateFromAST( struct Generator *generator, struct ASTnode *node, int inre void genPrologue( struct Compiler *compiler ) { + if( compiler->parser->debug ) { + putstring( "; prologue" ); + putnl( ); + } putstring( "format binary" ); putnl( ); putstring( "use32" ); putnl( ); putstring( "org $1000000" ); putnl( ); @@ -968,15 +973,19 @@ void genPrologue( struct Compiler *compiler ) putstring( "mov edx, 11" ); putnl( ); putstring( "int 0x80" ); putnl( ); putstring( "ret" ); putnl( ); - putstring( "_start:" ); putnl( ); } void genEpilogue( struct Compiler *compiler ) { struct Symbol *sym; - putstring( "hlt" ); - putnl( ); + if( compiler->parser->debug ) { + putstring( "; entry point" ); + putnl( ); + } + putstring( "_start:" ); putnl( ); + putstring( "call main" ); putnl( ); + putstring( "hlt" ); putnl( ); sym = compiler->parser->global_scope->sym; while( sym != NULL ) { genAddGlob( compiler->generator, sym->name ); @@ -995,6 +1004,7 @@ struct Parser *createParser( ) parser = (struct Parser *)malloc( sizeof( struct Parser ) ); parser->scanner = createScanner( ); parser->global_scope = createScope( "global" ); + parser->debug = 0; return parser; } @@ -1269,22 +1279,22 @@ void parseIf( struct Compiler *compiler ) parserExpect( parser, S_IF, "if" ); parserExpect( parser, S_LPAREN, "(" ); node = parseExpression( parser, 0 ); - if( compiler->generator->debug ) { + if( parser->debug ) { putstring( "; if then" ); putnl( ); } generateFromAST( compiler->generator, node, NOREG ); /* TODO: this should be condensed and optimized for the normal path * (rare ifs, invert the condition, jmpXX directly */ putstring( "cmp al, 0" ); putnl( ); + genFreeAllRegs( compiler->generator ); label1 = genGetLabel( compiler, compiler->parser->global_scope ); putstring( "je " ); putstring( label1 ); putnl( ); - genFreeAllRegs( compiler->generator ); parserExpect( parser, S_RPAREN, ")" ); parseStatementBlock( compiler ); if( parser->token == S_ELSE ) { label2 = genGetLabel( compiler, compiler->parser->global_scope ); putstring( "jmp " ); putstring( label2 ); putnl( ); - if( compiler->generator->debug ) { + if( parser->debug ) { putstring( "; else" ); putnl( ); } putstring( label1 ); putchar( ':' ); putnl( ); @@ -1296,7 +1306,7 @@ void parseIf( struct Compiler *compiler ) putstring( label1 ); putchar( ':' ); putnl( ); } - if( compiler->generator->debug ) { + if( parser->debug ) { putstring( "; fi" ); putnl( ); } free( label1 ); @@ -1313,21 +1323,21 @@ void parseWhile( struct Compiler *compiler ) parserExpect( parser, S_WHILE, "while" ); parserExpect( parser, S_LPAREN, "(" ); node = parseExpression( parser, 0 ); - if( compiler->generator->debug ) { + if( parser->debug ) { putstring( "; while " ); putnl( ); } label2 = genGetLabel( compiler, compiler->parser->global_scope ); putstring( label2 ); putchar( ':' ); putnl( ); generateFromAST( compiler->generator, node, NOREG ); putstring( "cmp al, 0" ); putnl( ); + genFreeAllRegs( compiler->generator ); label1 = genGetLabel( compiler, compiler->parser->global_scope ); putstring( "je " ); putstring( label1 ); putnl( ); - genFreeAllRegs( compiler->generator ); parserExpect( parser, S_RPAREN, ")" ); parseStatementBlock( compiler ); putstring( "jmp " ); putstring( label2 ); putnl( ); putstring( label1 ); putchar( ':' ); putnl( ); - if( compiler->generator->debug ) { + if( parser->debug ) { putstring( "; fi" ); putnl( ); } free( label2 ); @@ -1342,7 +1352,7 @@ void parseDo( struct Compiler *compiler ) parser = compiler->parser; parserExpect( parser, S_DO, "do" ); - if( compiler->generator->debug ) { + if( parser->debug ) { putstring( "; do" ); putnl( ); } label1 = genGetLabel( compiler, compiler->parser->global_scope ); @@ -1353,25 +1363,13 @@ void parseDo( struct Compiler *compiler ) node = parseExpression( parser, 0 ); generateFromAST( compiler->generator, node, NOREG ); putstring( "cmp al, 0" ); putnl( ); - putstring( "jne " ); putstring( label1 ); putnl( ); genFreeAllRegs( compiler->generator ); + putstring( "jne " ); putstring( label1 ); putnl( ); parserExpect( parser, S_RPAREN, ")" ); parserExpect( parser, S_SEMICOLON, ";" ); free( label1 ); } -/* - - - putstring( "jmp " ); putstring( label2 ); putnl( ); - putstring( label1 ); putchar( ':' ); putnl( ); - if( compiler->generator->debug ) { - putstring( "; fi" ); putnl( ); - } - free( label2 ); - free( label1 ); -} - */ void parseStatement( struct Compiler *compiler ) { struct Parser *parser; @@ -1413,6 +1411,34 @@ void parseStatementBlock( struct Compiler *compiler ) parserExpect( parser, S_RBRACE, "}" ); } +void parseFunctionDeclaraion( struct Compiler *compiler ) +{ + struct Parser *parser; + + parser = compiler->parser; + if( parser->token == S_IDENT ) { + if( strcmp( parser->scanner->ident, "void" ) != 0 ) { + scannerPrintErrorHeader( parser->scanner ); + putstring( "expected void as return value of a function declaration" ); + putnl( ); + exit( EXIT_FAILURE ); + } + } + parser->token = getToken( parser->scanner ); + if( parser->debug ) { + putstring( "; function declaration '" ); + putstring( parser->scanner->ident ); + putstring( "'" ); + putnl( ); + } + putstring( parser->scanner->ident ); putchar( ':' ); putnl( ); + parser->token = getToken( compiler->parser->scanner ); + parserExpect( parser, S_LPAREN, "(" ); + parserExpect( parser, S_RPAREN, ")" ); + parseStatementBlock( compiler ); + putstring( "ret" ); putnl( ); +} + /* compiler */ struct Compiler *createCompiler( ) @@ -1441,10 +1467,11 @@ int main( int argc, char **argv ) compiler = createCompiler( ); /* compiler->parser->scanner->debug = 1; */ + /* compiler->parser->debug = 1; */ /* compiler->generator->debug = 1; */ genPrologue( compiler ); compiler->parser->token = getToken( compiler->parser->scanner ); - parseStatementBlock( compiler ); + parseFunctionDeclaraion( compiler ); genEpilogue( compiler ); freeCompiler( compiler ); diff --git a/miniany/cc.wg b/miniany/cc.wg index dbf56a9..7aca567 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: 10 -.documents.1.cp: 39 -.documents.1.cw: 5 +.documents.1.co: 11 +.documents.1.cp: 74 +.documents.1.cw: 1 .documents.1.margin: 0 .documents.1.name: "main" .documents.1.sticky_selection: false .documents.1.viewmode: 1 -.documents.1.wordcount: 910 +.documents.1.wordcount: 928 .fileformat: 8 .findtext: "C4" .menu.accelerators.^@: "ZM" @@ -199,7 +199,7 @@ PRE echo -n -e "\034" > EOF PRE cat cc.c EOF hello.c | ./c4 PRE cat c4.c EOF cc.c EOF hello.c | ./c4 PRE cat c4.c4 EOF c4.c EOF cc.c EOF hello.c | ./c4 -P EOF contains the traditional FS (file separator) character in the ASCII character set. Every time c4/c4.c is invoked it reads exacly one input file up to the first FS character (or stops at the end of stdin). +P EOF contains the traditional FS (file separator) character in the ASCII character set. Every time c4 is invoked it reads exacly one input file up to the first FS character (or stops at the end of stdin). P We can also use -s, or -d on every level as follows: PRE cat cc.c EOF hello.c | ./c4 -d H2 References @@ -220,4 +220,7 @@ LB https://github.com/rswier/swieros.git: c.c in swieros, Robert Swierczek P Assembly: LB https://github.com/felipensp/assembly/blob/master/x86/itoa.s, for putint (early debugging keyword) LB https://baptiste-wicht.com/posts/2011/11/print-strings-integers-intel-assembly.htm (earldy debugging keyword) +P Documentation: +LB http://cowlark.com/wordgrinder/index.html: the fabulous editor which just does what it should do +LB https://github.com/mity/md4c: markdown to HTML in C . diff --git a/miniany/test1.c b/miniany/test1.c index 4bf86e3..9c971ca 100644 --- a/miniany/test1.c +++ b/miniany/test1.c @@ -1,5 +1,6 @@ /* test1 */ +void main( ) { int i; int j; -- cgit v1.2.3-54-g00ecf