以下代码目前在lli中不起作用:
//main.cpp
extern thread_local int tls;
int main() {
tls = 42;
return 0;
}
//clang++ -S -emit-llvm main.cpp && lli main.ll
Run Code Online (Sandbox Code Playgroud)
LLVM-IR:
; ModuleID = 'main.cpp'
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-pc-linux-gnu"
@tls = external thread_local global i32, align 4
; Function Attrs: norecurse uwtable
define i32 @main() #0 {
%1 = alloca i32, align 4
store i32 0, i32* %1, align 4
%2 = call i32* @_ZTW3tls()
store i32 42, i32* %2, align 4
ret i32 …
Run Code Online (Sandbox Code Playgroud) 编译的一个趋势是使用类型化的中间语言.Haskell的ghc
与它的core
中间语言,系统F-ω变体,是本体系结构[1]的一个例子.另一个是LLVM,它的核心是一种类型化的中间语言[2].这种方法的好处是可以及早检测构成代码生成器部分的转换中的错误.此外,可以在优化和代码生成期间使用类型信息.
为了提高效率,对类型化的IR进行类型检查,而不是推断它们的类型.为了快速进行类型检查,每个变量和每个活页夹都带有类型以便于类型检查.
但是,编译器管道中的许多转换可能会引入新变量.例如,规范化转换K(.)
可能会转换应用程序
M(N)
Run Code Online (Sandbox Code Playgroud)
变成一个表达式
let x = K(M) in
let y = K(N) in x(y)
Run Code Online (Sandbox Code Playgroud)
题.我想知道编译器如何处理给新引入的变量赋予类型的问题.难道他们重新类型检测,在上面的例子中K(M)
和K(N)
?这不是很费时间吗?它需要通过环境吗?他们是否使用AST节点中的映射来键入信息以避免重新运行类型检查?
S. Marlow,S.Peyton Jones,格拉斯哥Haskell编译器.
compiler-construction ghc intermediate-language compiler-optimization llvm-ir
我已经在llvm.org上使用在线编译器生成了一个bc文件,我想知道是否可以从ac或c ++程序加载这个bc文件,用llvm jit执行bc文件中的IR(以编程方式在c程序),并得到结果.
我怎么能做到这一点?
假设我有以下简单的C头文件:
// foo1.h
typedef int foo;
typedef struct {
foo a;
char const* b;
} bar;
bar baz(foo*, bar*, ...);
Run Code Online (Sandbox Code Playgroud)
我的目标是获取此文件,并生成一个如下所示的LLVM模块:
%struct.bar = type { i32, i8* }
declare { i32, i8* } @baz(i32*, %struct.bar*, ...)
Run Code Online (Sandbox Code Playgroud)
换句话说,将.h
带有声明的C 文件转换为等效的LLVM IR,包括类型分辨率,宏扩展等.
通过Clang传递它来生成LLVM IR会产生一个空模块(因为实际上没有使用任何定义):
$ clang -cc1 -S -emit-llvm foo1.h -o -
; ModuleID = 'foo1.h'
target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-apple-darwin13.3.0"
!llvm.ident = !{!0}
!0 = metadata !{metadata !"clang version 3.5 (trunk 200156) (llvm/trunk 200155)"}
Run Code Online (Sandbox Code Playgroud)
我的第一直觉是转向谷歌,我遇到了两个相关的问题:一个来自邮件列表 …
首先,我是LLVM通行证的新手.
我试图在转换过程之后(使用C++ API)向LLVM中的指令添加元数据.我打算存储此信息以供工具链中的其他工具使用.我有两个问题.
我希望我存储的信息作为元数据提供给另一个工作在LLVM IR上的工具.元数据是个好主意吗?我打算将字符串存储为带有一些指令的元数据.
如果元数据是正确的方式,我需要一些帮助来创建元数据节点.我打算使用setMedata()函数将它附加到指令.setMetadata()的哪个变体是正确使用的变体.我不确定我的数据应该是哪个MDKind.我想创建一个MDString,将它附加到我的MDNode,然后用一条指令调用setMetadata().如果我想将元数据附加到函数内的指令,我应该在setMedata()中使用什么上下文.上下文与元数据的相关性是什么?
我尝试在论坛和llvm doxygen文档中阅读了很多讨论,但我没有得到一个清晰而完整的答案来回答我的所有问题.我感谢您的帮助或一些可以帮助我理解这一点的材料.
llvm::User
(例如指令)的操作数是llvm::Value
s.
在mem2reg传递之后,变量采用SSA形式,并且它们与原始源代码对应的名称将丢失. Value::getName()
只是针对某些事情; 对于大多数变量,它们是中介,它没有设置.
该instnamer通可以运行给所有的变量的名称,如TMP1和TMP2,但这并不能捕捉到他们最初来自.这是原始C代码旁边的一些LLVM IR:
我正在构建一个简单的html页面来可视化和调试我正在进行的一些优化,并且我想将SSA变量显示为名称ver表示法,而不仅仅是临时的instnamer名称.它只是为了帮助我的可读性.
我通过命令行来获取我的LLVM IR,例如:
clang -g3 -O1 -emit-llvm -o test.bc -c test.c
Run Code Online (Sandbox Code Playgroud)
在国际关系中有电话llvm.dbg.declare
和电话llvm.dbg.value
; 你如何变成原始的源代码名称和SSA版本号?
那么如何从一个llvm::Value
?确定原始变量(或命名常量名称)?调试器必须能够做到这一点,所以我该怎么办?
现在我们按照本教程实现llvm的分析传递.并需要将一个额外的参数传递给插件,如下所示:
opt -load /path/to/myplugin.so -mypass -mypass_option input.bc
Run Code Online (Sandbox Code Playgroud)
但是我没有找到任何手册告诉我该怎么做.所以我想知道它是否有可能在实践中.
提前致谢.
我一直在尝试构建和执行LLVM模块.我生成模块的代码很长,所以我不会在这里发布.相反,我的问题是Clang和LLVM如何协同工作来实现名称修改.我会解释我的具体问题来激发这个问题.
以下是我的一个LLVM模块的源代码:
#include <iostream>
int main() {
std::cout << "Hello, world. " << std::endl;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
这是生成的LLVM IR ; 它对于StackOverflow来说太大了.
当我尝试使用我的模块时lli
,我收到以下错误:
LLVM错误:程序使用了无法解析的外部函数'__ZNSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEC1Emc'!
通过demangler运行符号,缺少的符号是:
_std :: __ 1 :: basic_string,std :: __ 1 :: allocator> :: basic_string(unsigned long,char)
额外_
是可疑的,没有前导下划线的功能似乎存在于IR中!
; Function Attrs: alwaysinline ssp uwtable
define available_externally hidden void @_ZNSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEC1Emc(%"class.std::__1::basic_string"*, i64, i8 signext) unnamed_addr #2 align 2 {
%4 = alloca %"class.std::__1::basic_string"*, align 8
%5 = alloca i64, align 8
%6 = alloca i8, align 1 …
Run Code Online (Sandbox Code Playgroud) 我正在研究LLVM系统,我已经阅读了入门文档.然而,一些命名法(以及铿锵例中的措辞)仍然有点令人困惑.以下术语和命令都是编译过程的一部分,我想知道是否有人能够更好地解释它们对我来说:
clang -S
vs. clang -c
(我知道是什么-c
,但结果如何不同?)*(编辑)在一个较高的水平,我了解整个编译过程,并且可以通过跟踪我的路还算好,我只是陷在一些点在哪里,例如,我期待看到"IR",而是看"位码"或" LLVM汇编"这让我认为我不理解它们几乎和我应该的一样!
我正在尝试为我最近设计的自定义处理器编写LLVM后端.
我试着按照http://llvm.org/docs/WritingAnLLVMBackend.html上的官方教程进行操作
但它是如此模糊,如此不完整和模糊,我没有遵循它.
然后我开始在线搜索其他教程,所有这些教程都遇到了与原始教程相同的症状.作者似乎在没有必要的初步解释的情况下假设了许多预读并编写了他们的教程.
我怎样才能找到一个教程或任何可以让我在LLVM中编写功能后端的东西?
- 更新:我看到两张投票和两张投票.低票说我的问题与编程无关.我想知道主持人如何得出结论编写编译器与编程无关.