-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathbf2llvm.c
103 lines (94 loc) · 3.39 KB
/
bf2llvm.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
/*
* Brainf**k -> LLVM IR Compiler
* $ gcc bf2llvm.c -o bf2llvm
* $ echo "+++++++++[>++++++++>+++++++++++>+++++<<<-]>.>++.+++++++..+++.\
>-.------------.<++++++++.--------.+++.------.--------.>+." | \
./bf2llvm | opt -S -O3 | lli
*/
#include <stdio.h>
#include <stdlib.h>
void emit_header() {
printf("define i32 @main() {\n");
printf(" %%data = alloca i8*, align 8\n");
printf(" %%ptr = alloca i8*, align 8\n");
printf(" %%data_ptr = call i8* @calloc(i64 30000, i64 1)\n");
printf(" store i8* %%data_ptr, i8** %%data, align 8\n");
printf(" store i8* %%data_ptr, i8** %%ptr, align 8\n");
}
int idx = 1;
void emit_move_ptr(int diff) {
printf(" %%%d = load i8*, i8** %%ptr, align 8\n", idx);
printf(" %%%d = getelementptr inbounds i8, i8* %%%d, i32 %d\n", idx + 1, idx, diff);
printf(" store i8* %%%d, i8** %%ptr, align 8\n", idx + 1);
idx += 2;
}
void emit_add(int diff) {
printf(" %%%d = load i8*, i8** %%ptr, align 8\n", idx);
printf(" %%%d = load i8, i8* %%%d, align 1\n", idx + 1, idx);
printf(" %%%d = add i8 %%%d, %d\n", idx + 2, idx + 1, diff);
printf(" store i8 %%%d, i8* %%%d, align 1\n", idx + 2, idx);
idx += 3;
}
void emit_put() {
printf(" %%%d = load i8*, i8** %%ptr, align 8\n", idx);
printf(" %%%d = load i8, i8* %%%d, align 1\n", idx + 1, idx);
printf(" %%%d = sext i8 %%%d to i32\n", idx + 2, idx + 1);
printf(" %%%d = call i32 @putchar(i32 %%%d)\n", idx + 3, idx + 2);
idx += 4;
}
void emit_get() {
printf(" %%%d = call i32 @getchar()\n", idx);
printf(" %%%d = trunc i32 %%%d to i8\n", idx + 1, idx);
printf(" %%%d = load i8*, i8** %%ptr, align 8\n", idx + 2);
printf(" store i8 %%%d, i8* %%%d, align 1\n", idx + 1, idx + 2);
idx += 3;
}
void emit_while_start(int while_index) {
printf(" br label %%while_cond%d\n", while_index);
printf("while_cond%d:\n", while_index);
printf(" %%%d = load i8*, i8** %%ptr, align 8\n", idx);
printf(" %%%d = load i8, i8* %%%d, align 1\n", idx + 1, idx);
printf(" %%%d = icmp ne i8 %%%d, 0\n", idx + 2, idx + 1);
printf(" br i1 %%%d, label %%while_body%d, label %%while_end%d\n", idx + 2, while_index, while_index);
printf("while_body%d:\n", while_index);
idx += 3;
}
void emit_while_end(int while_index) {
printf(" br label %%while_cond%d\n", while_index);
printf("while_end%d:\n", while_index);
}
void emit_footer() {
printf(" %%%d = load i8*, i8** %%data, align 8\n", idx);
printf(" call void @free(i8* %%%d)\n", idx);
printf(" ret i32 0\n");
printf("}\n\n");
printf("declare i8* @calloc(i64, i64)\n\n");
printf("declare void @free(i8*)\n\n");
printf("declare i32 @putchar(i32)\n\n");
printf("declare i32 @getchar()\n");
}
int main() {
char c;
int while_index = 0;
int while_indices[1000];
int* while_index_ptr = while_indices;
emit_header();
while ((c = getchar()) != EOF) {
switch (c) {
case '>': emit_move_ptr(1); break;
case '<': emit_move_ptr(-1); break;
case '+': emit_add(1); break;
case '-': emit_add(-1); break;
case '[': emit_while_start(*while_index_ptr++ = while_index++); break;
case ']': if (--while_index_ptr < while_indices) {
fprintf(stderr, "unmatching ]\n");
return 1;
}
emit_while_end(*while_index_ptr); break;
case '.': emit_put(); break;
case ',': emit_get(); break;
}
}
emit_footer();
return 0;
}