C++ 使用LLVM过程添加内部函数

C++ 使用LLVM过程添加内部函数,c++,linker,llvm,undefined-reference,llvm-ir,C++,Linker,Llvm,Undefined Reference,Llvm Ir,我已经使用LLVM过程向输入代码添加了一个内部代码。我能够看到内部调用,但我不知道如何将代码编译到我的目标体系结构(x86_64)。我正在运行以下命令: clang++ $(llvm-config --ldflags --libs all) ff.s -o foo 但链接器抱怨未定义的引用: /tmp/ff-2ada42.o: In function `fact(unsigned int)': /home/rubens/Desktop/ff.cpp:9: undefined reference

我已经使用LLVM过程向输入代码添加了一个内部代码。我能够看到内部调用,但我不知道如何将代码编译到我的目标体系结构(x86_64)。我正在运行以下命令:

clang++ $(llvm-config --ldflags --libs all) ff.s -o foo
但链接器抱怨未定义的引用:

/tmp/ff-2ada42.o: In function `fact(unsigned int)':
/home/rubens/Desktop/ff.cpp:9: undefined reference to `llvm.x86.sse3.mwait.i32.i32'
/tmp/ff-2ada42.o: In function `fib(unsigned int)':
/home/rubens/Desktop/ff.cpp:16: undefined reference to `llvm.x86.sse3.mwait.i32.i32'
/home/rubens/Desktop/ff.cpp:16: undefined reference to `llvm.x86.sse3.mwait.i32.i32'
/home/rubens/Desktop/ff.cpp:16: undefined reference to `llvm.x86.sse3.mwait.i32.i32'
尽管使用llvm配置中的ldflags,编译仍不会继续。关于如何正确编译代码有什么想法吗

要生成汇编代码,我已完成以下操作:

# Generating optimized code
clang++ $(llvm-config --cxxflags) -emit-llvm -c ff.cpp -o ff.bc
opt ff.bc -load path/to/mypass.so -mypass > opt_ff.bc

# Generating assembly
llc opt_ff.bc -o ff.s
我目前正在使用llvm版本3.4.2;clang版本3.4.2(标签/发布号34/dot2最终版);通用条款第4.9.2版(通用条款);以及Linux 3.17.2-1-ARCH x86_64


编辑:添加具有内在属性的IR:

文件~/llvm/include/llvm/IR/IntrinsicsX86.td:

...
589 // Thread synchronization ops.                                          
590 let TargetPrefix = "x86" in {  // All intrinsics start with "llvm.x86.".
591     def int_x86_sse3_monitor : GCCBuiltin<"__builtin_ia32_monitor">,      
592               Intrinsic<[], [llvm_ptr_ty,                               
593                          llvm_i32_ty, llvm_i32_ty], []>;                
594     def int_x86_sse3_mwait : GCCBuiltin<"__builtin_ia32_mwait">,          
595               Intrinsic<[], [llvm_i32_ty,                               
596                          llvm_i32_ty], []>;                             
597 }                                                                       
...

编辑2:以下是我如何在opt pass期间添加内在函数:

Function *f(bb->getParent());
Module *m(f->getParent());

std::vector<Type *> types(2, Type::getInt32Ty(getGlobalContext()));
Function *mwait = Intrinsic::getDeclaration(m, Intrinsic::x86_sse3_mwait, types);

std::vector<Value *> args;
IRBuilder<> builder(&bb->front());
for (uint32_t i : {1, 2}) args.push_back(builder.getInt32(i));

ArrayRef<Value *> args_ref(args);
builder.CreateCall(mwait, args_ref);
Function*f(bb->getParent());
模块*m(f->getParent());
std::vector类型(2,类型::getInt32Ty(getGlobalContext());
函数*mwait=内在::getDeclaration(m,内在::x86_sse3_mwait,类型);
std::向量args;
iBuilder生成器(&bb->front());
对于(uint32_t i:{1,2})args.push_-back(builder.getInt32(i));
ArrayRef args_ref(args);
builder.CreateCall(mwait,args\u ref);
编辑: 我目前正在写一个LLVM通行证,基本上就是在做你在这个问题上试图做的事情。您的代码存在以下问题:

std::vector<Type *> types(2, Type::getInt32Ty(getGlobalContext()));
Function *mwait = Intrinsic::getDeclaration(m, Intrinsic::x86_sse3_mwait, types);
请注意调用中缺少的类型参数。这是因为llvm.x86.sse3.mwait没有重载

我希望你能在这段时间内找到答案


好吧,因为我想回答你一段时间,这里是一个疯狂的猜测答案

问题在于如何通过优化器过程添加内部。看起来您只是在创建一个与内在函数同名的函数,而不是内在函数本身

这里有一个C++代码,它只使用内置的CLAN来获得IR的内部(我使用CLANG 3.5,但这不应该有任何影响)。p> 使用

clang-emit llvm-S编译它
I get:

; ModuleID = 'intrin.cpp'
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-unknown-linux-gnu"

; Function Attrs: nounwind uwtable
define i32 @main() #0 {
  call void @llvm.x86.sse3.mwait(i32 4, i32 2)
  ret i32 0
}

; Function Attrs: nounwind
declare void @llvm.x86.sse3.mwait(i32, i32) #1

attributes #0 = { nounwind uwtable "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" }
attributes #1 = { nounwind }

!llvm.ident = !{!0}

!0 = metadata !{metadata !"clang version 3.5.0 "}
请注意,SSE3内部版本没有像您的版本中那样的类型重载

在生成的文件上使用llc为我提供了:

.Ltmp2:
        .cfi_def_cfa_register %rbp
        movl    $4, %ecx
        movl    $2, %eax
        mwait
        xorl    %eax, %eax
        popq    %rbp
        retq
创建了正确的程序集

因此,我假设在opt过程中,将内在函数引入函数的方式是错误的

获取内部函数并调用它:

vector<Type*> types;
types.push_back(IntegerType::get(/*LLVM context*/, 32));
types.push_back(IntegerType::get(/*LLVM context*/, 32));

Function* func = Intrinsic::getDeclaration(/* module */, Intrinsic::x86_sse3_mwait, types);
CallInst* call = CallInst::Create(func, /* arguments */);
向量类型;
push_back(IntegerType::get(/*LLVM context*/,32));
push_back(IntegerType::get(/*LLVM context*/,32));
Function*func=内在::getDeclaration(/*模块*/,内在::x86_sse3_mwait,类型);
CallInst*call=CallInst::Create(func,/*参数*/);

您能否将LLVM IR与内部文件共享:对内部文件的调用和there声明?@MichaelHaidl我已经添加了请求信息。我原以为instrinsic调用会扩展到关联的内置函数中,但编译后调用仍保留在程序集文件中。您可以使用llvm dis使.bc文件可读,或者将-S传递给opt。您如何在opt pass中添加内部函数和调用也会很有趣。目前看来,调用的函数不是一个内在函数,而是一个与llvm内在函数同名的函数。感谢您的回复。我使用的方法与您指出的插入内在函数的方法基本相同。您是否看到我的代码中有任何陷阱,使我无法在最终的汇编中扩展内部代码?我觉得在运行
llc
时缺少了一些标志或参数,因为函数
llvm.x86.sse3.mwait.i32.i32
出现在我的程序集中。这很奇怪,请尝试在类型向量中没有任何内容的情况下获得内在的偏差。可能是类型重载的问题。如果不是,您可以查看llc的-mcpu或-mattr命令行标志。您是否介意添加用于使用
llc
生成汇编代码的标志?这也许可以解释为什么我没有扩展函数体。我只是使用了
llc input.ll-o input.S
功能非常强大!非常感谢您的回复!:顺便说一句,我正在认真考虑向stackexchange提议一个llvm条目。你怎么认为?
; ModuleID = 'intrin.cpp'
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-unknown-linux-gnu"

; Function Attrs: nounwind uwtable
define i32 @main() #0 {
  call void @llvm.x86.sse3.mwait(i32 4, i32 2)
  ret i32 0
}

; Function Attrs: nounwind
declare void @llvm.x86.sse3.mwait(i32, i32) #1

attributes #0 = { nounwind uwtable "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" }
attributes #1 = { nounwind }

!llvm.ident = !{!0}

!0 = metadata !{metadata !"clang version 3.5.0 "}
.Ltmp2:
        .cfi_def_cfa_register %rbp
        movl    $4, %ecx
        movl    $2, %eax
        mwait
        xorl    %eax, %eax
        popq    %rbp
        retq
vector<Type*> types;
types.push_back(IntegerType::get(/*LLVM context*/, 32));
types.push_back(IntegerType::get(/*LLVM context*/, 32));

Function* func = Intrinsic::getDeclaration(/* module */, Intrinsic::x86_sse3_mwait, types);
CallInst* call = CallInst::Create(func, /* arguments */);