commit initial
This commit is contained in:
392
.monkeycode/specs/2026-05-20-tiny-c-compiler-csharp/design.md
Normal file
392
.monkeycode/specs/2026-05-20-tiny-c-compiler-csharp/design.md
Normal file
@@ -0,0 +1,392 @@
|
||||
# Tiny C Compiler in C# - Technical Design
|
||||
|
||||
Feature Name: tiny-c-compiler-csharp
|
||||
Updated: 2026-05-20
|
||||
|
||||
## Description
|
||||
|
||||
本项目实现一个使用 C# 编写的 C 语言编译器,参考 TCC 的设计理念。编译器将 C 源代码直接编译为 x86/x64 本地机器码,不经过 MSIL 中间层。项目目标是实现一个轻量级、编译速度快的 C 编译器,支持 C99 标准的核心子集。
|
||||
|
||||
## Architecture
|
||||
|
||||
```mermaid
|
||||
graph TD
|
||||
A["C Source Code\n.c files"] --> B["Preprocessor\n预处理"]
|
||||
B --> C["Lexer\n词法分析"]
|
||||
C --> D["Parser\n语法分析"]
|
||||
D --> E["Semantic Analyzer\n语义分析"]
|
||||
E --> F["IR Generator\n中间表示生成"]
|
||||
F --> G["Code Generator\n代码生成 x86/x64"]
|
||||
G --> H["Object File\nPE/ELF"]
|
||||
H --> I["Executable\n可执行文件"]
|
||||
|
||||
J["Error Handler"] -.-> B
|
||||
J -.-> C
|
||||
J -.-> D
|
||||
J -.-> E
|
||||
J -.-> F
|
||||
J -.-> G
|
||||
|
||||
K["Symbol Table"] -.-> E
|
||||
K -.-> F
|
||||
K -.-> G
|
||||
|
||||
L["Type System"] -.-> E
|
||||
L -.-> F
|
||||
```
|
||||
|
||||
### Architecture Overview
|
||||
|
||||
编译器采用传统的单遍或多遍编译架构,分为以下主要阶段:
|
||||
|
||||
1. **预处理阶段**:处理宏展开、条件编译、头文件包含
|
||||
2. **前端阶段**:词法分析、语法分析、语义分析
|
||||
3. **中间阶段**:IR 生成与优化
|
||||
4. **后端阶段**:x86/x64 代码生成与可执行文件输出
|
||||
|
||||
## Components and Interfaces
|
||||
|
||||
### 1. Preprocessor (预处理器)
|
||||
|
||||
**职责**:
|
||||
- 处理 `#include` 指令,展开头文件
|
||||
- 处理 `#define` 宏定义和宏展开
|
||||
- 处理条件编译 `#ifdef`、`#ifndef`、`#endif`、`#if`
|
||||
- 处理 `#pragma` 指令
|
||||
|
||||
**接口**:
|
||||
```csharp
|
||||
public interface IPreprocessor
|
||||
{
|
||||
string Preprocess(string sourceCode, string sourceFile);
|
||||
void AddIncludePath(string path);
|
||||
void DefineMacro(string name, string? value);
|
||||
}
|
||||
```
|
||||
|
||||
### 2. Lexer (词法分析器)
|
||||
|
||||
**职责**:
|
||||
- 将预处理后的源代码分解为 token 流
|
||||
- 识别关键字、标识符、字面量、运算符、分隔符
|
||||
- 跳过注释和空白
|
||||
- 报告词法错误
|
||||
|
||||
**接口**:
|
||||
```csharp
|
||||
public interface ILexer
|
||||
{
|
||||
IEnumerable<Token> Tokenize(string source);
|
||||
}
|
||||
|
||||
public enum TokenType
|
||||
{
|
||||
Keyword, Identifier, IntLiteral, FloatLiteral,
|
||||
CharLiteral, StringLiteral, Operator, Separator,
|
||||
EOF, Error
|
||||
}
|
||||
|
||||
public record Token(
|
||||
TokenType Type,
|
||||
string Lexeme,
|
||||
object? Value,
|
||||
SourceLocation Location
|
||||
);
|
||||
```
|
||||
|
||||
### 3. Parser (语法分析器)
|
||||
|
||||
**职责**:
|
||||
- 实现递归下降解析器
|
||||
- 构建抽象语法树(AST)
|
||||
- 处理 C 语言的运算符优先级
|
||||
- 报告语法错误
|
||||
|
||||
**接口**:
|
||||
```csharp
|
||||
public interface IParser
|
||||
{
|
||||
AstNode Parse();
|
||||
}
|
||||
|
||||
public abstract record AstNode(SourceLocation Location);
|
||||
public record ProgramNode(List<DeclarationNode> Declarations, SourceLocation Location) : AstNode(Location);
|
||||
public record FunctionDeclarationNode(
|
||||
TypeNode ReturnType,
|
||||
string Name,
|
||||
List<ParameterNode> Parameters,
|
||||
BlockStatementNode Body,
|
||||
SourceLocation Location
|
||||
) : AstNode(Location);
|
||||
```
|
||||
|
||||
### 4. Semantic Analyzer (语义分析器)
|
||||
|
||||
**职责**:
|
||||
- 类型检查与类型推断
|
||||
- 符号表管理
|
||||
- 作用域管理
|
||||
- 语义错误报告
|
||||
|
||||
**接口**:
|
||||
```csharp
|
||||
public interface ISemanticAnalyzer
|
||||
{
|
||||
void Analyze(AstNode root);
|
||||
}
|
||||
|
||||
public interface ISymbolTable
|
||||
{
|
||||
void EnterScope();
|
||||
void ExitScope();
|
||||
void AddSymbol(string name, Symbol symbol);
|
||||
Symbol? Lookup(string name);
|
||||
}
|
||||
```
|
||||
|
||||
### 5. IR Generator (中间表示生成器)
|
||||
|
||||
**职责**:
|
||||
- 将 AST 转换为三地址码形式的 IR
|
||||
- 构建控制流图(CFG)
|
||||
- 支持基本优化(常量折叠、死代码消除)
|
||||
|
||||
**接口**:
|
||||
```csharp
|
||||
public interface IIrGenerator
|
||||
{
|
||||
IrProgram Generate(AstNode ast);
|
||||
}
|
||||
|
||||
public record IrProgram(List<IrFunction> Functions);
|
||||
public record IrFunction(string Name, List<IrBasicBlock> BasicBlocks);
|
||||
public record IrBasicBlock(string Label, List<IrInstruction> Instructions);
|
||||
public abstract record IrInstruction;
|
||||
```
|
||||
|
||||
### 6. Code Generator (代码生成器)
|
||||
|
||||
**职责**:
|
||||
- 将 IR 转换为 x86/x64 机器码
|
||||
- 寄存器分配
|
||||
- 栈帧管理
|
||||
- 遵循平台调用约定
|
||||
|
||||
**接口**:
|
||||
```csharp
|
||||
public interface ICodeGenerator
|
||||
{
|
||||
byte[] Generate(IrProgram program, TargetArchitecture architecture);
|
||||
}
|
||||
|
||||
public enum TargetArchitecture { X86, X64 }
|
||||
```
|
||||
|
||||
### 7. Object File Writer (目标文件写入器)
|
||||
|
||||
**职责**:
|
||||
- 生成 PE 格式文件(Windows)
|
||||
- 生成 ELF 格式文件(Linux)
|
||||
- 处理重定位信息
|
||||
- 设置入口点
|
||||
|
||||
**接口**:
|
||||
```csharp
|
||||
public interface IObjectFileWriter
|
||||
{
|
||||
byte[] WriteExecutable(byte[] machineCode, TargetPlatform platform);
|
||||
}
|
||||
|
||||
public enum TargetPlatform { WindowsX86, WindowsX64, LinuxX86, LinuxX64 }
|
||||
```
|
||||
|
||||
### 8. Compiler Driver (编译器驱动)
|
||||
|
||||
**职责**:
|
||||
- 协调各个编译阶段
|
||||
- 处理命令行参数
|
||||
- 错误汇总与报告
|
||||
- 管理编译流程
|
||||
|
||||
**接口**:
|
||||
```csharp
|
||||
public class CompilerDriver
|
||||
{
|
||||
public int Run(string[] args);
|
||||
public CompilationResult Compile(CompilationOptions options);
|
||||
}
|
||||
```
|
||||
|
||||
## Data Models
|
||||
|
||||
### Token 模型
|
||||
|
||||
```csharp
|
||||
public readonly struct SourceLocation
|
||||
{
|
||||
public string FileName { get; }
|
||||
public int Line { get; }
|
||||
public int Column { get; }
|
||||
}
|
||||
|
||||
public enum TokenType
|
||||
{
|
||||
// 关键字
|
||||
Int, Char, Float, Double, Long, Short, Void,
|
||||
If, Else, While, For, Do, Switch, Case, Default,
|
||||
Break, Continue, Return, Struct, Union, Typedef,
|
||||
// 字面量
|
||||
IntLiteral, FloatLiteral, CharLiteral, StringLiteral,
|
||||
// 标识符
|
||||
Identifier,
|
||||
// 运算符
|
||||
Plus, Minus, Star, Slash, Percent,
|
||||
Equal, NotEqual, Less, Greater, LessEqual, GreaterEqual,
|
||||
Assign, PlusAssign, MinusAssign, StarAssign, SlashAssign,
|
||||
And, Or, Not, BitAnd, BitOr, BitXor,
|
||||
LeftShift, RightShift,
|
||||
// 分隔符
|
||||
LeftParen, RightParen, LeftBrace, RightBrace,
|
||||
LeftBracket, RightBracket,
|
||||
Semicolon, Comma, Dot, Arrow, Colon,
|
||||
// 预处理器
|
||||
HashInclude, HashDefine, HashIf, HashIfdef, HashIfndef, HashElse, HashEndif,
|
||||
// 特殊
|
||||
EOF, Error
|
||||
}
|
||||
```
|
||||
|
||||
### Type System 模型
|
||||
|
||||
```csharp
|
||||
public abstract record CType(string Name);
|
||||
public record PrimitiveType(TypeKind Kind) : CType(Kind.ToString())
|
||||
{
|
||||
public enum TypeKind { Void, Char, Short, Int, Long, Float, Double }
|
||||
}
|
||||
public record PointerType(CType BaseType) : CType($"{BaseType}*");
|
||||
public record ArrayType(CType ElementType, int Size) : CType($"{ElementType}[{Size}]");
|
||||
public record StructType(string Name, List<FieldDeclaration> Fields) : CType(Name);
|
||||
public record FunctionType(CType ReturnType, List<CType> ParameterTypes) : CType("function");
|
||||
```
|
||||
|
||||
### IR 指令模型
|
||||
|
||||
```csharp
|
||||
public abstract record IrInstruction;
|
||||
public record IrBinaryOp(IrTemp Dest, IrBinaryOpType Op, IrValue Left, IrValue Right) : IrInstruction;
|
||||
public record IrUnaryOp(IrTemp Dest, IrUnaryOpType Op, IrValue Source) : IrInstruction;
|
||||
public record IrLoad(IrTemp Dest, IrValue Address) : IrInstruction;
|
||||
public record IrStore(IrValue Address, IrValue Value) : IrInstruction;
|
||||
public record IrCall(IrTemp? Dest, string FunctionName, List<IrValue> Arguments) : IrInstruction;
|
||||
public record IrJump(string TargetLabel) : IrInstruction;
|
||||
public record IrBranch(IrValue Condition, string TrueLabel, string FalseLabel) : IrInstruction;
|
||||
public record IrReturn(IrValue? Value) : IrInstruction;
|
||||
public record IrLabel(string LabelName) : IrInstruction;
|
||||
|
||||
public enum IrBinaryOpType { Add, Sub, Mul, Div, Mod, And, Or, Xor, Shl, Shr, Eq, Ne, Lt, Gt, Le, Ge }
|
||||
public enum IrUnaryOpType { Neg, Not, BitNot, Deref }
|
||||
|
||||
public abstract record IrValue;
|
||||
public record IrTemp(string Name, CType Type) : IrValue;
|
||||
public record IrConstant(long Value, CType Type) : IrValue;
|
||||
public record IrGlobal(string Name, CType Type) : IrValue;
|
||||
```
|
||||
|
||||
## Correctness Properties
|
||||
|
||||
### 不变量
|
||||
|
||||
1. **类型安全**: 所有 IR 指令的操作数类型必须匹配
|
||||
2. **作用域正确性**: 符号查找必须遵循词法作用域规则
|
||||
3. **控制流完整性**: 所有基本块必须有明确的前驱和后继
|
||||
4. **寄存器一致性**: 代码生成前后寄存器状态必须一致
|
||||
|
||||
### 约束条件
|
||||
|
||||
1. 生成的机器码必须符合 x86/x64 指令集规范
|
||||
2. 函数调用必须遵循目标平台的 ABI(Application Binary Interface)
|
||||
3. 栈帧布局必须保证栈指针对齐(x64 要求 16 字节对齐)
|
||||
4. 可执行文件格式必须符合 PE 或 ELF 规范
|
||||
|
||||
## Error Handling
|
||||
|
||||
### 错误分类
|
||||
|
||||
| 错误类型 | 阶段 | 处理方式 |
|
||||
|---------|------|---------|
|
||||
| 词法错误 | Lexer | 报告错误位置,跳过错误 token |
|
||||
| 语法错误 | Parser | 报告期望的 token,尝试错误恢复 |
|
||||
| 类型错误 | Semantic | 报告类型不匹配详情 |
|
||||
| 未声明符号 | Semantic | 报告符号名称和位置 |
|
||||
| 代码生成错误 | CodeGen | 报告不支持的 IR 指令 |
|
||||
|
||||
### 错误报告接口
|
||||
|
||||
```csharp
|
||||
public record ErrorInfo(
|
||||
ErrorLevel Level, // Warning, Error, Fatal
|
||||
string Message,
|
||||
SourceLocation Location,
|
||||
string? Suggestion = null
|
||||
);
|
||||
|
||||
public interface IErrorReporter
|
||||
{
|
||||
void Report(ErrorInfo error);
|
||||
bool HasErrors { get; }
|
||||
IEnumerable<ErrorInfo> GetErrors();
|
||||
}
|
||||
```
|
||||
|
||||
## Test Strategy
|
||||
|
||||
### 单元测试
|
||||
|
||||
1. **Lexer 测试**:验证各种 token 的正确识别
|
||||
2. **Parser 测试**:验证各种 C 语法的 AST 构建
|
||||
3. **Semantic 测试**:验证类型检查和符号表
|
||||
4. **IR 测试**:验证 AST 到 IR 的转换
|
||||
5. **CodeGen 测试**:验证 IR 到机器码的转换
|
||||
|
||||
### 集成测试
|
||||
|
||||
1. **端到端测试**:编译简单 C 程序并验证输出
|
||||
2. **回归测试**:使用 TCC 测试套件进行对比测试
|
||||
3. **性能测试**:测量编译速度和生成代码质量
|
||||
|
||||
### 测试用例示例
|
||||
|
||||
```c
|
||||
// test_hello.c
|
||||
#include <stdio.h>
|
||||
|
||||
int main() {
|
||||
printf("Hello, World!\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
// test_arithmetic.c
|
||||
int add(int a, int b) {
|
||||
return a + b;
|
||||
}
|
||||
|
||||
int main() {
|
||||
int result = add(3, 4);
|
||||
return result - 7; // should return 0
|
||||
}
|
||||
|
||||
// test_control_flow.c
|
||||
int factorial(int n) {
|
||||
if (n <= 1) return 1;
|
||||
return n * factorial(n - 1);
|
||||
}
|
||||
```
|
||||
|
||||
## References
|
||||
|
||||
[^1]: (TCC Source) - Tiny C Compiler 源码 https://repo.or.cz/tinycc.git
|
||||
[^2]: (PE Format) - Microsoft PE 和 COFF 规范 https://docs.microsoft.com/en-us/windows/win32/debug/pe-format
|
||||
[^3]: (ELF Format) - ELF 规范 https://refspecs.linuxfoundation.org/elf/elf.pdf
|
||||
[^4]: (x64 ABI) - System V AMD64 ABI https://github.com/hjl-tools/x86-psABI/wiki/x86-64-psABI-1.0.pdf
|
||||
[^5]: (x86 Calling Conventions) - x86 调用约定 https://en.wikipedia.org/wiki/X86_calling_conventions
|
||||
@@ -0,0 +1,116 @@
|
||||
# Requirements Document
|
||||
|
||||
## Introduction
|
||||
|
||||
本项目旨在开发一个使用 C# 语言编写的 C 语言编译器,参考 TCC(Tiny C Compiler)的设计理念。编译器将 C 源代码直接编译为 x86/x64 本地机器码,而非 MSIL(Microsoft Intermediate Language)。目标是实现一个轻量级、快速的 C 编译器,支持 C99 标准的核心特性。
|
||||
|
||||
## Glossary
|
||||
|
||||
- **TCC**: Tiny C Compiler,一个小型、快速的 C 编译器
|
||||
- **本地代码**: 直接可在 CPU 上执行的机器码(x86/x64)
|
||||
- **MSIL**: Microsoft Intermediate Language,.NET 平台的中间语言
|
||||
- **代码生成**: 将中间表示转换为目标机器码的过程
|
||||
- **词法分析**: 将源代码分解为 token 流的过程
|
||||
- **语法分析**: 将 token 流构建为抽象语法树(AST)的过程
|
||||
- **语义分析**: 验证 AST 的语义正确性并进行类型检查
|
||||
- **目标平台**: x86 (32-bit) 和 x64 (64-bit) Windows/Linux
|
||||
|
||||
## Requirements
|
||||
|
||||
### Requirement 1: 词法分析器
|
||||
|
||||
**User Story:** AS 一个 C 编译器开发者,I WANT 实现词法分析器,SO THAT 可以将 C 源代码转换为 token 流
|
||||
|
||||
#### Acceptance Criteria
|
||||
|
||||
1. WHEN 接收到 C 源代码文件,词法分析器 SHALL 输出 token 流
|
||||
2. WHEN 遇到 C 语言关键字(if, else, while, for, int, char 等),词法分析器 SHALL 识别为关键字 token
|
||||
3. WHEN 遇到标识符,词法分析器 SHALL 识别为标识符 token
|
||||
4. WHEN 遇到字面量(整数、浮点数、字符、字符串),词法分析器 SHALL 识别为相应的字面量 token
|
||||
5. WHEN 遇到注释(单行 // 和多行 /* */),词法分析器 SHALL 忽略注释内容
|
||||
6. WHEN 遇到词法错误,词法分析器 SHALL 报告错误位置和错误信息
|
||||
|
||||
### Requirement 2: 语法分析器
|
||||
|
||||
**User Story:** AS 一个 C 编译器开发者,I WANT 实现语法分析器,SO THAT 可以将 token 流构建为抽象语法树(AST)
|
||||
|
||||
#### Acceptance Criteria
|
||||
|
||||
1. WHEN 接收到 token 流,语法分析器 SHALL 构建 AST
|
||||
2. WHEN 遇到语法错误,语法分析器 SHALL 报告错误位置和错误描述
|
||||
3. WHILE 解析表达式,语法分析器 SHALL 正确处理运算符优先级
|
||||
4. WHEN 解析函数定义,语法分析器 SHALL 识别函数名、参数列表和函数体
|
||||
5. WHEN 解析控制流语句(if, while, for, switch),语法分析器 SHALL 构建对应的控制流 AST 节点
|
||||
|
||||
### Requirement 3: 语义分析器
|
||||
|
||||
**User Story:** AS 一个 C 编译器开发者,I WANT 实现语义分析器,SO THAT 可以验证 AST 的语义正确性
|
||||
|
||||
#### Acceptance Criteria
|
||||
|
||||
1. WHEN 接收到 AST,语义分析器 SHALL 执行类型检查
|
||||
2. WHEN 遇到未声明的变量,语义分析器 SHALL 报告错误
|
||||
3. WHEN 遇到类型不匹配的赋值或运算,语义分析器 SHALL 报告类型错误
|
||||
4. WHEN 遇到函数调用,语义分析器 SHALL 验证函数签名和参数类型
|
||||
5. WHILE 解析作用域,语义分析器 SHALL 正确管理变量的作用域
|
||||
|
||||
### Requirement 4: 中间表示(IR)生成
|
||||
|
||||
**User Story:** AS 一个 C 编译器开发者,I WANT 生成中间表示,SO THAT 可以优化并转换为目标机器码
|
||||
|
||||
#### Acceptance Criteria
|
||||
|
||||
1. WHEN 接收到语义分析后的 AST,IR 生成器 SHALL 输出三地址码形式的 IR
|
||||
2. WHEN 生成 IR,IR 生成器 SHALL 处理控制流图的构建
|
||||
3. WHILE 生成 IR,IR 生成器 SHALL 支持基本的数据流分析
|
||||
|
||||
### Requirement 5: 代码生成器(x86/x64)
|
||||
|
||||
**User Story:** AS 一个 C 编译器开发者,I WANT 实现代码生成器,SO THAT 可以将 IR 转换为 x86/x64 本地机器码
|
||||
|
||||
#### Acceptance Criteria
|
||||
|
||||
1. WHEN 接收到 IR,代码生成器 SHALL 输出 x86/x64 机器码
|
||||
2. WHEN 处理函数调用,代码生成器 SHALL 遵循目标平台的调用约定(calling convention)
|
||||
3. WHEN 处理局部变量,代码生成器 SHALL 分配栈空间
|
||||
4. WHEN 处理全局变量,代码生成器 SHALL 在数据段分配空间
|
||||
5. IF 目标平台为 x64,代码生成器 SHALL 使用 x64 寄存器
|
||||
6. IF 目标平台为 x86,代码生成器 SHALL 使用 x86 寄存器
|
||||
|
||||
### Requirement 6: 可执行文件生成
|
||||
|
||||
**User Story:** AS 一个 C 编译器用户,I WANT 编译器生成可执行文件,SO THAT 可以直接运行编译后的程序
|
||||
|
||||
#### Acceptance Criteria
|
||||
|
||||
1. WHEN 编译完成,编译器 SHALL 生成 PE(Windows)或 ELF(Linux)格式的可执行文件
|
||||
2. WHEN 生成 PE 文件,编译器 SHALL 包含正确的 PE 头和节表
|
||||
3. WHEN 生成 ELF 文件,编译器 SHALL 包含正确的 ELF 头和节头
|
||||
4. WHEN 生成的可执行文件被操作系统加载,操作系统 SHALL 能够正确执行程序
|
||||
|
||||
### Requirement 7: 命令行接口
|
||||
|
||||
**User Story:** AS 一个 C 编译器用户,I WANT 使用命令行编译 C 文件,SO THAT 可以方便地集成到构建系统中
|
||||
|
||||
#### Acceptance Criteria
|
||||
|
||||
1. WHEN 用户提供源文件路径,编译器 SHALL 编译并生成可执行文件
|
||||
2. WHEN 用户指定输出文件名,编译器 SHALL 使用指定的文件名
|
||||
3. WHEN 用户指定目标架构(x86/x64),编译器 SHALL 生成对应架构的代码
|
||||
4. IF 编译过程中发生错误,编译器 SHALL 输出错误信息并返回非零退出码
|
||||
5. WHEN 用户请求帮助信息,编译器 SHALL 显示使用说明
|
||||
|
||||
### Requirement 8: C99 核心特性支持
|
||||
|
||||
**User Story:** AS 一个 C 程序员,I WANT 编译器支持 C99 核心特性,SO THAT 可以编译现有的 C 代码
|
||||
|
||||
#### Acceptance Criteria
|
||||
|
||||
1. WHEN 编译 C99 代码,编译器 SHALL 支持基本数据类型(int, char, float, double, long, short)
|
||||
2. WHEN 编译 C99 代码,编译器 SHALL 支持指针和数组
|
||||
3. WHEN 编译 C99 代码,编译器 SHALL 支持结构体(struct)和联合体(union)
|
||||
4. WHEN 编译 C99 代码,编译器 SHALL 支持函数定义和调用
|
||||
5. WHEN 编译 C99 代码,编译器 SHALL 支持控制流语句(if, else, while, for, do-while, switch, break, continue, return)
|
||||
6. WHEN 编译 C99 代码,编译器 SHALL 支持宏定义(#define)和条件编译(#ifdef, #ifndef, #endif)
|
||||
7. WHEN 编译 C99 代码,编译器 SHALL 支持头文件包含(#include)
|
||||
8. IF 使用 C99 特性(如单行注释 //),编译器 SHALL 正确解析
|
||||
@@ -0,0 +1,96 @@
|
||||
# Implementation Task List
|
||||
|
||||
## Phase 1: 项目初始化与基础架构
|
||||
|
||||
- [ ] 1.1 创建 .NET 8 控制台项目结构
|
||||
- [ ] 1.2 配置项目解决方案和模块划分
|
||||
- [ ] 1.3 实现基础的错误报告系统(ErrorReporter)
|
||||
- [ ] 1.4 实现源代码位置追踪(SourceLocation)
|
||||
|
||||
## Phase 2: 预处理器实现
|
||||
|
||||
- [ ] 2.1 实现 #include 指令处理
|
||||
- [ ] 2.2 实现 #define 宏定义和宏展开
|
||||
- [ ] 2.3 实现条件编译(#ifdef, #ifndef, #if, #else, #endif)
|
||||
- [ ] 2.4 实现头文件搜索路径管理
|
||||
|
||||
## Phase 3: 词法分析器实现
|
||||
|
||||
- [ ] 3.1 定义所有 TokenType 枚举
|
||||
- [ ] 3.2 实现 Token 结构
|
||||
- [ ] 3.3 实现 Lexer 主类
|
||||
- [ ] 3.4 实现关键字识别
|
||||
- [ ] 3.5 实现标识符识别
|
||||
- [ ] 3.6 实现整数字面量识别
|
||||
- [ ] 3.7 实现浮点数字面量识别
|
||||
- [ ] 3.8 实现字符和字符串字面量识别
|
||||
- [ ] 3.9 实现运算符识别
|
||||
- [ ] 3.10 实现注释跳过
|
||||
- [ ] 3.11 编写 Lexer 单元测试
|
||||
|
||||
## Phase 4: 语法分析器实现
|
||||
|
||||
- [ ] 4.1 定义 AST 节点层次结构
|
||||
- [ ] 4.2 实现递归下降解析器框架
|
||||
- [ ] 4.3 实现表达式解析(处理运算符优先级)
|
||||
- [ ] 4.4 实现语句解析
|
||||
- [ ] 4.5 实现函数声明解析
|
||||
- [ ] 4.6 实现类型声明解析
|
||||
- [ ] 4.7 实现控制流语句解析(if, while, for, switch)
|
||||
- [ ] 4.8 实现结构体和联合体解析
|
||||
- [ ] 4.9 实现错误恢复机制
|
||||
- [ ] 4.10 编写 Parser 单元测试
|
||||
|
||||
## Phase 5: 语义分析器实现
|
||||
|
||||
- [ ] 5.1 实现类型系统(CType 层次结构)
|
||||
- [ ] 5.2 实现符号表(SymbolTable)
|
||||
- [ ] 5.3 实现作用域管理
|
||||
- [ ] 5.4 实现类型检查
|
||||
- [ ] 5.5 实现函数签名验证
|
||||
- [ ] 5.6 实现变量声明检查
|
||||
- [ ] 5.7 编写 Semantic Analyzer 单元测试
|
||||
|
||||
## Phase 6: 中间表示(IR)生成
|
||||
|
||||
- [ ] 6.1 定义 IR 指令集
|
||||
- [ ] 6.2 实现基本块(BasicBlock)结构
|
||||
- [ ] 6.3 实现控制流图(CFG)
|
||||
- [ ] 6.4 实现 AST 到 IR 转换
|
||||
- [ ] 6.5 实现临时变量管理
|
||||
- [ ] 6.6 实现常量折叠优化
|
||||
- [ ] 6.7 编写 IR Generator 单元测试
|
||||
|
||||
## Phase 7: x86/x64 代码生成器
|
||||
|
||||
- [ ] 7.1 定义目标架构抽象
|
||||
- [ ] 7.2 实现寄存器管理
|
||||
- [ ] 7.3 实现栈帧管理
|
||||
- [ ] 7.4 实现 x86 指令编码
|
||||
- [ ] 7.5 实现 x64 指令编码
|
||||
- [ ] 7.6 实现 IR 到机器码转换
|
||||
- [ ] 7.7 实现函数调用约定(cdecl, sysv64)
|
||||
- [ ] 7.8 实现寄存器分配
|
||||
- [ ] 7.9 编写 CodeGen 单元测试
|
||||
|
||||
## Phase 8: 可执行文件生成
|
||||
|
||||
- [ ] 8.1 实现 PE 文件格式写入(Windows)
|
||||
- [ ] 8.2 实现 ELF 文件格式写入(Linux)
|
||||
- [ ] 8.3 实现节表管理
|
||||
- [ ] 8.4 实现重定位处理
|
||||
- [ ] 8.5 实现入口点设置
|
||||
|
||||
## Phase 9: 编译器驱动与 CLI
|
||||
|
||||
- [ ] 9.1 实现命令行参数解析
|
||||
- [ ] 9.2 实现编译流程编排
|
||||
- [ ] 9.3 实现错误汇总与报告
|
||||
- [ ] 9.4 实现多文件编译支持
|
||||
|
||||
## Phase 10: 测试与优化
|
||||
|
||||
- [ ] 10.1 编写端到端测试
|
||||
- [ ] 10.2 使用 TCC 测试套件进行回归测试
|
||||
- [ ] 10.3 性能测试与优化
|
||||
- [ ] 10.4 内存使用优化
|
||||
461
.monkeycode/specs/2026-05-20-tinycc-improvements/design.md
Normal file
461
.monkeycode/specs/2026-05-20-tinycc-improvements/design.md
Normal file
@@ -0,0 +1,461 @@
|
||||
# TinyCC 编译器改进计划
|
||||
|
||||
Feature Name: 2026-05-20-tinycc-improvements
|
||||
Updated: 2026-05-20
|
||||
|
||||
## Description
|
||||
|
||||
本改进计划涵盖 TinyCC 编译器的 9 个核心改进方向,分为三个阶段:
|
||||
- **阶段一(基础完善)**:端到端测试、错误报告增强、仓库清理
|
||||
- **阶段二(功能完善)**:语义分析、预处理器集成、代码生成优化
|
||||
- **阶段三(高级特性)**:DWARF 调试信息、PE 格式支持、性能基准
|
||||
|
||||
## Architecture
|
||||
|
||||
```mermaid
|
||||
graph TD
|
||||
subgraph "阶段一:基础完善"
|
||||
A1[E2E 测试框架] --> A2[测试用例集合]
|
||||
B1[ErrorReporter 增强] --> B2[代码上下文格式化]
|
||||
C1[.gitignore 更新] --> C2[移除误提交文件]
|
||||
end
|
||||
|
||||
subgraph "阶段二:功能完善"
|
||||
D1[SemanticAnalyzer 完善] --> D2[类型系统增强]
|
||||
D1 --> D3[作用域管理优化]
|
||||
E1[Preprocessor 集成] --> E2[宏展开引擎]
|
||||
E1 --> E3[头文件搜索机制]
|
||||
F1[优化 CodeGen] --> F2[寄存器分配器]
|
||||
F1 --> F3[指令选择优化]
|
||||
end
|
||||
|
||||
subgraph "阶段三:高级特性"
|
||||
G1[DWARF 生成器] --> G2[调试信息编码]
|
||||
G1 --> G3[行号表生成]
|
||||
H1[PE Writer 完善] --> H2[PE 头生成]
|
||||
H1 --> H3[重定位表生成]
|
||||
I1[性能基准] --> I2[编译时间测量]
|
||||
I1 --> I3[执行时间测量]
|
||||
end
|
||||
|
||||
A2 -. 验证 .-> D1
|
||||
B2 -. 集成 .-> D1
|
||||
D3 -. 输入 .-> F2
|
||||
E3 -. 输出 .-> A2
|
||||
```
|
||||
|
||||
### 改进架构概览
|
||||
|
||||
改进计划遵循渐进式实现策略,每个阶段的输出为下一阶段提供基础:
|
||||
|
||||
1. **阶段一**建立测试基础设施和用户体验改进
|
||||
2. **阶段二**完善编译器核心功能
|
||||
3. **阶段三**添加高级特性和性能监控
|
||||
|
||||
## Components and Interfaces
|
||||
|
||||
### 1. 端到端测试框架
|
||||
|
||||
**职责**:
|
||||
- 编译测试 C 源文件并验证生成的可执行文件
|
||||
- 管理测试用例输入和预期输出
|
||||
- 报告测试通过/失败状态
|
||||
|
||||
**接口**:
|
||||
```csharp
|
||||
public interface IE2ETestRunner
|
||||
{
|
||||
Task<TestResult> RunTestAsync(TestCase testCase);
|
||||
IEnumerable<TestCase> LoadTestsFromDirectory(string directory);
|
||||
}
|
||||
|
||||
public record TestCase(
|
||||
string Name,
|
||||
string SourceCode,
|
||||
int ExpectedExitCode,
|
||||
string? ExpectedOutput = null
|
||||
);
|
||||
|
||||
public record TestResult(
|
||||
string TestCaseName,
|
||||
bool Passed,
|
||||
int ActualExitCode,
|
||||
string? ActualOutput = null,
|
||||
string? ErrorMessage = null
|
||||
);
|
||||
```
|
||||
|
||||
**实现策略**:
|
||||
- 使用 `CompilerDriver` 编译源代码到临时 ELF 文件
|
||||
- 使用 `Process` 类执行生成的可执行文件
|
||||
- 比较实际输出/退出码与预期值
|
||||
|
||||
### 2. 错误报告增强
|
||||
|
||||
**职责**:
|
||||
- 格式化错误信息,包含代码上下文
|
||||
- 生成可视化错误位置标记
|
||||
- 支持多错误汇总输出
|
||||
|
||||
**接口扩展**:
|
||||
```csharp
|
||||
public record ErrorInfo(
|
||||
ErrorLevel Level,
|
||||
string Message,
|
||||
SourceLocation Location,
|
||||
string? SourceLine = null, // 新增:出错的源代码行
|
||||
int? ColumnOffset = null, // 新增:错误在行内的偏移
|
||||
string? Suggestion = null // 新增:修复建议
|
||||
);
|
||||
|
||||
public sealed class ErrorReporter : IErrorReporter
|
||||
{
|
||||
private readonly List<ErrorInfo> _errors = new();
|
||||
private readonly Dictionary<string, string[]> _sourceCache = new(); // 新增:源代码缓存
|
||||
|
||||
public void Report(ErrorInfo error);
|
||||
public void SetSourceLines(string fileName, string[] lines); // 新增:设置源代码行
|
||||
public string FormatErrors(); // 新增:格式化所有错误
|
||||
}
|
||||
```
|
||||
|
||||
**格式化输出示例**:
|
||||
```
|
||||
test.c:3:5: error: expected ';' before 'return'
|
||||
2 | int add(int a, int b) {
|
||||
3 | int x = a + b
|
||||
| ^^^^^^^^
|
||||
4 | return x;
|
||||
| ~~~~~
|
||||
help: add ';' at the end of the statement
|
||||
```
|
||||
|
||||
### 3. 语义分析器完善
|
||||
|
||||
**职责扩展**:
|
||||
- 实现完整的类型检查系统
|
||||
- 支持嵌套作用域管理
|
||||
- 检测函数签名不匹配
|
||||
|
||||
**新增组件**:
|
||||
```csharp
|
||||
public sealed class TypeChecker
|
||||
{
|
||||
public CType? CheckBinaryOperation(TokenType op, CType left, CType right, SourceLocation loc);
|
||||
public CType? CheckUnaryOperation(TokenType op, CType operand, SourceLocation loc);
|
||||
public bool IsCompatible(CType source, CType target);
|
||||
public CType? PromoteType(CType type); // 类型提升
|
||||
}
|
||||
|
||||
public sealed class ScopeManager
|
||||
{
|
||||
private readonly Stack<Dictionary<string, Symbol>> _scopes = new();
|
||||
|
||||
public void EnterScope();
|
||||
public void ExitScope();
|
||||
public void DeclareSymbol(string name, Symbol symbol);
|
||||
public Symbol? LookupSymbol(string name);
|
||||
public bool IsDeclared(string name);
|
||||
}
|
||||
```
|
||||
|
||||
**类型检查规则**:
|
||||
| 操作 | 左操作数 | 右操作数 | 结果类型 |
|
||||
|------|---------|---------|---------|
|
||||
| 算术运算 | 整数/浮点 | 整数/浮点 | 提升后的类型 |
|
||||
| 比较运算 | 数值类型 | 数值类型 | int |
|
||||
| 赋值 | 类型 T | 类型 S | T(S 必须可转换为 T) |
|
||||
|
||||
### 4. 预处理器集成
|
||||
|
||||
**职责**:
|
||||
- 处理 `#include`、`#define`、条件编译
|
||||
- 管理头文件搜索路径
|
||||
- 宏展开和参数替换
|
||||
|
||||
**接口**:
|
||||
```csharp
|
||||
public interface IPreprocessor
|
||||
{
|
||||
string Preprocess(string sourceCode, string sourceFile);
|
||||
void AddIncludePath(string path);
|
||||
void DefineMacro(string name, string? value);
|
||||
void UndefineMacro(string name);
|
||||
}
|
||||
|
||||
public sealed class Macro
|
||||
{
|
||||
public string Name { get; }
|
||||
public string? Value { get; }
|
||||
public List<string>? Parameters { get; } // 函数宏参数
|
||||
public string? Body { get; }
|
||||
}
|
||||
```
|
||||
|
||||
**集成到 CompilerDriver**:
|
||||
```csharp
|
||||
// 在 CompilerDriver.Compile 中
|
||||
var preprocessor = new Preprocessor(_errorReporter);
|
||||
foreach (var includePath in options.IncludePaths)
|
||||
{
|
||||
preprocessor.AddIncludePath(includePath);
|
||||
}
|
||||
var preprocessedSource = preprocessor.Preprocess(options.SourceFile);
|
||||
var lexer = new Lexer(preprocessedSource, options.SourceFile, _errorReporter);
|
||||
```
|
||||
|
||||
### 5. 代码生成优化
|
||||
|
||||
**职责**:
|
||||
- 实现图着色寄存器分配
|
||||
- 指令选择和调度
|
||||
- 栈帧布局优化
|
||||
|
||||
**寄存器分配器接口**:
|
||||
```csharp
|
||||
public sealed class GraphColoringAllocator
|
||||
{
|
||||
private readonly Dictionary<IrValue, HashSet<IrValue>> _interferenceGraph = new();
|
||||
private readonly Dictionary<IrValue, string> _allocation = new();
|
||||
private readonly HashSet<IrValue> _spilledVars = new();
|
||||
|
||||
public void Allocate(IrFunction function, string[] availableRegs);
|
||||
public string? GetRegister(IrValue value);
|
||||
public bool IsSpilled(IrValue value);
|
||||
}
|
||||
```
|
||||
|
||||
**优化验证策略**:
|
||||
- 比较优化前后生成的机器码长度
|
||||
- 验证优化后程序的执行结果正确性
|
||||
- 测量溢出变量数量
|
||||
|
||||
### 6. DWARF 调试信息生成器
|
||||
|
||||
**职责**:
|
||||
- 生成 DWARF 调试信息节
|
||||
- 编码源文件路径和行号映射
|
||||
- 生成变量和类型调试信息
|
||||
|
||||
**接口**:
|
||||
```csharp
|
||||
public sealed class DwarfGenerator
|
||||
{
|
||||
private readonly List<DwarfInfo> _debugInfo = new();
|
||||
private readonly List<DwarfLine> _lineTable = new();
|
||||
|
||||
public void AddFile(string fileName);
|
||||
public void AddLineEntry(int fileIndex, int line, int address);
|
||||
public void AddVariable(string name, CType type, int scopeLevel, int offset);
|
||||
public byte[] GenerateDebugSection();
|
||||
public byte[] GenerateLineSection();
|
||||
}
|
||||
```
|
||||
|
||||
**ELF 集成**:
|
||||
- 在 `ElfWriter` 中添加 `.debug_info`、`.debug_line` 节
|
||||
- 更新节头表和字符串表
|
||||
|
||||
### 7. PE 写出器完善
|
||||
|
||||
**职责**:
|
||||
- 生成完整的 PE32+ 文件头
|
||||
- 创建 `.text` 和 `.data` 节
|
||||
- 处理重定位和导入表
|
||||
|
||||
**PE 文件结构**:
|
||||
```
|
||||
DOS Header (64 bytes)
|
||||
PE Signature ("PE\0\0")
|
||||
COFF File Header (20 bytes)
|
||||
Optional Header (PE32+, 112 bytes)
|
||||
Data Directories (16 entries)
|
||||
Section Headers (40 bytes per section)
|
||||
.text Section (代码)
|
||||
.data Section (数据)
|
||||
```
|
||||
|
||||
### 8. 性能基准测试框架
|
||||
|
||||
**职责**:
|
||||
- 测量编译时间
|
||||
- 测量生成代码执行时间
|
||||
- 生成统计报告
|
||||
|
||||
**接口**:
|
||||
```csharp
|
||||
public sealed class BenchmarkRunner
|
||||
{
|
||||
public BenchmarkResult RunCompilationBenchmark(string sourceFile, int iterations = 10);
|
||||
public BenchmarkResult RunExecutionBenchmark(string executable, int iterations = 100);
|
||||
}
|
||||
|
||||
public record BenchmarkResult(
|
||||
string TestName,
|
||||
double MeanTimeMs,
|
||||
double MedianTimeMs,
|
||||
double StdDevMs,
|
||||
int Iterations
|
||||
);
|
||||
```
|
||||
|
||||
## Data Models
|
||||
|
||||
### 错误信息模型(增强)
|
||||
|
||||
```csharp
|
||||
public enum ErrorLevel
|
||||
{
|
||||
Warning,
|
||||
Error,
|
||||
Fatal
|
||||
}
|
||||
|
||||
public readonly struct SourceLocation
|
||||
{
|
||||
public string FileName { get; }
|
||||
public int Line { get; }
|
||||
public int Column { get; }
|
||||
public int Length { get; } // 新增:错误跨度
|
||||
}
|
||||
```
|
||||
|
||||
### 测试用例模型
|
||||
|
||||
```csharp
|
||||
public record TestCase(
|
||||
string Name,
|
||||
string SourceCode,
|
||||
int ExpectedExitCode,
|
||||
string? ExpectedOutput = null,
|
||||
string? ExpectedErrorPattern = null // 期望的错误模式
|
||||
);
|
||||
```
|
||||
|
||||
### DWARF 调试信息模型
|
||||
|
||||
```csharp
|
||||
public record DwarfInfoEntry(
|
||||
uint Offset,
|
||||
uint AbbrevCode,
|
||||
Dictionary<uint, object> Attributes
|
||||
);
|
||||
|
||||
public record DwarfLineEntry(
|
||||
int Address,
|
||||
int FileIndex,
|
||||
int Line,
|
||||
int Column,
|
||||
bool IsStatement,
|
||||
bool IsEndOfSequence
|
||||
);
|
||||
```
|
||||
|
||||
## Correctness Properties
|
||||
|
||||
### 不变量
|
||||
|
||||
1. **测试覆盖完整性**: 每个 C 语言特性至少有一个 E2E 测试用例
|
||||
2. **错误信息准确性**: 错误位置标记必须指向正确的源代码行和列
|
||||
3. **类型检查健全性**: 类型检查必须拒绝所有类型错误的程序
|
||||
4. **寄存器分配正确性**: 分配的寄存器不能干涉活跃变量
|
||||
5. **调试信息一致性**: 调试信息中的行号必须与实际代码位置匹配
|
||||
|
||||
### 约束条件
|
||||
|
||||
1. E2E 测试必须在 Linux x64 环境下运行
|
||||
2. 错误报告格式化器必须处理多字节字符
|
||||
3. 寄存器分配器必须遵循 System V AMD64 ABI
|
||||
4. DWARF 信息必须兼容 gdb 7.0+
|
||||
5. PE 文件必须兼容 Windows 10+ 加载器
|
||||
|
||||
## Error Handling
|
||||
|
||||
### 错误场景与处理策略
|
||||
|
||||
| 错误场景 | 检测阶段 | 处理方式 |
|
||||
|---------|---------|---------|
|
||||
| 头文件不存在 | 预处理 | 报告错误,提供搜索路径 |
|
||||
| 宏重复定义 | 预处理 | 报告警告,使用新定义 |
|
||||
| 未声明变量 | 语义分析 | 报告错误,标记位置 |
|
||||
| 类型不匹配 | 语义分析 | 报告错误,显示期望和实际类型 |
|
||||
| 寄存器溢出 | 代码生成 | 溢出到栈,更新栈帧布局 |
|
||||
| DWARF 编码失败 | 调试信息生成 | 报告错误,继续编译 |
|
||||
| PE 头生成失败 | 目标文件写入 | 报告错误,终止编译 |
|
||||
|
||||
### 错误恢复策略
|
||||
|
||||
- **词法/语法错误**: 尝试跳过错误 token,继续解析
|
||||
- **语义错误**: 收集所有错误,一次性输出
|
||||
- **代码生成错误**: 立即终止,报告详细错误信息
|
||||
|
||||
## Test Strategy
|
||||
|
||||
### 单元测试
|
||||
|
||||
1. **错误报告测试**: 验证错误信息格式化和代码上下文显示
|
||||
2. **类型检查测试**: 验证各种类型场景的检查逻辑
|
||||
3. **寄存器分配测试**: 验证图着色算法正确性
|
||||
4. **DWARF 编码测试**: 验证调试信息编码正确性
|
||||
|
||||
### 集成测试
|
||||
|
||||
1. **端到端测试**: 编译并运行测试 C 程序,验证输出
|
||||
2. **预处理器集成测试**: 验证宏展开和头文件包含
|
||||
3. **PE 格式测试**: 在 Windows 环境验证生成的 PE 文件
|
||||
|
||||
### E2E 测试用例集合
|
||||
|
||||
```c
|
||||
// test_arithmetic.c - 算术运算测试
|
||||
int add(int a, int b) { return a + b; }
|
||||
int main() { return add(3, 4) == 7 ? 0 : 1; }
|
||||
|
||||
// test_control_flow.c - 控制流测试
|
||||
int main() {
|
||||
int sum = 0;
|
||||
for (int i = 1; i <= 10; i++) sum += i;
|
||||
return sum == 55 ? 0 : 1;
|
||||
}
|
||||
|
||||
// test_functions.c - 函数调用测试
|
||||
int factorial(int n) {
|
||||
if (n <= 1) return 1;
|
||||
return n * factorial(n - 1);
|
||||
}
|
||||
int main() { return factorial(5) == 120 ? 0 : 1; }
|
||||
|
||||
// test_pointers.c - 指针测试
|
||||
int main() {
|
||||
int x = 42;
|
||||
int *p = &x;
|
||||
return *p == 42 ? 0 : 1;
|
||||
}
|
||||
|
||||
// test_arrays.c - 数组测试
|
||||
int main() {
|
||||
int arr[3] = {1, 2, 3};
|
||||
return arr[1] == 2 ? 0 : 1;
|
||||
}
|
||||
|
||||
// test_macro.c - 宏测试
|
||||
#define MAX(a, b) ((a) > (b) ? (a) : (b))
|
||||
int main() { return MAX(3, 5) == 5 ? 0 : 1; }
|
||||
```
|
||||
|
||||
### 性能基准测试
|
||||
|
||||
- **编译时间基准**: 测量编译标准 C 文件的时间(如 `factorial.c`, `sort.c`)
|
||||
- **执行时间基准**: 测量生成代码执行时间,与 gcc/clang 对比
|
||||
- **内存使用基准**: 测量编译过程中的内存峰值
|
||||
|
||||
## References
|
||||
|
||||
[^1]: (DWARF Spec) - DWARF 调试标准格式 https://dwarfstd.org
|
||||
[^2]: (PE Spec) - Microsoft PE 和 COFF 规范 https://docs.microsoft.com/en-us/windows/win32/debug/pe-format
|
||||
[^3]: (System V AMD64 ABI) - x64 调用约定 https://github.com/hjl-tools/x86-psABI/wiki/x86-64-psABI-1.0.pdf
|
||||
[^4]: (ELF Spec) - ELF 规范 https://refspecs.linuxfoundation.org/elf/elf.pdf
|
||||
[^5]: (CompilerDriver.cs#L18) - 当前编译器驱动实现 src/TinyCC.Core/CompilerDriver.cs
|
||||
[^6]: (ErrorReporter.cs#L6) - 当前错误报告器实现 src/TinyCC.Core/Diagnostics/ErrorReporter.cs
|
||||
[^7]: (SemanticAnalyzer.cs#L11) - 当前语义分析器实现 src/TinyCC.Core/Semantic/SemanticAnalyzer.cs
|
||||
[^8]: (OptimizedX64CodeGenerator.cs#L12) - 当前优化代码生成器实现 src/TinyCC.Core/CodeGen/OptimizedX64CodeGenerator.cs
|
||||
123
.monkeycode/specs/2026-05-20-tinycc-improvements/requirements.md
Normal file
123
.monkeycode/specs/2026-05-20-tinycc-improvements/requirements.md
Normal file
@@ -0,0 +1,123 @@
|
||||
# Requirements Document
|
||||
|
||||
## Introduction
|
||||
|
||||
本改进计划涵盖 TinyCC 编译器的 9 个核心改进方向,包括端到端测试、错误报告增强、代码清理、语义分析完善、预处理器集成、代码生成优化、调试信息支持、PE 格式支持及性能基准测试。
|
||||
|
||||
## Glossary
|
||||
|
||||
- **TinyCC**: 本项目实现的轻量级 C 编译器
|
||||
- **E2E 测试**: 端到端测试,验证完整编译流程
|
||||
- **ELF**: Executable and Linkable Format,Linux 可执行文件格式
|
||||
- **PE**: Portable Executable,Windows 可执行文件格式
|
||||
- **DWARF**: 调试信息格式,支持源码级调试
|
||||
- **ABI**: Application Binary Interface,应用二进制接口
|
||||
|
||||
## Requirements
|
||||
|
||||
### Requirement 1: 端到端编译测试
|
||||
|
||||
**User Story:** AS 一个编译器开发者,I WANT 验证完整编译流程生成的可执行文件能够正确运行,SO THAT 确保编译器各组件协同工作正常
|
||||
|
||||
#### Acceptance Criteria
|
||||
|
||||
1. WHEN 提供包含 `main` 函数的 C 源代码,编译器 SHALL 生成可在 Linux 上执行的 ELF 文件
|
||||
2. WHEN 运行生成的 ELF 文件,程序 SHALL 返回正确的退出码
|
||||
3. WHEN 编译包含算术运算的 C 程序,执行程序 SHALL 输出正确的计算结果
|
||||
4. WHEN 编译包含函数调用的 C 程序,执行程序 SHALL 正确调用函数并返回结果
|
||||
5. WHEN 编译包含控制流语句(if/while/for)的 C 程序,执行程序 SHALL 正确执行控制流
|
||||
|
||||
### Requirement 2: 增强错误报告
|
||||
|
||||
**User Story:** AS 一个 C 程序员,I WANT 编译器提供包含代码上下文和位置提示的错误信息,SO THAT 能够快速定位和修复代码问题
|
||||
|
||||
#### Acceptance Criteria
|
||||
|
||||
1. WHEN 报告编译错误,错误信息 SHALL 包含文件名、行号和列号
|
||||
2. WHEN 报告语法错误,错误信息 SHALL 显示出错代码行及错误位置标记
|
||||
3. WHEN 报告类型错误,错误信息 SHALL 说明期望的类型和实际提供的类型
|
||||
4. WHEN 报告多个错误,编译器 SHALL 汇总所有错误并一次性输出
|
||||
5. IF 错误信息包含建议,建议 SHALL 提供可能的修复方向
|
||||
|
||||
### Requirement 3: 清理误提交文件
|
||||
|
||||
**User Story:** AS 一个仓库维护者,I WANT 从版本控制中移除构建产物和临时文件,SO THAT 保持仓库整洁并减小仓库体积
|
||||
|
||||
#### Acceptance Criteria
|
||||
|
||||
1. WHEN 提交代码,构建目录 `bin/` 和 `obj/` SHALL 被 `.gitignore` 排除
|
||||
2. WHEN 提交代码,临时测试文件 `test_output` SHALL 从版本控制中移除
|
||||
3. WHEN 提交代码,本地测试文件 `test.c` SHALL 从版本控制中移除
|
||||
|
||||
### Requirement 4: 语义分析器完整实现
|
||||
|
||||
**User Story:** AS 一个 C 编译器开发者,I WANT 语义分析器能够验证程序的语义正确性,SO THAT 拒绝语义错误的 C 程序
|
||||
|
||||
#### Acceptance Criteria
|
||||
|
||||
1. WHEN 遇到未声明的变量,语义分析器 SHALL 报告"未声明的标识符"错误
|
||||
2. WHEN 遇到类型不匹配的赋值操作,语义分析器 SHALL 报告类型不匹配错误
|
||||
3. WHEN 遇到函数调用参数数量不匹配,语义分析器 SHALL 报告参数数量错误
|
||||
4. WHEN 遇到函数调用参数类型不匹配,语义分析器 SHALL 报告参数类型错误
|
||||
5. WHILE 处理嵌套作用域,语义分析器 SHALL 正确解析变量的词法作用域
|
||||
6. WHEN 遇到重复的函数声明,语义分析器 SHALL 报告重复定义错误
|
||||
|
||||
### Requirement 5: 预处理器集成到编译流程
|
||||
|
||||
**User Story:** AS 一个 C 编译器用户,I WANT 编译器正确处理预处理指令,SO THAT 可以编译包含宏和头文件的 C 程序
|
||||
|
||||
#### Acceptance Criteria
|
||||
|
||||
1. WHEN 遇到 `#include` 指令,预处理器 SHALL 展开并包含指定头文件的内容
|
||||
2. WHEN 遇到 `#define` 宏定义,预处理器 SHALL 在后续代码中展开宏
|
||||
3. WHEN 遇到 `#ifdef`/`#ifndef` 条件编译,预处理器 SHALL 根据宏定义情况选择编译分支
|
||||
4. WHEN 预处理完成后,编译器驱动 SHALL 将预处理后的源代码传递给词法分析器
|
||||
5. IF 头文件不存在,预处理器 SHALL 报告错误并提供搜索路径信息
|
||||
|
||||
### Requirement 6: 代码生成优化验证
|
||||
|
||||
**User Story:** AS 一个编译器开发者,I WANT 验证优化后的代码生成器能够正确分配寄存器并生成高效代码,SO THAT 提升生成程序的执行性能
|
||||
|
||||
#### Acceptance Criteria
|
||||
|
||||
1. WHEN 使用优化代码生成器编译函数,寄存器分配算法 SHALL 为活跃变量分配物理寄存器
|
||||
2. WHEN 寄存器数量不足,寄存器分配算法 SHALL 正确地将变量溢出到栈
|
||||
3. WHEN 生成优化后的机器码,程序执行结果 SHALL 与未优化版本一致
|
||||
4. WHILE 分配寄存器,寄存器分配算法 SHALL 遵循调用约定保留被调用者保存的寄存器
|
||||
5. IF 代码生成器生成溢出代码,溢出区域 SHALL 正确管理栈帧布局
|
||||
|
||||
### Requirement 7: DWARF 调试信息生成
|
||||
|
||||
**User Story:** AS 一个 C 程序员,I WANT 编译器生成 DWARF 调试信息,SO THAT 可以使用 gdb 对生成的可执行文件进行源码级调试
|
||||
|
||||
#### Acceptance Criteria
|
||||
|
||||
1. WHEN 启用调试信息选项,编译器 SHALL 在 ELF 文件中生成 `.debug_info` 节
|
||||
2. WHEN 生成调试信息,调试信息 SHALL 包含源文件路径和行号映射
|
||||
3. WHEN 生成调试信息,调试信息 SHALL 包含变量名称、类型和作用域信息
|
||||
4. WHEN 使用 gdb 加载生成的可执行文件,gdb SHALL 能够显示源代码并设置断点
|
||||
5. IF 未启用调试信息选项,编译器 SHALL 不生成调试信息以减小文件体积
|
||||
|
||||
### Requirement 8: PE 格式可执行文件支持
|
||||
|
||||
**User Story:** AS 一个 Windows 用户,I WANT 编译器生成 Windows PE 格式的可执行文件,SO THAT 可以在 Windows 系统上运行编译后的程序
|
||||
|
||||
#### Acceptance Criteria
|
||||
|
||||
1. WHEN 指定目标平台为 Windows x64,编译器 SHALL 生成 PE32+ 格式的可执行文件
|
||||
2. WHEN 生成 PE 文件,PE 文件 SHALL 包含正确的 DOS 头和 PE 签名
|
||||
3. WHEN 生成 PE 文件,PE 文件 SHALL 包含有效的节表(`.text`、`.data`)
|
||||
4. WHEN 运行生成的 PE 文件,Windows 操作系统 SHALL 能够加载并执行程序
|
||||
5. WHEN 生成 PE 文件,PE 文件 SHALL 设置正确的入口点(Entry Point)
|
||||
|
||||
### Requirement 9: 编译性能基准测试
|
||||
|
||||
**User Story:** AS 一个编译器开发者,I WANT 建立编译性能基准,SO THAT 可以量化编译器性能变化并识别性能瓶颈
|
||||
|
||||
#### Acceptance Criteria
|
||||
|
||||
1. WHEN 运行性能基准测试,测试 SHALL 测量编译器处理标准 C 文件的编译时间
|
||||
2. WHEN 运行性能基准测试,测试 SHALL 测量生成代码的执行时间
|
||||
3. WHEN 运行性能基准测试,测试 SHALL 输出编译时间和执行时间的统计报告
|
||||
4. WHILE 进行性能优化,开发者 SHALL 能够对比优化前后的基准测试结果
|
||||
5. IF 性能基准测试发现回归,测试结果 SHALL 标记性能下降的模块
|
||||
80
.monkeycode/specs/2026-05-20-tinycc-improvements/tasklist.md
Normal file
80
.monkeycode/specs/2026-05-20-tinycc-improvements/tasklist.md
Normal file
@@ -0,0 +1,80 @@
|
||||
# TinyCC 改进计划 - 任务列表
|
||||
|
||||
Feature Name: 2026-05-20-tinycc-improvements
|
||||
Created: 2026-05-20
|
||||
|
||||
## 阶段一:基础完善
|
||||
|
||||
### Task 1.1: 创建端到端测试框架
|
||||
|
||||
- [ ] 1.1.1 创建 `TinyCC.E2ETests` 测试项目,配置 xUnit 测试框架
|
||||
- [ ] 1.1.2 实现 `E2ETestRunner` 类,支持编译 C 源代码并执行生成的 ELF 文件
|
||||
- [ ] 1.1.3 实现测试用例管理,支持从嵌入式代码或文件加载测试用例
|
||||
- [ ] 1.1.4 编写基础测试用例:算术运算、控制流、函数调用
|
||||
- [ ] 1.1.5 运行端到端测试,验证当前编译器功能,记录失败项
|
||||
|
||||
### Task 1.2: 增强错误报告
|
||||
|
||||
- [ ] 1.2.1 扩展 `ErrorInfo` 结构,添加 `SourceLine`、`ColumnOffset`、`Suggestion` 字段
|
||||
- [ ] 1.2.2 在 `ErrorReporter` 中实现源代码行缓存机制
|
||||
- [ ] 1.2.3 实现错误信息格式化器,支持代码上下文和位置标记显示
|
||||
- [ ] 1.2.4 集成到 `CompilerDriver`,在编译前缓存源代码行
|
||||
- [ ] 1.2.5 编写单元测试验证错误格式化输出
|
||||
|
||||
### Task 1.3: 清理误提交文件
|
||||
|
||||
- [ ] 1.3.1 更新 `.gitignore`,确保 `bin/`、`obj/`、`test.c`、`test_output/` 被排除
|
||||
- [ ] 1.3.2 从 git 历史中移除 `test_output` 和 `test.c` 文件
|
||||
- [ ] 1.3.3 验证 `git status` 输出清洁,无构建产物
|
||||
|
||||
## 阶段二:功能完善
|
||||
|
||||
### Task 2.1: 完善语义分析器
|
||||
|
||||
- [ ] 2.1.1 实现完整的 `TypeChecker` 类,支持类型兼容性检查和类型提升
|
||||
- [ ] 2.1.2 完善 `ScopeManager`,支持嵌套作用域和符号查找
|
||||
- [ ] 2.1.3 实现函数签名验证,检测参数数量和类型不匹配
|
||||
- [ ] 2.1.4 实现重复声明检测(函数和全局变量)
|
||||
- [ ] 2.1.5 编写单元测试验证类型检查和作用域管理
|
||||
|
||||
### Task 2.2: 预处理器集成到编译流程
|
||||
|
||||
- [ ] 2.2.1 完善 `Preprocessor` 类,支持 `#include` 头文件搜索和展开
|
||||
- [ ] 2.2.2 实现 `#define` 宏定义和宏展开(包括函数宏)
|
||||
- [ ] 2.2.3 实现条件编译 `#ifdef`/`#ifndef`/`#endif`/`#if`/`#else`/`#elif`
|
||||
- [ ] 2.2.4 集成预处理器到 `CompilerDriver.Compile` 流程
|
||||
- [ ] 2.2.5 编写单元测试和 E2E 测试验证预处理功能
|
||||
|
||||
### Task 2.3: 代码生成优化验证
|
||||
|
||||
- [ ] 2.3.1 完善 `GraphColoringAllocator` 寄存器分配器实现
|
||||
- [ ] 2.3.2 实现变量溢出到栈的逻辑和栈帧布局管理
|
||||
- [ ] 2.3.3 集成优化代码生成器到 `CompilerDriver`
|
||||
- [ ] 2.3.4 编写测试验证优化前后代码执行结果一致性
|
||||
- [ ] 2.3.5 比较优化前后生成的机器码长度和寄存器使用情况
|
||||
|
||||
## 阶段三:高级特性
|
||||
|
||||
### Task 3.1: DWARF 调试信息生成
|
||||
|
||||
- [ ] 3.1.1 实现 `DwarfGenerator` 类,支持 DWARF 调试信息编码
|
||||
- [ ] 3.1.2 实现行号表生成(`.debug_line` 节)
|
||||
- [ ] 3.1.3 实现变量和类型调试信息(`.debug_info` 节)
|
||||
- [ ] 3.1.4 集成到 `ElfWriter`,添加调试信息节到 ELF 文件
|
||||
- [ ] 3.1.5 使用 gdb 验证生成的调试信息可正确显示源码和设置断点
|
||||
|
||||
### Task 3.2: PE 格式可执行文件支持
|
||||
|
||||
- [ ] 3.2.1 完善 `PeWriter`,生成完整的 PE32+ 文件头
|
||||
- [ ] 3.2.2 实现 `.text` 和 `.data` 节创建和填充
|
||||
- [ ] 3.2.3 实现 PE 入口点设置和重定位处理
|
||||
- [ ] 3.2.4 集成 PE 写出器到 `CompilerDriver` 的 Windows 平台分支
|
||||
- [ ] 3.2.5 验证生成的 PE 文件可在 Windows 环境加载执行
|
||||
|
||||
### Task 3.3: 编译性能基准测试
|
||||
|
||||
- [ ] 3.3.1 实现 `BenchmarkRunner` 类,支持编译时间和执行时间测量
|
||||
- [ ] 3.3.2 创建标准测试用例集合(factorial、sort 等)
|
||||
- [ ] 3.3.3 实现统计报告生成(均值、中位数、标准差)
|
||||
- [ ] 3.3.4 集成到测试框架,支持一键运行基准测试
|
||||
- [ ] 3.3.5 记录初始基准数据,建立性能基线
|
||||
Reference in New Issue
Block a user