Block的本质及变量截取

本文的内容主要是基于Clang编译器的官方文档所写。

在开始探索Block的本质之前,大家先试着分析一下,下面的代码会输出什么:

void main() {
__block int a = 13;
int b = 13;
NSMutableString* str = [[NSMutableString alloc] initWithString:@"Hello"];
void(^blockTest)(void) = ^{
NSLog(@"a = %d, b = %d, str = %@", a, b, str);
};
a++;
b++;
[str appendString:@"World"];
blockTest();
}

如果你对输出结果不是那么有把握的话,那么相信通过今天的这篇文章,你会有一个明确的答案。

LLVM里的寄存器分配 - 准备工作(一)

背景介绍

本文档是基于LLVM 的寄存器分配系列科研笔记第一篇,以一个C语言程序为主干介绍LLVM在寄存器分配前做的一些主要工作,分析在寄存器分配前期可能的写操作来源,并记录了我在研究LLVM 后端中 SSA 形式的中间表示时的一些想法。

进入寄存器分配

我们以下述 C 语言源码为例开始本文的说明:

int foo(int a, int b, int e) {
b = a + e;
a = b * e;
e = a * b;
b = a * e;
b = b * e;
return b;
}

深入浅出的理解LLVM

LLVM项目是模块化、可重用的编译器以及工具链技术的集合。

美国计算机协会 (ACM) 将其2012年软件系统奖项颁给了LLVM,之前曾经获得此奖项的软件和技术包括:Java、Apache、Mosaic、the World Wide Web、Smalltalk、UNIX、Eclipse等等

创始人: Chris Lattner,亦是Swift之父

什么是LLVM

传统的编译器架构

  • Frontend:前端
    词法分析、语法分析、语义分析、生成中间代码
  • Optimizer:优化器
    中间代码优化
  • Backend:后端
    生成机器码

自己动手写LLVM Pass 三

LLVM Pass官方教程会教您如何编译一个相当简单的(Legacy)LLVM Pass,她能够被opt动态加载。但现在你是一个懒惰的家伙,你想自动的在opt 甚至clang中运行您的Pass。本文提供了将Pass集成到旧版PassManager管道的几种方法之一。然后,我的下一篇文章将讨论如何添加自定义clang命令行选项以启用自定义功能。

默认情况下,要在Pass管道中运行Pass,我们需要先弄清楚管道是如何构建的。有一个构建器类,PassManagerBuilder用于构建旧版PassManager以及默认的Pass管道。其中生成器类所在的路径,但是,它有点陌生-它放在include/llvm/Transforms/IPO/PassManagerBuilder.hlib/Transform/IPO/PassManagerBuilder.cpp,而不是我们所熟悉的IRPassManager文件夹。

自己动手写LLVM Pass 四

在stackoverflow上有关LLVM的最常见问题之一是:我写了一个Hello World Pass,如何使用clang来运行它,而不是opt?

最常见的解决方案之一是单独使用(传统)PassManager扩展点和-Xclang -load -Xclang MyPass.so命令行选项。

然而,我想知道:

我可以通过简单地将一个命令行选项传递给clang来运行我的Pass或自定义功能吗?

当然,这需要对LLVM源代码树进行一些更改。但我相信这将是学习clang内部以及它如何与LLVM交互的好方法。所以这里有一个简单但又有趣的教程。让我们开始吧!

自己动手写LLVM Pass 二

收集程序分析的任务也被建模为LLVM PassManager中的Pass,除了它们从不(也不应该)修改IR。此外,与传统的PassManager相比,分析数据在新的PassManager中以不同的方式进行管理和开发,我决定使用单独的文章来介绍它。

本文将讨论如何使用新的AnalysisManager检索分析数据。

所以抓住你最喜欢的编辑器,让我们开始吧!

自己动手写LLVM Pass 一

PassManager系统是LLVM中最重要的基础架构之一。

经过大约10多年的努力,开发人员决定给她一个新的面目。

新的PassManager Pass背后的基本概念仍然与旧版本相同:通过LLVM IR单元运行Pass,例如,功能来检查内部的IR或甚至修改它,然后将结果IR传递给下一个Pass管道。最大的区别是我们写Pass的方式。

新Pass和新PassManager背后有几种设计理念。我强烈建议读者查看过去LLVM开发者大会的相关讲座。但我不打算详细介绍。本文仅通过简单的HelloNewPM Pass 作为新PassManager系统的预告。让我们亲自动手吧!

通常,编写(遗留)LLVM Pass的教程将首先告诉您编写一个继承其中一个llvm::Pass族的类, 例如llvm::FunctionPass , 然后实现一些必要的方法,比如bool FunctionPass::runOnFunction(Function &F)

自己动手写LLVM pass(零)

您已经跟随着LLVM的官方教程完成了HelloWorld pass…..

现在,您想学的更多,看更多的代码,例子……

因此,您可以深入到无比优秀的LLVM源代码树,了解这些着名且功能强大的优化如何通过pass实现的…

但结果却是被异乎寻常的传递构造语法所迷惑,这种语法既不类似于你刚刚遵循的教程,也没有在官方网站的任何地方记录

这正是我几年前碰到的,当时,我还是一个LLVM新手和LLVM pass是我之前听到的唯一的事情。

编写LLVM的后端(一)

本文档是指如何编写一个可以把LLVM的中间表示转换成一个特定的机器或者其他语言的后端。对于一个特定机器的代码或者是汇编语言或者是二进制代码。

llvm后端的是一个和目标相关的代码产生器,可以创建不同类型的目标处理器的输出,如x86,powerpc, alpha, sparc。后端也可以用于产生针对Cell处理器的SPU或者GPU来支持计算内核的执行。

文档重点描述了在llvm/lib/Target子目录下存在的一些例子。特别的,文档描述了如何创建一个静态编译器(一个产生文本汇编)。sparc有相对标准的特性,如RISC指令集和一个比较直接的调用约定。

函数栈2:gcc及llvm中x86机器的栈分配

假设:

  • 假设有函数main, f1,f2和g。其中,mainf1和f2,并且f1调用g,f2和g不再调用任何函数。
  • 栈空间从高地址往低地址增长(linux是这样的)。
  • 假设编译时没有开启eliminate frame pointer优化。如果开启该优化的话,对于参数固定的函数,不需要使用EBP寄存器来存储当前frame pointer。
  • 如下的栈布局只是一般的情况,对于一些特殊编译器优化,还会有其它的元素。
  • 本文也不讨论关于栈帧对齐以及栈内数据对齐的问题。