DScript

Tags
codec++
Created
May 29, 2025 1:37 AM

www.51cto.com

与C++内存布局及调用约定深度兼容的动态脚本语言,通过自研编译器实现即时编译与无缝嵌入,尝试在保留脚本灵活性的同时,尽可能贴近C++的原生性能,为性能与效率的平衡提供了轻量化解决方案

image
  • 前端:
    • 词法分析:字符流->记号流(Tokens),使用 Flex,根据自定义的正则表达式规则,自动生成词法分析的扫描器
    • 语法分析:记号流->抽象语法树(AST),采用Bison来实现,Bison可以与Flex进行协作,根据上下文无关文法(CFG)对输入的 tokens 序列进行分析,验证其是否符合某种语言的语法规则,并构建对应的抽象语法树
    • 语义分析、生成中间代码:抽象语法树->中间代码,使用了LLVM IR作为中间代码语言,它介于高级语言和目标代码之间,既能表达高级语言的抽象概念,又能适应底层机器代码的生成需求
      1. 符号表管理

      2. 作用域解析:追踪变量/函数的作用域(如块级作用域、全局作用域)。
      3. 符号绑定:将标识符与其声明关联(如变量类型、函数签名)。
      4. 重复定义检查:禁止同一作用域内同名符号的重复声明。
      5. 类型系统校验

      6. 类型推断与检查:验证表达式和操作的合法性,如 int a = "str"; 类型不匹配。
      7. 隐式类型转换:处理类型提升,如 int + float 自动转为浮点运算。
      8. 函数签名匹配:检查实参与形参的个数、类型一致性。
      9. 控制流合法性

      10. 语句上下文检查:确保 break 仅在循环内、 return 与函数返回类型一致。
      11. 可达性分析:检测不可达代码(如 return 后的语句)。
      12. 常量表达式求值

      13. 优化常量计算(如 const x = 2 + 3*4; 直接计算为 14 )。
      14. 用于数组长度、条件编译等需编译期确定值的场景。
  • 优化器(中端):通过一系列LLVM预置的优化遍(Pass)
  • 数据流分析
    死代码消除 (DCE)
    通过数据流分析,LLVM 能够精确地识别和删除这些无用的指令。
    全局值编号(GVN)
    检测并消除等价的冗余表达式,减少重复计算。
    循环优化
    循环展开  (Loop Unrolling)
    通过展开循环体中的指令,减少循环控制的开销,并增加指令级并行性。
    循环分割  (Loop Split)
    将复杂的循环拆分为多个更简单的循环,以便更好地优化每个循环。
    循环不变代码外提  (LICM)
    将循环中不变的计算移出循环体,从而减少不必要的重复计算。
    控制流优化
    条件合并  (Conditional Merging)
    合并控制流中多余的条件判断,从而简化分支结构。
    跳转线程化  (Jump Threading)
    在控制流图中,将多个条件判断组合为一个单一的跳转,以减少不必要的分支。
    尾调用优化 (TCO)
    优化递归函数调用,使得尾递归调用能够直接重用当前栈帧,从而避免栈溢出。
    内存访问优化
    内存别名分析  (Alias Analysis)
    确定不同指针是否指向相同的内存位置,从而帮助优化器在内存访问上进行优化,如消除冗余的内存加载和存储操作。
    堆栈分配优化  (Stack Allocation Optimization)
    通过分析栈上变量的生命周期,减少不必要的内存分配和释放,或者将栈分配的变量优化到寄存器中。
  • 后端:负责将中间代码转换成目标机器的的机器码
    • 使用 LLVM 的 ORC JIT 作为即时编译器的实现,支持在程序运行时编译脚本,并通过查找函数地址的方式执行脚本
    • 编译器最终输出为x86_64平台的可执行二进制,以JIT实例的方式常驻内存,通过入口函数地址执行
SuperMade with Super