【问题标题】:Cannot link custom generated LLVM IR with Clang generated IR无法将自定义生成的 LLVM IR 与 Clang 生成的 IR 链接
【发布时间】:2020-05-07 21:13:25
【问题描述】:

我一直在尝试将使用 llvm 的 C++ api 生成的 IR 与 Clang++ 生成的另一个 IR 文件链接起来。 Clang 的输入文件是一个函数 fn 我试图从第一个 IR 文件中调用。但是llvm-link 不会用它的定义替换fn 的声明。

ma​​in_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 \0A\00", 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。我会很高兴知道我缺少的那一点。

【问题讨论】:

    标签: llvm clang++ llvm-ir


    【解决方案1】:

    答案就在名称中。

    您“手动”生成的 IR 有一个名为 fn 的函数,而 clang++ 发出名称 _Z2fni

    您需要使名称匹配。在main_ir.ll 中发出_Z2fni,或者(在这种情况下可以说更好)在fn_ir 中更改fn 的定义,例如:

    extern "C" void fn(int x) {
      return x * 2;
    }
    

    extern "C" 告诉编译器使用 C 修改约定,这不那么脆弱,因为即使您更改 fn 的参数类型或数量,它也会起作用。但是,如果您想将 C++ 类型传递给 fn,它将不起作用,那么您需要为 main_ir.ll 发出正确的函数名称。

    UPD:

    还有两个“差异”:

    1. fn 在两个模块中有不同的参数:i32 vs i32, ...
    2. 另一个问题是main 声明为内部。我猜它只是被剥离了,因为它是内部的并且没有被任何人调用。

    因此,只需删除 internal 标志就可以完成这项工作。

    【讨论】:

    • 非常感谢! @AlexDenisov。然而,这似乎不是问题。添加extern "C" 确实会破坏函数名称,但链接文件仍然只包含fn_ir.ll 的内容。 'llvm-link' 只是忽略 main_ir.ll
    • @droptop 我添加了另一条评论,应该可以解决您遇到的问题:)
    • 非常感谢它的工作。我仍然不知道我是怎么错过externallinkage 的东西... :) :) :)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-02-18
    • 1970-01-01
    • 1970-01-01
    • 2018-10-30
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多