当查看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
?
答案 0 :(得分: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)
参数是:
签名@ivarne show是专门的调用约定。参数仍然是盒装的,但参数类型和计数已经知道了(并且函数闭包是不必要的,因为它已经是专用的)。
关于示例函数的输出,此部分检查参数的数量(如果不是3 - >转到标签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
答案 1 :(得分: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
}
这可能被认为是代码生成中的一个错误,但我不知道。