3

在查看 julia 编译器生成的 LLVM IR 时(使用code_llvm),我注意到在使用数组作为参数时函数签名中有一些奇怪的地方。让我举个例子:

function test(a,b,c)
    return nothing
end

(这是一个无用的示例,但结果与其他函数相同,此示例的结果 IR 只是不那么混乱)

使用code_llvm(test, (Int,Int,Int)),我得到以下输出:

; Function Attrs: sspreq
define void @julia_test14855(i64, i64, i64) #2 {
top:
  ret void, !dbg !366
}

使用code_llvm(test, (Array{Int},Array{Int},Array{Int})),我得到了(至少对我而言)意想不到的结果:

; Function Attrs: sspreq
define %jl_value_t* @julia_test14856(%jl_value_t*, %jl_value_t**, i32) #2 {
top:
  %3 = icmp eq i32 %2, 3, !dbg !369
  br i1 %3, label %ifcont, label %else, !dbg !369

else:                                             ; preds = %top
  call void @jl_error(i8* getelementptr inbounds ([26 x i8]* @_j_str0, i64 0, i64 0)), !dbg !369
  unreachable, !dbg !369

ifcont:                                           ; preds = %top
  %4 = load %jl_value_t** inttoptr (i64 36005472 to %jl_value_t**), align 32, !dbg !370
  ret %jl_value_t* %4, !dbg !370
}

为什么 llvm 函数的签名不只是列出 3 个变量i64*或类似的东西?为什么函数void不再返回?

4

2 回答 2

4

Why is the signature of the llvm function not just listing the 3 variables as i64*

这个签名是通用的 Julia 调用约定(因为,正如@ivarne 提到的,类型不完整)。

@julia_test14856(%jl_value_t*, %jl_value_t**, i32)论据是:

  1. 指向函数闭包的指针
  2. 指向盒装参数的指针(jl_value_t 是基本盒型)
  3. 参数数量

@ivarne 显示的签名是专门的调用约定。参数仍然是装箱传递的,但参数类型和计数已经知道(并且函数闭包是不必要的,因为它已经是专门的)。

关于示例函数的输出,本节检查参数的数量(如果不是 3 -> goto label else:):

top:
  %3 = icmp eq i32 %2, 3, !dbg !369
  br i1 %3, label %ifcont, label %else, !dbg !369

本节返回错误:

else:                                             ; preds = %top
  call void @jl_error(i8* getelementptr inbounds ([26 x i8]* @_j_str0, i64 0, i64 0)), !dbg !369
  unreachable, !dbg !369

最后,默认情况下进入这一行,该行提取nothing存储在地址中的值36005472(在@ivarne 版本中,这是有保证的,因此可以void直接返回)。

%4 = load %jl_value_t** inttoptr (i64 36005472 to %jl_value_t**), align 32, !dbg !370

于 2014-02-19T15:51:39.443 回答
2

我会假设这是因为它Array{Int, N}是一个部分初始化的类型,并且它与代码生成寻找的模式不匹配。

也试试

julia> code_llvm(test, (Array{Int,1},Array{Int,1},Array{Int,1}))

define void @julia_test15626(%jl_value_t*, %jl_value_t*, %jl_value_t*) {
top:
  ret void, !dbg !974
}

这可能被认为是代码生成中的错误,但我不知道。

于 2014-02-19T11:49:56.740 回答