无法 link 使用 Clang 生成的 IR 自定义生成的 LLVM IR
Cannot link custom generated LLVM IR with Clang generated IR
我一直在尝试 link 使用 llvm 的 C++ api 生成的 IR 与另一个由 Clang++ 生成的 IR 文件。 Clang 的输入文件是一个函数 fn
我正在尝试从第一个 IR 文件调用。但是 llvm-link
不会用其定义替换 fn
的声明。
main_ir.ll
source_filename = "top"
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-pc-linux-gnu"
@0 = private unnamed_addr constant [5 x i8] c"%d [=11=]A[=11=]", align 1
declare i32 @printf(...)
declare i32 @fn(i32, ...)
define internal i32 @main() {
entrypoint:
%f_call = call i32 (i32, ...) @fn(i32 2)
%printfCall = call i32 (...) @printf(i8* getelementptr inbounds ([5 x i8], [5 x i8]* @0,
i32 0, i32 0), i32 %f_call)
br label %ProgramExit
ProgramExit: ; preds = %entrypoint
ret i32 0
}
fn_ir.ll(用 Clang 生成)
source_filename = "libDessin.cpp"
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-pc-linux-gnu"
; Function Attrs: noinline nounwind optnone uwtable
define dso_local i32 @_Z2fni(i32) #0 {
%2 = alloca i32, align 4
store i32 %0, i32* %2, align 4
%3 = load i32, i32* %2, align 4
%4 = mul nsw i32 %3, 2
ret i32 %4
}
attributes #0 = { noinline nounwind optnone uwtable "correctly-rounded-divide-sqrt-fp-
math"="false" "disable-tail-calls"="false" "less-precise-fpmad"="false" "min-legal-vector-
width"="0" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-
math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-
math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "target-
cpu"="x86-64" "target-features"="+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "unsafe-fp-math"="false"
"use-soft-float"="false" }
!llvm.module.flags = !{!0}
!llvm.ident = !{!1}
!0 = !{i32 1, !"wchar_size", i32 4}
!1 = !{!"clang version 9.0.1-12 "}
而所有 llvm-link 所做的就是复制 fn_ir.ll 的内容,并将 source_filename
更改为 llvm-link
。我真的很高兴知道我所缺少的那一点。
答案就在名称修改中。
您的 'manually' 生成的 IR 有一个名为 fn
的函数,而 clang++
发出名称 _Z2fni
.
您需要使名称匹配。在 main_ir.ll
中发出 _Z2fni
,或者(在这种情况下可以更好地争论)在 fn_ir
中更改 fn
的定义,例如:
extern "C" void fn(int x) {
return x * 2;
}
extern "C"
告诉编译器使用 C mangling 约定,这不太脆弱,因为即使您更改 fn
的参数类型或数量,它也会工作。但是,如果你想将 C++ 类型传递给 fn
,它就不起作用,那么你需要为 main_ir.ll
.
发出正确的函数名称
UPD:
还有两个'discrepancies':
fn
在两个模块中有不同的参数:i32
vs i32, ...
- 另一个问题是
main
声明为内部。我猜它只是被剥离了,因为它是内部的并且没有被任何人调用。
所以只需删除 internal
标志就可以完成这项工作。
我一直在尝试 link 使用 llvm 的 C++ api 生成的 IR 与另一个由 Clang++ 生成的 IR 文件。 Clang 的输入文件是一个函数 fn
我正在尝试从第一个 IR 文件调用。但是 llvm-link
不会用其定义替换 fn
的声明。
main_ir.ll
source_filename = "top"
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-pc-linux-gnu"
@0 = private unnamed_addr constant [5 x i8] c"%d [=11=]A[=11=]", align 1
declare i32 @printf(...)
declare i32 @fn(i32, ...)
define internal i32 @main() {
entrypoint:
%f_call = call i32 (i32, ...) @fn(i32 2)
%printfCall = call i32 (...) @printf(i8* getelementptr inbounds ([5 x i8], [5 x i8]* @0,
i32 0, i32 0), i32 %f_call)
br label %ProgramExit
ProgramExit: ; preds = %entrypoint
ret i32 0
}
fn_ir.ll(用 Clang 生成)
source_filename = "libDessin.cpp"
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-pc-linux-gnu"
; Function Attrs: noinline nounwind optnone uwtable
define dso_local i32 @_Z2fni(i32) #0 {
%2 = alloca i32, align 4
store i32 %0, i32* %2, align 4
%3 = load i32, i32* %2, align 4
%4 = mul nsw i32 %3, 2
ret i32 %4
}
attributes #0 = { noinline nounwind optnone uwtable "correctly-rounded-divide-sqrt-fp-
math"="false" "disable-tail-calls"="false" "less-precise-fpmad"="false" "min-legal-vector-
width"="0" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-
math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-
math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "target-
cpu"="x86-64" "target-features"="+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "unsafe-fp-math"="false"
"use-soft-float"="false" }
!llvm.module.flags = !{!0}
!llvm.ident = !{!1}
!0 = !{i32 1, !"wchar_size", i32 4}
!1 = !{!"clang version 9.0.1-12 "}
而所有 llvm-link 所做的就是复制 fn_ir.ll 的内容,并将 source_filename
更改为 llvm-link
。我真的很高兴知道我所缺少的那一点。
答案就在名称修改中。
您的 'manually' 生成的 IR 有一个名为 fn
的函数,而 clang++
发出名称 _Z2fni
.
您需要使名称匹配。在 main_ir.ll
中发出 _Z2fni
,或者(在这种情况下可以更好地争论)在 fn_ir
中更改 fn
的定义,例如:
extern "C" void fn(int x) {
return x * 2;
}
extern "C"
告诉编译器使用 C mangling 约定,这不太脆弱,因为即使您更改 fn
的参数类型或数量,它也会工作。但是,如果你想将 C++ 类型传递给 fn
,它就不起作用,那么你需要为 main_ir.ll
.
UPD:
还有两个'discrepancies':
fn
在两个模块中有不同的参数:i32
vsi32, ...
- 另一个问题是
main
声明为内部。我猜它只是被剥离了,因为它是内部的并且没有被任何人调用。
所以只需删除 internal
标志就可以完成这项工作。