colored demo
This commit is contained in:
parent
1bcff515b7
commit
e425464aab
5 changed files with 183 additions and 35 deletions
3
.gitignore
vendored
3
.gitignore
vendored
|
@ -3,4 +3,5 @@ cov
|
||||||
*.o
|
*.o
|
||||||
*.s
|
*.s
|
||||||
*.ans
|
*.ans
|
||||||
*.elf
|
*.elf
|
||||||
|
*.html
|
88
boot.c
88
boot.c
|
@ -20,13 +20,10 @@ void exit(int status);
|
||||||
int fprintf(void* file, char* format, ...);
|
int fprintf(void* file, char* format, ...);
|
||||||
int ungetc(int ch, void* file);
|
int ungetc(int ch, void* file);
|
||||||
|
|
||||||
void ungetchar(int ch) {
|
|
||||||
ungetc(ch, stdin);
|
|
||||||
}
|
|
||||||
|
|
||||||
// limitations
|
// limitations
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
|
ECHO_BUFFER_SIZE = 65536,
|
||||||
STRING_TABLE_SIZE = 65536,
|
STRING_TABLE_SIZE = 65536,
|
||||||
STRING_LUT_SIZE = 4096,
|
STRING_LUT_SIZE = 4096,
|
||||||
ID_TABLE_SIZE = 65536,
|
ID_TABLE_SIZE = 65536,
|
||||||
|
@ -35,6 +32,28 @@ enum {
|
||||||
REG_SIZE = 4096,
|
REG_SIZE = 4096,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// hooks
|
||||||
|
|
||||||
|
char echo_buffer[ECHO_BUFFER_SIZE];
|
||||||
|
int echo_size;
|
||||||
|
|
||||||
|
int readchar() {
|
||||||
|
int ch = getchar();
|
||||||
|
if (ch != '\n') {
|
||||||
|
echo_buffer[echo_size++] = ch;
|
||||||
|
} else {
|
||||||
|
echo_buffer[echo_size++] = 0;
|
||||||
|
printf("#@%s\n", echo_buffer);
|
||||||
|
echo_size = 0;
|
||||||
|
}
|
||||||
|
return ch;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ungetchar(int ch) {
|
||||||
|
--echo_size;
|
||||||
|
ungetc(ch, stdin);
|
||||||
|
}
|
||||||
|
|
||||||
// constants
|
// constants
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
|
@ -220,7 +239,7 @@ int is_id_cont(int ch) {
|
||||||
|
|
||||||
int parse_int(int ch) {
|
int parse_int(int ch) {
|
||||||
int num = ch - '0';
|
int num = ch - '0';
|
||||||
while (is_digit(ch = getchar())) {
|
while (is_digit(ch = readchar())) {
|
||||||
num *= 10;
|
num *= 10;
|
||||||
num += ch - '0';
|
num += ch - '0';
|
||||||
}
|
}
|
||||||
|
@ -229,7 +248,7 @@ int parse_int(int ch) {
|
||||||
}
|
}
|
||||||
|
|
||||||
int get_escaped_char() {
|
int get_escaped_char() {
|
||||||
int ch = getchar();
|
int ch = readchar();
|
||||||
if (ch == 'n') return '\n';
|
if (ch == 'n') return '\n';
|
||||||
if (ch == 't') return '\t';
|
if (ch == 't') return '\t';
|
||||||
if (ch == 'r') return '\r';
|
if (ch == 'r') return '\r';
|
||||||
|
@ -252,7 +271,7 @@ int string_lut_size;
|
||||||
int parse_string() {
|
int parse_string() {
|
||||||
int offset = string_offset;
|
int offset = string_offset;
|
||||||
int ch;
|
int ch;
|
||||||
while ((ch = getchar()) != '"') {
|
while ((ch = readchar()) != '"') {
|
||||||
if (ch == -1 || ch == '\n') {
|
if (ch == -1 || ch == '\n') {
|
||||||
fprintf(stderr, "expecting '\"'\n");
|
fprintf(stderr, "expecting '\"'\n");
|
||||||
exit(1);
|
exit(1);
|
||||||
|
@ -292,7 +311,7 @@ int id_lut_size;
|
||||||
int parse_id(int ch) {
|
int parse_id(int ch) {
|
||||||
int offset = id_offset;
|
int offset = id_offset;
|
||||||
id_table[id_offset++] = ch;
|
id_table[id_offset++] = ch;
|
||||||
while (is_id_cont(ch = getchar())) {
|
while (is_id_cont(ch = readchar())) {
|
||||||
id_table[id_offset++] = ch;
|
id_table[id_offset++] = ch;
|
||||||
}
|
}
|
||||||
ungetchar(ch);
|
ungetchar(ch);
|
||||||
|
@ -366,9 +385,9 @@ void next_token() {
|
||||||
token_state = 0;
|
token_state = 0;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
int ch = getchar();
|
int ch = readchar();
|
||||||
while (ch == ' ' || ch == '\t' || ch == '\r' || ch == '\n') {
|
while (ch == ' ' || ch == '\t' || ch == '\r' || ch == '\n') {
|
||||||
ch = getchar();
|
ch = readchar();
|
||||||
}
|
}
|
||||||
if (ch == -1) {
|
if (ch == -1) {
|
||||||
token_type = TOKEN_EOF;
|
token_type = TOKEN_EOF;
|
||||||
|
@ -385,7 +404,7 @@ void next_token() {
|
||||||
} else if (ch == '}') {
|
} else if (ch == '}') {
|
||||||
token_type = TOKEN_BRACE_RIGHT;
|
token_type = TOKEN_BRACE_RIGHT;
|
||||||
} else if (ch == '+') {
|
} else if (ch == '+') {
|
||||||
int ch2 = getchar();
|
int ch2 = readchar();
|
||||||
if (ch2 == '+') {
|
if (ch2 == '+') {
|
||||||
token_type = TOKEN_INC;
|
token_type = TOKEN_INC;
|
||||||
} else if (ch2 == '=') {
|
} else if (ch2 == '=') {
|
||||||
|
@ -395,7 +414,7 @@ void next_token() {
|
||||||
token_type = TOKEN_ADD;
|
token_type = TOKEN_ADD;
|
||||||
}
|
}
|
||||||
} else if (ch == '-') {
|
} else if (ch == '-') {
|
||||||
int ch2 = getchar();
|
int ch2 = readchar();
|
||||||
if (ch2 == '-') {
|
if (ch2 == '-') {
|
||||||
token_type = TOKEN_DEC;
|
token_type = TOKEN_DEC;
|
||||||
} else if (ch2 == '=') {
|
} else if (ch2 == '=') {
|
||||||
|
@ -405,7 +424,7 @@ void next_token() {
|
||||||
token_type = TOKEN_SUB;
|
token_type = TOKEN_SUB;
|
||||||
}
|
}
|
||||||
} else if (ch == '*') {
|
} else if (ch == '*') {
|
||||||
int ch2 = getchar();
|
int ch2 = readchar();
|
||||||
if (ch2 == '=') {
|
if (ch2 == '=') {
|
||||||
token_type = TOKEN_MUL_ASSIGN;
|
token_type = TOKEN_MUL_ASSIGN;
|
||||||
} else {
|
} else {
|
||||||
|
@ -413,22 +432,22 @@ void next_token() {
|
||||||
token_type = TOKEN_MUL;
|
token_type = TOKEN_MUL;
|
||||||
}
|
}
|
||||||
} else if (ch == '/') {
|
} else if (ch == '/') {
|
||||||
int ch2 = getchar();
|
int ch2 = readchar();
|
||||||
if (ch2 == '=') {
|
if (ch2 == '=') {
|
||||||
token_type = TOKEN_DIV_ASSIGN;
|
token_type = TOKEN_DIV_ASSIGN;
|
||||||
} else if (ch2 == '/') {
|
} else if (ch2 == '/') {
|
||||||
do ch = getchar(); while (ch != -1 && ch != '\n');
|
do ch = readchar(); while (ch != -1 && ch != '\n');
|
||||||
next_token();
|
next_token();
|
||||||
return;
|
return;
|
||||||
} else if (ch2 == '*') {
|
} else if (ch2 == '*') {
|
||||||
while (1) {
|
while (1) {
|
||||||
ch = getchar();
|
ch = readchar();
|
||||||
if (ch == -1) {
|
if (ch == -1) {
|
||||||
fprintf(stderr, "expecting '*/'\n");
|
fprintf(stderr, "expecting '*/'\n");
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
if (ch == '*') {
|
if (ch == '*') {
|
||||||
ch = getchar();
|
ch = readchar();
|
||||||
if (ch == '/') {
|
if (ch == '/') {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -441,7 +460,7 @@ void next_token() {
|
||||||
token_type = TOKEN_DIV;
|
token_type = TOKEN_DIV;
|
||||||
}
|
}
|
||||||
} else if (ch == '%') {
|
} else if (ch == '%') {
|
||||||
int ch2 = getchar();
|
int ch2 = readchar();
|
||||||
if (ch2 == '=') {
|
if (ch2 == '=') {
|
||||||
token_type = TOKEN_REM_ASSIGN;
|
token_type = TOKEN_REM_ASSIGN;
|
||||||
} else {
|
} else {
|
||||||
|
@ -457,11 +476,11 @@ void next_token() {
|
||||||
} else if (ch == ',') {
|
} else if (ch == ',') {
|
||||||
token_type = TOKEN_COMMA;
|
token_type = TOKEN_COMMA;
|
||||||
} else if (ch == '<') {
|
} else if (ch == '<') {
|
||||||
int ch2 = getchar();
|
int ch2 = readchar();
|
||||||
if (ch2 == '=') {
|
if (ch2 == '=') {
|
||||||
token_type = TOKEN_LE;
|
token_type = TOKEN_LE;
|
||||||
} else if (ch2 == '<') {
|
} else if (ch2 == '<') {
|
||||||
int ch3 = getchar();
|
int ch3 = readchar();
|
||||||
if (ch3 == '=') {
|
if (ch3 == '=') {
|
||||||
token_type = TOKEN_LSHIFT_ASSIGN;
|
token_type = TOKEN_LSHIFT_ASSIGN;
|
||||||
} else {
|
} else {
|
||||||
|
@ -473,11 +492,11 @@ void next_token() {
|
||||||
token_type = TOKEN_LT;
|
token_type = TOKEN_LT;
|
||||||
}
|
}
|
||||||
} else if (ch == '>') {
|
} else if (ch == '>') {
|
||||||
int ch2 = getchar();
|
int ch2 = readchar();
|
||||||
if (ch2 == '=') {
|
if (ch2 == '=') {
|
||||||
token_type = TOKEN_GE;
|
token_type = TOKEN_GE;
|
||||||
} else if (ch2 == '>') {
|
} else if (ch2 == '>') {
|
||||||
int ch3 = getchar();
|
int ch3 = readchar();
|
||||||
if (ch3 == '=') {
|
if (ch3 == '=') {
|
||||||
token_type = TOKEN_RSHIFT_ASSIGN;
|
token_type = TOKEN_RSHIFT_ASSIGN;
|
||||||
} else {
|
} else {
|
||||||
|
@ -489,7 +508,7 @@ void next_token() {
|
||||||
token_type = TOKEN_GT;
|
token_type = TOKEN_GT;
|
||||||
}
|
}
|
||||||
} else if (ch == '=') {
|
} else if (ch == '=') {
|
||||||
int ch2 = getchar();
|
int ch2 = readchar();
|
||||||
if (ch2 == '=') {
|
if (ch2 == '=') {
|
||||||
token_type = TOKEN_EQ;
|
token_type = TOKEN_EQ;
|
||||||
} else {
|
} else {
|
||||||
|
@ -497,7 +516,7 @@ void next_token() {
|
||||||
token_type = TOKEN_ASSIGN;
|
token_type = TOKEN_ASSIGN;
|
||||||
}
|
}
|
||||||
} else if (ch == '!') {
|
} else if (ch == '!') {
|
||||||
int ch2 = getchar();
|
int ch2 = readchar();
|
||||||
if (ch2 == '=') {
|
if (ch2 == '=') {
|
||||||
token_type = TOKEN_NE;
|
token_type = TOKEN_NE;
|
||||||
} else {
|
} else {
|
||||||
|
@ -505,7 +524,7 @@ void next_token() {
|
||||||
token_type = TOKEN_NOT;
|
token_type = TOKEN_NOT;
|
||||||
}
|
}
|
||||||
} else if (ch == '&') {
|
} else if (ch == '&') {
|
||||||
int ch2 = getchar();
|
int ch2 = readchar();
|
||||||
if (ch2 == '=') {
|
if (ch2 == '=') {
|
||||||
token_type = TOKEN_AND_ASSIGN;
|
token_type = TOKEN_AND_ASSIGN;
|
||||||
} else if (ch2 == '&') {
|
} else if (ch2 == '&') {
|
||||||
|
@ -515,7 +534,7 @@ void next_token() {
|
||||||
token_type = TOKEN_AND;
|
token_type = TOKEN_AND;
|
||||||
}
|
}
|
||||||
} else if (ch == '|') {
|
} else if (ch == '|') {
|
||||||
int ch2 = getchar();
|
int ch2 = readchar();
|
||||||
if (ch2 == '=') {
|
if (ch2 == '=') {
|
||||||
token_type = TOKEN_OR_ASSIGN;
|
token_type = TOKEN_OR_ASSIGN;
|
||||||
} else if (ch2 == '|') {
|
} else if (ch2 == '|') {
|
||||||
|
@ -525,7 +544,7 @@ void next_token() {
|
||||||
token_type = TOKEN_OR;
|
token_type = TOKEN_OR;
|
||||||
}
|
}
|
||||||
} else if (ch == '^') {
|
} else if (ch == '^') {
|
||||||
int ch2 = getchar();
|
int ch2 = readchar();
|
||||||
if (ch2 == '=') {
|
if (ch2 == '=') {
|
||||||
token_type = TOKEN_XOR_ASSIGN;
|
token_type = TOKEN_XOR_ASSIGN;
|
||||||
} else {
|
} else {
|
||||||
|
@ -536,11 +555,11 @@ void next_token() {
|
||||||
token_type = TOKEN_INV;
|
token_type = TOKEN_INV;
|
||||||
} else if (ch == '\'') {
|
} else if (ch == '\'') {
|
||||||
token_type = TOKEN_NUMBER;
|
token_type = TOKEN_NUMBER;
|
||||||
token_data = getchar();
|
token_data = readchar();
|
||||||
if (token_data == '\\') {
|
if (token_data == '\\') {
|
||||||
token_data = get_escaped_char();
|
token_data = get_escaped_char();
|
||||||
}
|
}
|
||||||
if (getchar() != '\'') {
|
if (readchar() != '\'') {
|
||||||
fprintf(stderr, "expecting '\n");
|
fprintf(stderr, "expecting '\n");
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
@ -550,8 +569,8 @@ void next_token() {
|
||||||
dedup_string();
|
dedup_string();
|
||||||
} else if (ch == '.') {
|
} else if (ch == '.') {
|
||||||
token_type = 0;
|
token_type = 0;
|
||||||
if (getchar() == '.') {
|
if (readchar() == '.') {
|
||||||
if (getchar() == '.') {
|
if (readchar() == '.') {
|
||||||
token_type = TOKEN_ELLIPSIS;
|
token_type = TOKEN_ELLIPSIS;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -826,7 +845,7 @@ void load(int rd, int rs) {
|
||||||
}
|
}
|
||||||
rs = rd;
|
rs = rd;
|
||||||
}
|
}
|
||||||
printf(" %s %s, 0(%s) # load non-trivial register\n", op, rd_name, reg_name(rs));
|
printf(" %s %s, 0(%s)\n", op, rd_name, reg_name(rs));
|
||||||
}
|
}
|
||||||
|
|
||||||
// store a trivial register into a non-trivial one
|
// store a trivial register into a non-trivial one
|
||||||
|
@ -839,7 +858,7 @@ void store(char* rs, int reg) {
|
||||||
}
|
}
|
||||||
reg = REG_T2;
|
reg = REG_T2;
|
||||||
}
|
}
|
||||||
printf(" %s %s, 0(%s) # store non-trivial register\n", op, rs, reg_name(reg));
|
printf(" %s %s, 0(%s)\n", op, rs, reg_name(reg));
|
||||||
}
|
}
|
||||||
|
|
||||||
int is_nontrivial(int reg) {
|
int is_nontrivial(int reg) {
|
||||||
|
@ -972,7 +991,7 @@ int lookup(int id) {
|
||||||
char* name = id_table + id_lut[id];
|
char* name = id_table + id_lut[id];
|
||||||
if (global_kind[id]) {
|
if (global_kind[id]) {
|
||||||
if (global_kind[id] == KIND_FUNCTION) {
|
if (global_kind[id] == KIND_FUNCTION) {
|
||||||
fprintf(stderr, "function name must not appear outside function call: %s\n", name);
|
fprintf(stderr, "function name can only be directly called: %s\n", name);
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
int rd = next_reg(TYPE_VOID_PTR);
|
int rd = next_reg(TYPE_VOID_PTR);
|
||||||
|
@ -1974,6 +1993,7 @@ void parse_top_level() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void dump_string_table() {
|
void dump_string_table() {
|
||||||
|
printf("# string table: \n");
|
||||||
printf(".data\n");
|
printf(".data\n");
|
||||||
for (int i = 0; i < string_lut_size; ++i) {
|
for (int i = 0; i < string_lut_size; ++i) {
|
||||||
printf(".LC%d: .string \"", i);
|
printf(".LC%d: .string \"", i);
|
||||||
|
|
4
compile.sh
Normal file
4
compile.sh
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
gcc boot.c -o boot.elf &&
|
||||||
|
./boot.elf < $1 > $1.s
|
||||||
|
python3 transcript.py < $1.s > $1.html
|
||||||
|
rm boot.elf
|
9
demo/for.c
Normal file
9
demo/for.c
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
int printf(char* format, ...);
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
int i;
|
||||||
|
for (i = 0;
|
||||||
|
i < 10;
|
||||||
|
++i)
|
||||||
|
printf("hello %d\n", i);
|
||||||
|
}
|
114
transcript.py
Normal file
114
transcript.py
Normal file
|
@ -0,0 +1,114 @@
|
||||||
|
import sys
|
||||||
|
import html
|
||||||
|
|
||||||
|
src = ''
|
||||||
|
asm = ''
|
||||||
|
style = 0
|
||||||
|
flip = False
|
||||||
|
|
||||||
|
def decorate(line):
|
||||||
|
return f'<span class="style{style}">{html.escape(line)}</span>'
|
||||||
|
|
||||||
|
for line in sys.stdin:
|
||||||
|
if line.startswith("#@"):
|
||||||
|
line = line.removeprefix("#@")
|
||||||
|
src += decorate(line) if flip else line
|
||||||
|
style += 1
|
||||||
|
style %= 5
|
||||||
|
flip = False
|
||||||
|
elif line.startswith("# string table: "):
|
||||||
|
asm += line
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
asm += decorate(line)
|
||||||
|
flip = True
|
||||||
|
|
||||||
|
for line in sys.stdin:
|
||||||
|
asm += line
|
||||||
|
|
||||||
|
title = 'RVBTCC Code Gen Demo'
|
||||||
|
|
||||||
|
|
||||||
|
template = '''
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<title><%title%></title>
|
||||||
|
<style>
|
||||||
|
body {
|
||||||
|
font-family: Arial, sans-serif;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
header {
|
||||||
|
background-color: #4CAF50;
|
||||||
|
color: white;
|
||||||
|
padding: 1em;
|
||||||
|
text-align: center;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
.container {
|
||||||
|
display: flex;
|
||||||
|
width: 80%;
|
||||||
|
margin: 2em 0;
|
||||||
|
}
|
||||||
|
.column {
|
||||||
|
flex: 1;
|
||||||
|
margin: 0 1em;
|
||||||
|
}
|
||||||
|
pre {
|
||||||
|
background-color: #f4f4f4;
|
||||||
|
padding: 1em;
|
||||||
|
border: 1px solid #ddd;
|
||||||
|
overflow-x: auto;
|
||||||
|
}
|
||||||
|
code {
|
||||||
|
font-family: 'Consolas', Consolas, monospace;
|
||||||
|
font-size: 20px;
|
||||||
|
}
|
||||||
|
.style0 {
|
||||||
|
background-color: rgba(255,129,130,0.4);
|
||||||
|
}
|
||||||
|
.style1 {
|
||||||
|
background-color: rgba(212,167,44,0.4);
|
||||||
|
}
|
||||||
|
.style2 {
|
||||||
|
background-color: rgba(74,194,107,0.4);
|
||||||
|
}
|
||||||
|
.style3 {
|
||||||
|
background-color: rgba(84,174,255,0.4);
|
||||||
|
}
|
||||||
|
.style4 {
|
||||||
|
background-color: rgba(194,151,255,0.4);
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<header>
|
||||||
|
<h1><%title%></h1>
|
||||||
|
</header>
|
||||||
|
<div class="container">
|
||||||
|
<div class="column">
|
||||||
|
<h2>Source Code</h2>
|
||||||
|
<pre>
|
||||||
|
<code><%src%></code>
|
||||||
|
</pre>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="column">
|
||||||
|
<h2>Assembly</h2>
|
||||||
|
<pre>
|
||||||
|
<code><%asm%></code>
|
||||||
|
</pre>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
'''
|
||||||
|
|
||||||
|
print(template.replace("<%title%>", title).replace("<%src%>", src).replace("<%asm%>", asm))
|
Loading…
Add table
Add a link
Reference in a new issue