9

我对语言创建和编译器构造感兴趣,并且一直在研究这里的示例: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 asm 中看到明显的段错误吗?

; 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。

谢谢。

4

2 回答 2

17

我遇到了同样的问题。我剥离了 Loren 的编译器,除了执行之外一切正常。

分段错误是由以下事实引起的:

ExecutionEngine *ee = EngineBuilder(module).create();

返回 NULL。要查看实际错误,您需要获取错误字符串:

std::string 错误;ExecutionEngine *ee = EngineBuilder(module).setErrorStr(&error).create();

在您的情况下,您可能应该看到:

“无法找到此三元组的目标(未注册目标)

要解决这个问题,您需要致电

InitializeNativeTarget();

但如果你得到:

JIT 尚未链接。

你应该包括:

llvm/ExecutionEngine/MCJIT.h

这将链接 JIT 引擎。

于 2011-04-29T10:10:29.313 回答
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(),对吗?

于 2010-08-10T09:36:38.117 回答