Skip to content

Commit 5cd18cc

Browse files
committed
Initial commit
0 parents  commit 5cd18cc

File tree

13 files changed

+646
-0
lines changed

13 files changed

+646
-0
lines changed

.gitattributes

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
# Auto detect text files and perform LF normalization
2+
* text=auto

.gitignore

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
# Prerequisites
2+
*.d
3+
4+
# Object files
5+
*.o
6+
*.ko
7+
*.obj
8+
*.elf
9+
10+
# Linker output
11+
*.ilk
12+
*.map
13+
*.exp
14+
15+
# Precompiled Headers
16+
*.gch
17+
*.pch
18+
19+
# Libraries
20+
*.lib
21+
*.a
22+
*.la
23+
*.lo
24+
25+
# Shared objects (inc. Windows DLLs)
26+
*.dll
27+
*.so
28+
*.so.*
29+
*.dylib
30+
31+
# Executables
32+
*.exe
33+
*.out
34+
*.app
35+
*.i*86
36+
*.x86_64
37+
*.hex
38+
39+
# Debug files
40+
*.dSYM/
41+
*.su
42+
*.idb
43+
*.pdb
44+
45+
# Kernel Module Compile Results
46+
*.mod*
47+
*.cmd
48+
.tmp_versions/
49+
modules.order
50+
Module.symvers
51+
Mkfile.old
52+
dkms.conf
53+
54+
.vscode
55+
*.bin

makefile

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
.DEFAULT_GOAL := main.bin
2+
3+
run: main.bin
4+
./main.bin
5+
6+
main.bin: src/*
7+
gcc src/*.c -o main.bin
8+
9+
clean:
10+
mkdir -p build
11+
rm -f build/*

sample.s

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
uint8 test1 = 123;
2+
uint8 test2 = 0xea;
3+
uint8 test3 = 0b01010101;
4+
uint8 test4 = 'a';
5+
uint8* pointer1 = &test1;
6+
uint8 test5 = *pointer1;
7+
8+
uint8 divide (uint8 value, uint8 divisor) {
9+
uint8 i = 0;
10+
while (value > 0) {
11+
value = value - divisor;
12+
i = i + 1;
13+
}
14+
return i;
15+
}
16+
17+
uint8_t main () {
18+
divide(7, 2);
19+
return 0;
20+
}

src/generator.c

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
#include "generator.h"
2+
3+
static int visit(Node*, int);
4+
5+
static char intermediateCode [1024];
6+
static char* codePointer = intermediateCode;
7+
8+
static int registerUse[8] = {0};
9+
static char* registerNames[] = {"rdi", "rsi", "rdx", "rcx", "r8", "r9"};
10+
11+
static int allocReg() {
12+
for (int i = 0; i < sizeof(registerUse)/sizeof(int); i++) {
13+
if (registerUse[i] == 0) {
14+
registerUse[i] = 1;
15+
return i;
16+
}
17+
}
18+
}
19+
20+
static void freeReg(int i) {
21+
registerUse[i] = 0;
22+
}
23+
24+
static void visitAll(NodeListEntry* listRoot, int depth) {
25+
if (listRoot == NULL) return;
26+
NodeListEntry* curEntry = listRoot;
27+
while (curEntry->next != NULL) {
28+
curEntry = curEntry->next;
29+
visit(curEntry->node, depth);
30+
}
31+
}
32+
33+
static void printIndent(int depth) {
34+
for (int i = 0; i < depth; i++) {
35+
printf(" ");
36+
}
37+
}
38+
39+
static int visit(Node* node, int depth) {
40+
printIndent(depth);
41+
switch (node->type) {
42+
case N_VAR_DECL:
43+
// TODO decide symbol location in memory
44+
printf("Variable declaration: %s %s\n", node->VarDecl.symbol->type->name, node->VarDecl.symbol->token->value);
45+
break;
46+
case N_FUNC_DECL:
47+
printf("Function declaration: %s %s\n", node->FunctionDecl.returnType->name, node->token->value);
48+
codePointer += sprintf(codePointer, "LABEL %s\n", node->token->value);
49+
visitAll(node->FunctionDecl.formalParameters, depth+1);
50+
visit(node->FunctionDecl.block, depth+1);
51+
break;
52+
case N_BLOCK:
53+
printf("Block\n");
54+
visitAll(node->Block.variableDeclarations, depth+1);
55+
visitAll(node->Block.statements, depth+1);
56+
break;
57+
case N_NUMBER:
58+
printf("Number: %s\n", node->token->value);
59+
int regN = allocReg();
60+
codePointer += sprintf(codePointer, "COPY %s -> R%d %s\n", node->token->value, regN);
61+
return regN;
62+
case N_VARIABLE:
63+
printf("Variable: %s\n", node->token->value);
64+
int regV = allocReg();
65+
// TODO use symbol location instead of token value
66+
codePointer += sprintf(codePointer, "COPY %s -> R%d\n", node->token->value, regV);
67+
return regV;
68+
case N_ASSIGNMENT:
69+
printf("Assignment: %s\n", node->token->value);
70+
int regA = visit(node->Assignment.expr, depth+1);
71+
codePointer += sprintf(codePointer, "COPY R%d -> %s\n", regA, node->token->value);
72+
break;
73+
case N_BINOP:
74+
printf("BinOp: %s\n", node->token->value);
75+
int regL = visit(node->BinOp.left, depth+1);
76+
int regR = visit(node->BinOp.right, depth+1);
77+
int regRes = allocReg();
78+
codePointer += sprintf(codePointer, "BINOP R%d %s R%d -> R%d\n", regL, node->token->value, regR, regRes);
79+
freeReg(regL);
80+
freeReg(regR);
81+
return regRes;
82+
case N_RETURN:
83+
printf("Return\n");
84+
int reg = visit(node->Return.expr, depth+1);
85+
codePointer += sprintf(codePointer, "RET R%d\n", reg);
86+
return reg;
87+
default:
88+
printf("Unknown node type!\n");
89+
break;
90+
}
91+
92+
return 0;
93+
}
94+
95+
char* generate(Node* rootNode) {
96+
visit(rootNode, 0);
97+
return intermediateCode;
98+
}

src/generator.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
#ifndef _GENERATOR_H
2+
#define _GENERATOR_H
3+
4+
#include <stdlib.h>
5+
#include <stdio.h>
6+
#include "lexer.h"
7+
#include "parser.h"
8+
9+
char* generate(Node*);
10+
11+
#endif

src/lexer.c

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
#include "lexer.h"
2+
3+
static Token* curToken;
4+
5+
static Token* newToken(enum TokenType type) {
6+
Token* token = calloc(1, sizeof(Token));
7+
token->type = type;
8+
return token;
9+
}
10+
11+
static void addToken(enum TokenType type, char* value) {
12+
Token* token = newToken(T_END);
13+
curToken->next = token;
14+
curToken->type = type;
15+
curToken->value = value;
16+
curToken = token;
17+
}
18+
19+
static char next(FILE* fp) {
20+
char c = getc(fp);
21+
return c;
22+
}
23+
24+
static char peek(FILE* fp) {
25+
char c = getc(fp);
26+
ungetc(c, fp);
27+
return c;
28+
}
29+
30+
static int isWhitespace(char c) {
31+
if (c == ' ') return 1;
32+
if (c == '\t') return 1;
33+
return 0;
34+
}
35+
36+
static void checkNumeric(FILE* fp, char c) {
37+
char* value = calloc(32, sizeof(char));
38+
int i = 0;
39+
while(1) {
40+
value[i++] = c;
41+
if (!isdigit(peek(fp))) break;
42+
c = tolower(fgetc(fp));
43+
}
44+
45+
addToken(T_NUMBER, value);
46+
}
47+
48+
static void checkKeyword(FILE* fp, char c) {
49+
char* value = calloc(32, sizeof(char));
50+
int i = 0;
51+
while(1) {
52+
value[i++] = c;
53+
if (!isalnum(peek(fp))) break;
54+
c = tolower(fgetc(fp));
55+
}
56+
57+
if (strcmp(value, "return") == 0) addToken(T_RETURN, value);
58+
else if (strcmp(value, "uint8") == 0) addToken(T_TYPE, value);
59+
else addToken(T_ID, value);
60+
}
61+
62+
Token* lex(FILE* fp) {
63+
Token* firstToken = newToken(T_END);
64+
curToken = firstToken;
65+
66+
while (1) {
67+
char c = next(fp);
68+
69+
if (c == EOF) {addToken(T_END, NULL); break;}
70+
if (isWhitespace(c)) continue;
71+
72+
if (c == '(') {addToken(T_LPAREN, "{"); continue;}
73+
if (c == ')') {addToken(T_RPAREN, "}"); continue;}
74+
if (c == '{') {addToken(T_LBRACE, "{"); continue;}
75+
if (c == '}') {addToken(T_RBRACE, "}"); continue;}
76+
if (c == ',') {addToken(T_COMMA, ","); continue;}
77+
if (c == '+') {addToken(T_PLUS, "+"); continue;}
78+
if (c == '-') {addToken(T_MINUS, "-"); continue;}
79+
if (c == '*') {addToken(T_MUL, "*"); continue;}
80+
if (c == '/') {addToken(T_DIV, "/"); continue;}
81+
if (c == '=') {addToken(T_ASSIGN, "="); continue;}
82+
if (c == ';') {addToken(T_SEMICOLON, ";"); continue;}
83+
84+
if (isdigit(c)) {checkNumeric(fp, c); continue;}
85+
if (isalpha(c)) {checkKeyword(fp, c); continue;}
86+
}
87+
88+
return firstToken;
89+
}

src/lexer.h

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
#ifndef _LEXER_H
2+
#define _LEXER_H
3+
4+
#include <stdlib.h>
5+
#include <stdio.h>
6+
#include <ctype.h>
7+
#include <string.h>
8+
9+
enum TokenType {T_END=0, T_LPAREN, T_RPAREN, T_LBRACE, T_RBRACE, T_COMMA, T_PLUS, T_MINUS, T_MUL, T_DIV, T_ASSIGN, T_NUMBER, T_RETURN, T_ID, T_TYPE, T_SEMICOLON};
10+
11+
typedef struct Token Token;
12+
struct Token {
13+
enum TokenType type;
14+
char *value;
15+
Token *next;
16+
};
17+
18+
Token* lex(FILE*);
19+
20+
#endif

src/main.c

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
#include <stdio.h>
2+
#include "lexer.h"
3+
#include "parser.h"
4+
#include "generator.h"
5+
6+
int main() {
7+
FILE *fp;
8+
fp = fopen("test.s", "r");
9+
10+
Token* firstToken = lex(fp);
11+
12+
Node* rootNode = parse(firstToken);
13+
14+
char* result = generate(rootNode);
15+
printf("%s", result);
16+
17+
return 0;
18+
}

0 commit comments

Comments
 (0)