Compare commits

..

No commits in common. "main" and "regalloc" have entirely different histories.

93 changed files with 563 additions and 1158 deletions

4
.gitignore vendored
View File

@ -1,6 +1,4 @@
build build
cov *.out
*.o *.o
*.s *.s
*.ans
*.elf

133
README.md
View File

@ -1,34 +1,47 @@
# RVBTCC # RVBTCC
2000 行的轻量级自举编译器。 - 约 1900 行的轻量级自举编译器。
- 编译器和自举编译器行为一致。
- 旨在展示如何迅速编写一个自举编译器。
- 语法类似 C输出 RISC-V 汇编。 - 语法类似 C输出 RISC-V 汇编。
- 依赖几个 glibc 函数用于输入输出。 - 依赖几个 libc 函数用于输入输出。
- 仅作学习用途,请勿在生产环境中使用 - 不使用动态内存分配,嵌入式友好
## 用法 ## 用法
如果你有 RISC-V 真机,可以采用真机运行,否则可以考虑模拟运行。两者行为应当是一致的。 如果你有 RISC-V 真机,可以采用真机运行,否则可以考虑模拟运行。两者行为应当是一致的。
如果是模拟运行,则需要安装以下依赖: ### 真机运行
编译运行程序src 为本语言源代码。可以编译 demo 文件夹下的实例。
```sh ```sh
sudo apt install gcc-12-riscv64-linux-gnu qemu-user qemu-system-misc $ sh run-native.sh <src>
```
如果是真机运行,则可以跳过这一步。
编译运行程序src 为本语言源代码。可以编译 demo 或 test 文件夹下的实例。
```sh
$ bash run.sh <src>
``` ```
自举编译器,输出的文件位于 build 文件夹中。 自举编译器,输出的文件位于 build 文件夹中。
```sh ```sh
$ bash boot.sh $ sh boot-native.sh
```
### 模拟运行
安装以下依赖
```sh
sudo apt install gcc-12-riscv64-linux-gnu qemu-user qemu-system-misc
```
编译运行程序src 为本语言源代码。可以编译 demo 文件夹下的实例。
```sh
$ sh run.sh <src>
```
自举编译器,输出的文件位于 build 文件夹中。
```sh
$ sh boot.sh
``` ```
### 自举过程 ### 自举过程
@ -36,14 +49,14 @@ $ bash boot.sh
自举会输出六个文件,三个汇编文件和三个可执行文件: 自举会输出六个文件,三个汇编文件和三个可执行文件:
| 源代码 | 编译器 | 汇编 | 可执行 | 代号 | 命名 | | 源代码 | 编译器 | 汇编 | 可执行 | 代号 | 命名 |
| ------ | --------- | ------- | --------- | ---- | ---------------------- | | ----------------- | --------- | ------- | --------- | ---- | ---------------------- |
| boot.c | gcc | | gcc.elf | G | 自制编译器 | | boot.c boot-lib.c | gcc | | gcc.out | G | 自制编译器 |
| boot.c | gcc.elf | boot1.s | boot1.elf | B1 | 自举自制编译器 | | boot.c boot-lib.h | gcc.out | boot1.s | boot1.out | B1 | 自举自制编译器 |
| boot.c | boot1.elf | boot2.s | boot2.elf | B2 | 自举自举自制编译器 | | boot.c boot-lib.h | boot1.out | boot2.s | boot2.out | B2 | 自举自举自制编译器 |
| boot.c | boot2.elf | boot3.s | | B3 | 验证自举自举自制编译器 | | boot.c boot-lib.h | boot2.out | boot3.s | | B3 | 验证自举自举自制编译器 |
除了第一次编译全程由 gcc 完成之外,另外三次编译从源码到汇编由本编译器完成,从汇编到可执行文件由 gcc 完成。从汇编到可执行文件时需要将 glibc 链接进去,这对于 gcc 来说是默认的行为 后三次编译时boot-lib.h 的内容被手动导入 boot.c 开头进行编译boot-lib.c 提供的库通过链接引入
整个自举及其验证的过程如下图所示: 整个自举及其验证的过程如下图所示:
@ -82,26 +95,23 @@ $ bash boot.sh
### 关键字 ### 关键字
本语言包含的关键字即为支持的标量类型的关键字和流程控制的关键字,还有 `extern` 和 `enum`。 本语言包含的关键字即为支持的标量类型的关键字和流程控制的关键字,还有 `const`。
#### `extern` 关键字 #### `const` 关键字
`extern` 在全局函数和变量的声明的开头中可以使用 `const` 关键字可以在类型中使用,在大部分情况下会被直接忽略。支持它是为了更好兼容 C 程序
全局函数的声明和定义都会直接忽略这个关键字。全局函数的声明和定义由是否提供函数体决定,与该关键字无关。 但是当在出现
全局变量如果使用了这个关键字,则有以下特性和限制: - 全局,标量(即不是数组)
- 类型为 `const int``const int const`
- 带有初始化
- 变量仅被声明,而没有被定义。 的声明时,将会被解析为整数常量。
- 如果需要使用这样的变量,需要稍后提供定义,或在外部已经定义。
- 不可以初始化。
- 不可是数组。
#### `enum` 关键字 整数常量在使用的时候会被直接替换为对应的右值,失去作为全局变量左值的性质。
用于定义整数常量。enum 的名字必须省略,因此不能用于定义枚举类型。 使用 `int const``int` 可以避免这样的特殊处理。
整数常量可以用于数组大小、全局变量初始化等需要常量的地方。
### 支持以下运算符 ### 支持以下运算符
@ -132,13 +142,12 @@ $ bash boot.sh
### 其它支持与不支持 ### 其它支持与不支持
- 不允许在一个声明中声明多个变量或函数(如 `int a, b;`)请写成多个声明。
- 支持全局变量和局部变量,局部变量遮挡全局变量。 - 支持全局变量和局部变量,局部变量遮挡全局变量。
- 不支持局部变量之间的遮挡,重名的局部变量为同一变量。 - 不支持局部变量之间的遮挡,重名的局部变量为同一变量。
- 支持函数声明,可以通过函数声明来调用 C 语言库。不支持变量声明。
- 函数只支持最多八个参数。函数声明中支持可变参数,仅用于兼容 C 语言库。 - 函数只支持最多八个参数。函数声明中支持可变参数,仅用于兼容 C 语言库。
- 类型检查有遗漏,若 C 编译器报错,而本语言编译通过,就可以认为是 UB。 - 类型检查有遗漏,若 C 编译器报错,而本语言编译通过,就可以认为是 UB。
- 例如函数调用的参数和 `return` 语句不会检查类型。 - 例如函数调用的参数和 `return` 语句不会检查类型。
- 赋值和比较时没有类型检查,这是为了方便 `0` 成为空指针常量。
## 限制 ## 限制
@ -146,54 +155,24 @@ $ bash boot.sh
编译过程中涉及的以下参数: 编译过程中涉及的以下参数:
- 符号表总长度、字符串表总长度 - 符号表总长度、字符串表总长度
- 符号数、字符串数、局部变量数、(虚拟)寄存器 - 符号数、字符串数、全局变量数、局部变量
不能超过源代码中指定的常数。 不能超过源代码中指定的常数。如果有必要这些常数可以适度加大。
- 目前源代码中的常数能够保证自举成功。如果有必要可以将它们适度加大。 目前源代码中的常数能够保证自举。
- 该设计保证了没有任何的动态内存分配。如果愿意,可以将它们改为 `malloc``free` 动态管理,本语言是完全支持的。
如果愿意,完全可以把程序中的各类表改为 `malloc``free` 动态管理,本语言是完全支持的。
## 依赖 ## 依赖
直接依赖下面这些 C 语言库函数和变量,在本语言中提供声明后调用。 直接依赖下面这些 C 语言库函数,在本语言中提供声明后调用。
- `printf` - `printf`
- `getchar` - `getchar`
- `exit` - `exit`
- `ungetc``stdin`(理论上非必须,可以在本语言中手动模拟) 间接依赖下面这些 C 语言库函数,在 C 语言中进行封装后调用。
- `fprintf``stderr`(理论上非必须,仅用于输出错误信息)
## 测试 - `ungetc`(理论上非必须,可以在本语言中手动模拟)
- `vfprintf` 和可变参数有关的宏(用于输出调试信息,非必须)
### 单元测试
直接运行
```sh
$ bash test.sh
```
### 覆盖率
安装如下可视化工具
```sh
$ pip install gcovr
```
然后
```sh
$ sh cov-boot.sh
```
```sh
$ sh cov-test.sh
```
就会在 cov 文件夹下生成自举或测试的 coverage 数据

15
boot-lib.c Normal file
View File

@ -0,0 +1,15 @@
#include <stdio.h>
#include <stdarg.h>
int eprintf(const char format[], ...) {
va_list args;
va_start(args, format);
int ret = vfprintf(stderr, format, args);
va_end(args);
return ret;
}
void ungetchar(int ch) {
ungetc(ch, stdin);
}

11
boot-lib.h Normal file
View File

@ -0,0 +1,11 @@
#include <stdio.h>
#include <stdlib.h>
// std
int printf(const char* format, ...);
int getchar();
void exit(int status);
// ext
void ungetchar(int ch);
int eprintf(const char* format, ...);

12
boot-native.sh Normal file
View File

@ -0,0 +1,12 @@
mkdir -p build && cd build &&
cat ../boot-lib.h ../boot.c | sed '/^#/d' > boot-all.c &&
gcc ../boot.c ../boot-lib.c -o gcc.out &&
./gcc.out < boot-all.c > boot1.s &&
gcc -static boot1.s ../boot-lib.c -o boot1.out &&
./boot1.out < boot-all.c > boot2.s &&
gcc -static boot2.s ../boot-lib.c -o boot2.out &&
./boot2.out < boot-all.c > boot3.s &&
cmp --silent boot1.s boot2.s && echo "boot1.s == boot2.s" || echo "boot1.s != boot2.s"
cmp --silent boot2.s boot3.s && echo "boot2.s == boot3.s" || echo "boot2.s != boot3.s"
cmp --silent boot1.s boot3.s && echo "boot1.s == boot3.s" || echo "boot1.s != boot3.s"
rm boot-all.c

812
boot.c

File diff suppressed because it is too large Load Diff

26
boot.sh
View File

@ -1,22 +1,12 @@
if [ $(uname -m) != "riscv64" ]; then
function compile_and_run() {
riscv64-linux-gnu-gcc-12 -static $1.s -o $1.elf &&
qemu-riscv64 $1.elf < ../boot.c > $2.s
return $?
}
else
function compile_and_run() {
gcc $1.s -o $1.elf &&
./$1.elf < ../boot.c > $2.s
return $?
}
fi
mkdir -p build && cd build && mkdir -p build && cd build &&
gcc ../boot.c -o gcc.elf && cat ../boot-lib.h ../boot.c | sed '/^#/d' > boot-all.c &&
./gcc.elf < ../boot.c > boot1.s && gcc ../boot.c ../boot-lib.c -o gcc.out &&
compile_and_run boot1 boot2 && ./gcc.out < boot-all.c > boot1.s &&
compile_and_run boot2 boot3 riscv64-linux-gnu-gcc-12 -static boot1.s ../boot-lib.c -o boot1.out &&
qemu-riscv64 boot1.out < boot-all.c > boot2.s &&
riscv64-linux-gnu-gcc-12 -static boot2.s ../boot-lib.c -o boot2.out &&
qemu-riscv64 boot2.out < boot-all.c > boot3.s
cmp --silent boot1.s boot2.s && echo "boot1.s == boot2.s" || echo "boot1.s != boot2.s" cmp --silent boot1.s boot2.s && echo "boot1.s == boot2.s" || echo "boot1.s != boot2.s"
cmp --silent boot2.s boot3.s && echo "boot2.s == boot3.s" || echo "boot2.s != boot3.s" cmp --silent boot2.s boot3.s && echo "boot2.s == boot3.s" || echo "boot2.s != boot3.s"
cmp --silent boot1.s boot3.s && echo "boot1.s == boot3.s" || echo "boot1.s != boot3.s" cmp --silent boot1.s boot3.s && echo "boot1.s == boot3.s" || echo "boot1.s != boot3.s"
rm boot-all.c

View File

@ -1,6 +0,0 @@
mkdir -p cov && cd cov &&
rm *
gcc --coverage -g -O0 ../boot.c -o boot.elf
./boot.elf < ../boot.c > /dev/null
gcov boot.elf-boot.c
python3 -m gcovr --html-details --html-theme github.green -o report.html -r ..

View File

@ -1,10 +0,0 @@
mkdir -p cov && cd cov &&
rm *
gcc --coverage -g -O0 ../boot.c -o boot.elf
for i in ../test/**/*.c; do
echo "Running coverage for test '$i'"
./boot.elf < $i > /dev/null 2>/dev/null
gcov boot.elf-boot.c
done
python3 -m gcovr --html-details --html-theme github.green -o report.html -r ..

17
demo/add.c Normal file
View File

@ -0,0 +1,17 @@
int printf(const char format[], ...);
int scanf(const char format[], ...);
int putchar(int ch);
int* p;
int f1() {
int a = 1;
return *(a+(a+(a+(a+(a+(a+(a+(a+(a+(a+(p))))))))))); // a[10]
}
int main() {
int a[15];
p = a;
for (int i = 0; i < 15; a[i] = i, ++i);
return f1();
}

5
demo/hello.c Normal file
View File

@ -0,0 +1,5 @@
int printf(const char* format, ...);
int main() {
printf("hello world %d\n", 42);
}

46
demo/lut.c Normal file
View File

@ -0,0 +1,46 @@
int printf(const char format[], ...);
int getchar();
char string_table[65536];
int string_offset;
int string_lut[4096];
int string_lut_size;
int parse_string() {
int offset = string_offset;
int ch;
while ((ch = getchar()) != '"') {
if (ch == -1 || ch == '\n') {
printf("expecting '\"'\n");
return 1;
}
string_table[string_offset++] = ch;
}
string_table[string_offset++] = 0;
string_lut[string_lut_size] = offset;
return string_lut_size++;
}
int streq(const char* s1, const char* s2) {
while (*s1 && *s2 && *s1 == *s2) {
s1++;
s2++;
}
return *s1 == *s2;
}
void dump_string_table() {
printf(".data\n");
for (int i = 0; i < string_lut_size; ++i) {
char* id = string_table + string_lut[i];
printf(".LC%d: .string \"%s\", const: %d\n",
i, id, streq(id, "const"));
}
}
int main() {
char ch;
while ((ch = getchar()) == '"') parse_string();
dump_string_table();
}

View File

@ -1,4 +1,4 @@
int printf(char* format, ...); int printf(const char format[], ...);
int putchar(int ch); int putchar(int ch);
int a[9]; int a[9];

View File

@ -1,28 +1,24 @@
int printf(char* format, ...); int printf(const char format[], ...);
int scanf(char* format, ...); int scanf(const char format[], ...);
int exit(int status);
void swap(int* a, int* b) {
int t = *a;
*a = *b;
*b = t;
}
void sort(int a[], int n) { void sort(int a[], int n) {
for (int i = 0; i < n; i++) { for (int i = 0; i < n; i++) {
for (int j = i + 1; j < n; j++) { for (int j = i + 1; j < n; j++) {
if (a[i] > a[j]) { if (a[i] > a[j]) {
swap(&a[i], &a[j]); int t = a[i];
a[i] = a[j];
a[j] = t;
} }
} }
} }
} }
int a[100];
int n;
int main() { int main() {
int n;
int a[100];
printf("Enter the number of elements in the array: ");
scanf("%d", &n); scanf("%d", &n);
printf("Enter the elements of the array: ");
for (int i = 0; i < n; i++) { for (int i = 0; i < n; i++) {
scanf("%d", &a[i]); scanf("%d", &a[i]);
} }

16
demo/strcmp.c Normal file
View File

@ -0,0 +1,16 @@
int printf(const char* format, ...);
int strcmp(const char* s1, const char* s2) {
while (*s1 && *s2 && *s1 == *s2) {
s1++;
s2++;
}
return *s1 - *s2;
}
int main() {
const char* s1 = "helloworld";
const char* s2 = "world";
printf("%d\n", strcmp(s1, s2));
printf("%d\n", strcmp(s1 + 5, s2));
}

5
run-native.sh Normal file
View File

@ -0,0 +1,5 @@
gcc boot.c boot-lib.c &&
./a.out < $1 > $1.s &&
gcc -static $1.s boot-lib.c -o $1.out &&
./$1.out
echo $?

20
run.sh
View File

@ -1,17 +1,5 @@
if [ $(uname -m) != "riscv64" ]; then gcc boot.c boot-lib.c &&
function compile_and_run() { ./a.out < $1 > $1.s &&
riscv64-linux-gnu-gcc-12 -static $1.s -o $1.elf riscv64-linux-gnu-gcc-12 -static $1.s boot-lib.c -o $1.out &&
qemu-riscv64 $1.elf qemu-riscv64 $1.out
}
else
function compile_and_run() {
gcc $1.s -o $1.elf
./$1.elf
}
fi
gcc boot.c -o boot.elf &&
./boot.elf < $1 > $1.s &&
compile_and_run $1
echo $? echo $?
rm $1.s $1.s.elf boot.elf 2> /dev/null

68
test.sh
View File

@ -1,68 +0,0 @@
if [ $(uname -m) != "riscv64" ]; then
function compile() {
riscv64-linux-gnu-gcc-12 -static $1.s -o $1.elf
}
function run_with_input() {
qemu-riscv64 $1.elf < $1.in > $1.ans
}
function run_without_input() {
qemu-riscv64 $1.elf > $1.ans
}
else
function compile() {
gcc $1.s -o $1.elf
}
function run_with_input() {
./$1.elf < $1.in > $1.ans
}
function run_without_input() {
./$1.elf > $1.ans
}
fi
cd test
gcc ../boot.c -o boot.elf
all_cnt=0
succ_cnt=0
for D in *; do
if [ -d "${D}" ]; then
echo "Testing subdirectory '$D'"
cd $D
for i in *.c; do
all_cnt=$((all_cnt+1))
failed=1
i=$(basename $i .c)
if [ -f $i.out ]; then
../boot.elf < $i.c > $i.s &&
compile $i
if [[ $? == 0 ]]; then
if [ -f $i.in ]; then
run_with_input $i
else
run_without_input $i
fi
echo $? >> $i.ans
cmp $i.out $i.ans
failed=$?
if [[ $failed == 0 ]]; then
rm $i.ans $i.elf $i.s
fi
else
failed=1
fi
else
../boot.elf < $i.c > /dev/null 2>/dev/null
failed=$((!$?))
fi
if [[ $failed == 0 ]]; then
echo "Test '$D/$i' passed"
succ_cnt=$((succ_cnt+1))
else
echo "Test '$D/$i' failed"
fi
done
cd ..
fi
done
echo "Passed $succ_cnt/$all_cnt tests"
rm boot.elf

View File

@ -1,39 +0,0 @@
int printf(char* format, ...);
int scanf(char* format, ...);
int exit(int status);
void assert_eq(int expected, int actual) {
if (expected != actual) {
printf("expected: %d, actual: %d\n", expected, actual);
exit(1);
}
}
void check(int a[], int i, int j) {
assert_eq(i - j, &a[i] - &a[j]);
assert_eq(j - i, &a[j] - &a[i]);
assert_eq(a[i], *(a + i));
assert_eq(i[a], *(i + a));
assert_eq(a[j - i], *(a + (j - i)));
assert_eq(j[a - i], *(j + (a - i)));
}
void check_all(int a[], int n) {
for (int i = 0; i < n; i++) {
for (int j = i + 1; j < n; j++) {
if (a[i] > a[j]) {
check(a, i, j);
}
}
}
}
int global[100];
int main() {
int local[100];
check_all(global, 100);
check_all(local, 100);
}

View File

@ -1 +0,0 @@
0

View File

@ -1,11 +0,0 @@
100
13 49 15 58 24 74 80 81 69 23
67 88 59 39 1 12 73 50 55 53
71 63 9 90 87 89 51 75 40 84
25 94 68 47 48 14 99 33 62 79
66 85 56 31 38 29 86 46 70 6
10 19 64 72 45 4 11 42 78 7
95 27 93 57 21 35 5 22 76 54
44 98 61 32 17 92 65 36 20 28
83 2 18 60 16 41 30 37 100 97
77 3 82 8 26 34 91 43 96 52

View File

@ -1,2 +0,0 @@
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
0

View File

@ -1,4 +0,0 @@
// hello
/* world */
int main() {}

View File

@ -1 +0,0 @@
0

View File

@ -1,8 +0,0 @@
enum {
A, B, C = -B, D, E = +1, F,
};
int main() {
return A + B + C + D + E + F;
// 0 + 1 + -1 + 0 + 1 + 2 = 3
}

View File

@ -1 +0,0 @@
3

View File

@ -1,7 +0,0 @@
int printf(char* format, ...);
int gi = 42;
int main() {
printf("hello world %d\n", gi);
}

View File

@ -1,2 +0,0 @@
hello world 42
0

View File

@ -1,3 +0,0 @@
int main() {
return 42;
}

View File

@ -1 +0,0 @@
42

View File

@ -1,3 +0,0 @@
int main() {
&0;
}

View File

@ -1,5 +0,0 @@
int main() {
int* a;
int* b;
a + b;
}

View File

@ -1,5 +0,0 @@
int main() {
int a;
int* b;
0 ? a : b;
}

View File

@ -1,4 +0,0 @@
int main() {
int a;
*a;
}

View File

@ -1,4 +0,0 @@
int main() {
void* p;
*p;
}

View File

@ -1,3 +0,0 @@
void f() {
f(0
}

View File

@ -1,3 +0,0 @@
int main() {
'
}

View File

@ -1 +0,0 @@
/*

View File

@ -1 +0,0 @@
enum { A = 1

View File

@ -1 +0,0 @@
void f(int a

View File

@ -1,3 +0,0 @@
int main() {
"
}

View File

@ -1,3 +0,0 @@
int main() {
break;
}

View File

@ -1,3 +0,0 @@
int main() {
continue;
}

View File

@ -1 +0,0 @@
.

View File

@ -1,3 +0,0 @@
int main() {
return '\i';
}

View File

@ -1 +0,0 @@
enum { 0 };

View File

@ -1 +0,0 @@
int a[-1];

View File

@ -1,3 +0,0 @@
int main() {
f();
}

View File

@ -1,3 +0,0 @@
int main() {
a;
}

View File

@ -1,4 +0,0 @@
int main() {
int* p;
p * p;
}

View File

@ -1,4 +0,0 @@
int main() {
int* p;
~p;
}

View File

@ -1,5 +0,0 @@
int main() {
int* a;
char* b;
a - b;
}

View File

@ -1 +0,0 @@
`

View File

@ -1,3 +0,0 @@
int main() {
~~
}

View File

@ -1 +0,0 @@
0

View File

@ -1,3 +0,0 @@
int main() {
if 1
}

View File

@ -1,2 +0,0 @@
int size = 10;
int a[size];

View File

@ -1 +0,0 @@
void f(void a) {}

View File

@ -1 +0,0 @@
void a;

View File

@ -1,3 +0,0 @@
void f() {
void a;
}

View File

@ -1,39 +0,0 @@
int printf(char* format, ...);
int main() {
int i;
// For loop
printf("For loop:\n");
for (i = 0; i < 5; i++) {
if (i == 3) {
break; // Exit the loop when i is 3
}
printf("%d ", i);
}
printf("\n");
// While loop
printf("While loop:\n");
i = 0;
while (i < 5) {
if (i == 3) {
break; // Exit the loop when i is 3
}
printf("%d ", i);
i++;
}
printf("\n");
// Do-while loop
printf("Do-while loop:\n");
i = 0;
do {
if (i == 3) {
break; // Exit the loop when i is 3
}
printf("%d ", i);
i++;
} while (i < 5);
printf("\n");
}

View File

@ -1,7 +0,0 @@
For loop:
0 1 2
While loop:
0 1 2
Do-while loop:
0 1 2
0

View File

@ -1,41 +0,0 @@
int printf(char* format, ...);
int main() {
int i;
// For loop
printf("For loop:\n");
for (i = 0; i < 5; i++) {
if (i == 3) {
continue; // Skip the rest of the loop when i is 3
}
printf("%d ", i);
}
printf("\n");
// While loop
printf("While loop:\n");
i = 0;
while (i < 5) {
if (i == 3) {
i++;
continue; // Skip the rest of the loop when i is 3
}
printf("%d ", i);
i++;
}
printf("\n");
// Do-while loop
printf("Do-while loop:\n");
i = 0;
do {
if (i == 3) {
i++;
continue; // Skip the rest of the loop when i is 3
}
printf("%d ", i);
i++;
} while (i < 5);
printf("\n");
}

View File

@ -1,7 +0,0 @@
For loop:
0 1 2 4
While loop:
0 1 2 4
Do-while loop:
0 1 2 4
0

View File

@ -1,20 +0,0 @@
int printf(char* format, ...);
void test() {
int i;
int j;
for (i = 0; i < 5; i++) {
for (j = 0; j < 5; j++) {
if (i >= 2 && j >= 2 && i + j >= 5) {
return; // Exit nested loop via return
}
printf("(%d, %d)%c", i, j, " \n"[j == 4]);
}
}
}
int main() {
test();
printf("\n");
}

View File

@ -1,4 +0,0 @@
(0, 0) (0, 1) (0, 2) (0, 3) (0, 4)
(1, 0) (1, 1) (1, 2) (1, 3) (1, 4)
(2, 0) (2, 1) (2, 2)
0

View File

@ -1 +0,0 @@
42

View File

@ -1 +0,0 @@
42

View File

@ -1,34 +0,0 @@
int getchar();
int putchar(int ch);
int fprintf(void* file, char* format, ...);
extern void* stdout;
int main() {
char ch = 0["\t\r\""];;
while ((ch = getchar()) != -1) {
if (ch == '\\') {
ch = getchar();
if (ch == 'n') {
ch = '\n';
} else if (ch == 't') {
ch = '\t';
} else if (ch == 'r') {
ch = '\r';
} else if (ch == '0') {
ch = '\0';
} else if (ch == '\\') {
ch = '\\';
} else if (ch == '\'') {
ch = '\'';
} else if (ch == '\"') {
ch = '\"';
} else {
fprintf(stdout, "unexpected escaped character: '\\%c'\n", ch);
return 1;
}
}
putchar(ch);
}
return 0;
}

View File

@ -1 +0,0 @@
hello\n\tworld\u

View File

@ -1,3 +0,0 @@
hello
worldunexpected escaped character: '\u'
1

View File

@ -1,21 +0,0 @@
int printf(char* format, ...);
enum {
a = 1
};
int get_20() {
return (a+(a+(a+(a+(a+(a+(a+(a+(a+(a+(a+(a+(a+(a+(a+(a+(a+(a+(a+(a+(- -0)))))))))))))))))))));
}
void dummy(int a0, int a1, int a2, int a3, int a4, int a5, int a6, int a7) {
printf("%d %d\n", a0);
}
int main() {
char placeholder[4096];
int a = 1;
dummy((a+(a+(a+(a+(a+(a+(a+(a+(a+(a+(a+(a+(a+(a+(a+(a+(a+(a+(a+(a+(! !0))))))))))))))))))))), a, a, a, a, a, a, a);
return (a=(a+(a+(a+(a+(a+(a+(a+(a+(a+(a+(a+(a+(a+(a+(a+(a+(a+(a+(a+(a+(~ ~0)))))))))))))))))))))), (a = +a);
}

View File

View File

@ -1,2 +0,0 @@
20 1
20

View File

@ -1,28 +0,0 @@
int printf(char* format, ...);
int main() {
int a = 5;
int b = 4;
a += b;
printf("%d\n", a);
a -= b;
printf("%d\n", a);
a *= b;
printf("%d\n", a);
a /= b;
printf("%d\n", a);
a %= b;
printf("%d\n", a);
a &= b;
printf("%d\n", a);
a |= b;
printf("%d\n", a);
a ^= b;
printf("%d\n", a);
a = b;
printf("%d\n", a);
a <<= b;
printf("%d\n", a);
a >>= b;
printf("%d\n", a);
}

View File

@ -1,12 +0,0 @@
9
5
20
5
1
0
4
0
4
64
4
0

View File

@ -1,16 +0,0 @@
int printf(char* format, ...);
int main() {
int a = 5;
int b = 4;
printf("%d+%d=%d\n", a, b, a + b);
printf("%d-%d=%d\n", a, b, a - b);
printf("%d*%d=%d\n", a, b, a * b);
printf("%d/%d=%d\n", a, b, a / b);
printf("%d%%%d=%d\n", a, b, a % b);
printf("%d&%d=%d\n", a, b, a & b);
printf("%d|%d=%d\n", a, b, a | b);
printf("%d^%d=%d\n", a, b, a ^ b);
printf("%d<<%d=%d\n", a, b, a << b);
printf("%d>>%d=%d\n", a, b, a >> b);
}

View File

@ -1,11 +0,0 @@
5+4=9
5-4=1
5*4=20
5/4=1
5%4=1
5&4=4
5|4=5
5^4=1
5<<4=80
5>>4=0
0

View File

@ -1,14 +0,0 @@
int printf(char* format, ...);
int main() {
int a = 4;
printf("a = %d\n", a);
printf("a++ = %d\n", a++);
printf("a = %d\n", a);
printf("++a = %d\n", ++a);
printf("a = %d\n", a);
printf("a-- = %d\n", a--);
printf("a = %d\n", a);
printf("--a = %d\n", --a);
printf("a = %d\n", a);
}

View File

@ -1,10 +0,0 @@
a = 4
a++ = 4
a = 5
++a = 6
a = 6
a-- = 6
a = 5
--a = 4
a = 4
0

View File

@ -1,17 +0,0 @@
int printf(char* format, ...);
int f(int i) {
printf("f(%d)\n", i);
return i % 2;
}
int main() {
1 && f(1);
0 && f(2);
1 || f(3);
0 || f(4);
1 ? f(5) : f(6);
0 ? f(7) : f(8);
1 && f(9) || f(10);
0 && f(11) || f(12);
}

View File

View File

@ -1,7 +0,0 @@
f(1)
f(4)
f(5)
f(8)
f(9)
f(12)
0

View File

@ -1,9 +0,0 @@
int printf(char* format, ...);
int main() {
int a = 5;
printf("+a=%d\n", +a);
printf("-a=%d\n", -a);
printf("!a=%d\n", !a);
printf("~a=%d\n", ~a);
}

View File

@ -1,5 +0,0 @@
+a=5
-a=-5
!a=0
~a=-6
0

View File

@ -1,4 +0,0 @@
int main() {
int* p;
&p;
}

View File

@ -1 +0,0 @@
void f(int* a[]) {}

View File

@ -1 +0,0 @@
int* a[10];

View File

@ -1,3 +0,0 @@
void f() {
int* a[10];
}

View File

@ -1,3 +0,0 @@
int main() {
(main)();
}

View File

@ -1,5 +0,0 @@
void f();
int main() {
f(0, 1, 2, 3, 4, 5, 6, 7, 8, 9);
}

View File

@ -1 +0,0 @@
void f(int a0, int a1, int a2, int a3, int a4, int a5, int a6, int a7, int a8) {}