我对语言创建和编译器构造很感兴趣,并且已经在这里通过示例进行了研究:http://gnuu.org/2009/09/18/writing-your-own-toy-compiler/。作者使用的是LLVM 2.6,在对LLVM 2.7进行了一些更改后,我得到了所有代码生成代码进行编译。当给编译器输入测试代码时,
int do_math( int a ) {
int x = a * 5 + 3
}
do_math( 10 )
程序正常工作,直到它尝试运行代码,此时它会出现段错误。我正在我的系统上构建LLDB,但与此同时,任何人都会在此LLVM中看到明显的seg错误?
; ModuleID = 'main'
define internal void @main() {
entry:
%0 = call i64 @do_math(i64 10) ; <i64> [#uses=0]
ret void
}
define internal i64 @do_math(i64) {
entry:
%a = alloca i64 ; <i64*> [#uses=1]
%x = alloca i64 ; <i64*> [#uses=1]
%1 = add i64 5, 3 ; <i64> [#uses=1]
%2 = load i64* %a ; <i64> [#uses=1]
%3 = mul i64 %2, %1 ; <i64> [#uses=1]
store i64 %3, i64* %x
ret void
}
输出只是:
Segmentation fault
我的主题是OS X x86_64。
感谢。
答案 0 :(得分:16)
我遇到了同样的问题。我删除了Loren的编译器,除了执行之外,一切正常。
分段错误是由以下事实引起的:
ExecutionEngine * ee = EngineBuilder(module).create();
返回NULL。要查看实际错误,您需要获取错误字符串:
std :: string错误; ExecutionEngine * ee = EngineBuilder(module).setErrorStr(&amp; error).create();
在你的情况下你应该看到:
“无法找到此三联的目标(未注册任何目标)
要解决此问题,您需要致电
InitializeNativeTarget();
但如果你得到:
JIT尚未被链接。
你应该包括:
LLVM / ExecutionEngine / MCJIT.h
将链接JIT引擎。
答案 1 :(得分:0)
您发布的LLVM ASM不是您提供的C代码的正确翻译。您将%a
分配为堆栈变量,然后从中加载未初始化的数据并使用它。您想要做的是命名您的参数%a
并使用该值。请尝试使用此代码:
define internal i64 @do_math(i64 %a) {
entry:
%x = alloca i64 ; <i64*> [#uses=1]
%1 = add i64 5, 3 ; <i64> [#uses=1]
%2 = mul i64 %a, %1 ; <i64> [#uses=1]
store i64 %2, i64* %x
ret void
}
此外,您的main()
原型可能与C运行时库所期望的不匹配。而且,除此之外,您确实意识到您没有从do_math()
返回结果,对吧?