无法将自定义生成的LLVM IR与Clang生成的IR链接

问题描述 投票:0回答:1

我一直在尝试将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 \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所做的都是在source_filename更改为llvm-link的情况下复制fn_ir.ll的内容。我很高兴知道我想念的东西。

llvm clang++ llvm-ir
1个回答
1
投票

答案是名字改写。

您“手动”生成的IR具有名为fn的功能,而clang++发出的名称为_Z2fni

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

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

extern "C"告诉编译器使用C mangling约定,它不那么脆弱,因为即使您更改fn的类型或参数数量也可以使用。但是,如果要将C ++类型传递到fn中,它将无法正常工作,那么您需要为main_ir.ll发出正确的函数名称。

UPD:

还有两个'差异':

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

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

© www.soinside.com 2019 - 2024. All rights reserved.