Невозможно связать пользовательский IR LLVM с IR, созданным Clang - PullRequest
0 голосов
/ 08 мая 2020

Я пытался связать IR, сгенерированный с помощью llvm C ++ api, с другим IR файлом, созданным Clang ++. Входной файл для 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 воспроизводит содержимое fn_ir.ll с изменением source_filename на llvm-link. Я был бы очень счастлив узнать то, что мне не хватает.

1 Ответ

2 голосов
/ 08 мая 2020

Ответ находится в изменении имени.

Ваш «вручную» сгенерированный IR имеет функцию с именем fn, а clang++ выдает имя _Z2fni.

Вам нужно чтобы имена совпадали. Либо выдайте _Z2fni в main_ir.ll, либо (что в данном случае лучше) измените определение fn в fn_ir, например:

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

extern "C" сообщает компилятору чтобы использовать соглашение об изменении C, это меньше fr agile, так как оно будет работать, даже если вы измените тип или количество аргументов fn. Однако это не сработает, если вы хотите передать типы C ++ в fn, тогда вам необходимо указать правильное имя функции для main_ir.ll.

UPD:

Есть еще два «несоответствия»:

  1. fn имеет разные аргументы в двух модулях: i32 vs i32, ...
  2. Другая проблема - этот main объявлен как внутренний. Я предполагаю, что он просто удален, поскольку он является внутренним и никем не вызывается.

Так что простое удаление флага internal должно сработать за вас.

...