commit initial
This commit is contained in:
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
|
||||
Reference in New Issue
Block a user