LLVM 项目博客

LLVM 项目新闻和来自战壕的细节

交互式编程的又一进步

我们很高兴地宣布 编译器研究 团队成功完成了另一轮实习项目,专注于交互式编程方面的增强,特别是与 LLVM 中的 Clang-REPL 组件相关的增强。

编译器研究团队包括普林斯顿大学和欧洲核子研究组织的科研人员。我们的主要目标可以用以下描述来概括

在 LLVM 中建立一个高效的工作流程,使 C++ 的 交互式开发 成为可能,并让更多的人能够体验探索性的 C++ 编程。

以下是今年实习生们的一些突出贡献。

傅宇泉 - Clang-REPL 中的代码自动完成

Clang-Repl 允许开发人员在 REPL 环境中以交互方式使用 C++ 编程。但是,它缺少为用户输入提供代码完成或自动完成选项的功能,这可能会很耗时,而且容易出现输入错误。

有了这个代码完成系统,用户可以快速完成输入,或者查看有效完成候选的列表。代码完成也是上下文感知的,根据当前位置和当前行上的输入提供语义相关的结果。

导师:Vassil Vassilev (普林斯顿大学) & David Lange (普林斯顿大学)

项目详情:Clang-REPL 中的代码自动完成

资金来源:2023 年 Google 暑期代码编程

示例 - 避免冗长的输入

clang-repl> struct WhateverMeaningfulLoooooooooongName{ int field;};
clang-repl> Wh<tab>

使用代码完成功能,按 Tab 键可以完成实体名称

clang-repl>  WhateverMeaningfulLoooooooooongName

有关实施细节,请参阅相应的 幻灯片博客

阿努巴布·戈什 - Clang-REPL 的 WebAssembly 支持

Xeus 框架可以通过 Jupyter 在 Web 浏览器中访问 Clang-REPL(一个将 C++ 代码 JIT 编译为本机代码的解释器)。但是,这会将计算负载转移到服务器端。

更具可扩展性的方法是使用 WebAssembly。它允许对编译为中间字节码的本机(例如 C/C++/Rust)程序进行沙箱执行,速度接近本机速度。这个想法是在 WebAssembly 中运行 clang-repl,并生成 JIT 编译的 WebAssembly 代码并在客户端执行。

但是,这会带来一些挑战(例如,WebAssembly 中的代码是不可变的,这对 JIT 来说是不可接受的)。

解决方案:为了解决代码不可变性问题,在 REPL 循环的每次迭代时都会创建一个新的 WebAssembly 模块。最初,一个包含标准 C/C++ 库、LLVM、Clang 和 wasm-ld 的预编译模块会被发送到浏览器,浏览器运行解释器并编译用户代码。

由于我们不能调用 Interpreter::Execute() 来执行模块(由于依赖 JITLink),因此手动使用 LLVM WebAssembly 后端来生成一个目标文件。然后将该文件传递给 WebAssembly 版本的 LLD (wasm-ld),将其转换为共享库,并写入 Emscripten 的虚拟文件系统。Emscripten 的动态链接功能可以用来加载这个库。

导师:Vassil Vassilev (普林斯顿大学) & Alexander Penev (Uni-Plovdiv.bg)

项目详情:Clang-REPL 的 WebAssembly 支持

资金来源:2023 年 Google 暑期代码编程

示例

SDL_Init(SDL_INIT_VIDEO);
SDL_Window *window;
SDL_Rendered *renderer;
SDL_CreateWindowAndRenderer (300, 300, 0, &window, &renderer);

这应该连接到一个简单的黑色画布。接下来,我们可以在上面绘制东西。

SDL_SetRenderDrawColor(renderer, 0x80, 0x00, 0x00, 0xFF);
SDL_Rect rect3 = {.x = 20, .y = 20, .w = 150, .h = 100};
SDL_RenderFillRect(rendered, &rect3);
 
SDL_SetRenderDrawColor(renderer, 0x00, 0x80, 0x00, 0xFF);
SDL_Rect rect4 = {.x = 40, .y = 40, .w = 150, .h = 100};
SDL_RenderFillRect(rendered, &rect4);
 
SDL_RenderPresent(renderer);

输出应该类似于以下内容

Web Assembly Example

为了支持重新优化,JITLink API 通过添加跨架构存根创建 API 进行了扩展。这个 API 在 JITLink 支持的所有平台和架构上都能工作,通过它我们可以使用 JITLink 创建可重定向的存根。

一旦重新优化 API 开发完成,就该真正实施重新优化了。引入了一个新层来支持对 IR 模块进行重新优化。有很多抽象层可以实现重定向,但我们最终是在 IR 层实现它,因为这带来了很多重新优化技术,可以通过直接转换 IR 来轻松实现。从 API 的角度来看,最灵活的抽象层可能是前端 AST 层。

Clang-REPL 依赖于 LLJIT 来执行与 JIT 相关的任务。为 LLJIT 启用重新优化也有助于在 Clang-REPL 中启用它。但是,也存在一些小挑战(例如,clang-repl 对运行时执行静态初始化程序的方式与 ELF orc 运行时执行的方式不匹配)。这些问题的可能解决方案正在讨论中(例如,添加一个新的 dl 函数)。尽管如此,我们现在拥有一个真实的实验环境,可以在其中测试新的重新优化技术并执行基准测试,以查看它们是否有用。

最后,基于上述基础设施,现在可以进行配置文件引导优化(通过转换 IR 模块)。在代码完全上游之前,还需要进行一些增强,但目前的代码在 orc-runtime 侧实现了 instrumentation,这在很大程度上简化了实现。

导师:Vassil Vassilev (普林斯顿大学) & Lang Hames/ lhames (苹果公司)

项目详情:使用 JITLink 进行重新优化

资金来源:2023 年 Google 暑期代码编程

示例:如果函数调用次数超过 10 次,则执行 -O2 优化

以下示例使用 LLVM 库构建 PassManager,然后运行优化管道。

static Error reoptimizeTo02(ReOptimizeLayer &Parent, ReOptMaterializationUnitID MUID,
    unsigned Curverison, ResourceTrackerSP OldRT, ThreadSafeModule &TSM) {
      TSM.withModuleDo([&]{llvm::Module &M) {
         auto PassManager = buildPassManager();
         PassManager.run(M);
        });
        return Error::success();
}
ReOptLayer ->setReoptimizeFunc(reoptimizeTo02);
ReOptLayer ->setAddProfileFunc(reoptimizeIfCallFrequent);

有关更多示例,请参阅 LLVM-JITLink-COFF-Example 存储库。

克里希纳·纳拉亚南 - 使用 clang-repl 进行教程开发

开源文档在软件生命周期中经常被忽视。具体来说,这个项目的目标是通过记录如何为贡献者在本地机器上设置各自的环境,从而帮助他们为项目的代码和文档做出贡献。这些环境是在本地设置的,经过测试,然后将设置方法更新到相关的文档中。

除了其他编译器研究技术,在这个项目中还为 LLVM(特别是 Clang-Repl 文档)添加了说明性文字。还添加了使用示例。

导师:Vassil Vassilev (普林斯顿大学) & David Lange (普林斯顿大学)

项目详情:使用 clang-repl 进行教程开发

资金来源:2023 年 Google 暑期代码编程

示例

// Classes and Structures
clang-repl> #include <iostream>
clang-repl> class Rectangle {int width, height; public: void set_values (int,int);\
clang-repl... int area() {return width*height;}};
clang-repl>  void Rectangle::set_values (int x, int y) { width = x;height = y;}
clang-repl> int main () { Rectangle rect;rect.set_values (3,4);\
clang-repl... std::cout << "area: " << rect.area() << std::endl;\
clang-repl... return 0;}
clang-repl> main();
area: 12