# 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 RunTestAsync(TestCase testCase); IEnumerable 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 _errors = new(); private readonly Dictionary _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> _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? 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> _interferenceGraph = new(); private readonly Dictionary _allocation = new(); private readonly HashSet _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 _debugInfo = new(); private readonly List _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 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