使用 LLVM pass 添加内在函数

2024-02-15

我使用 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-config 中的 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 (tags/RELEASE_34/dot2-final);海湾合作委员会版本 4.9.2 (GCC);和 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 }                                                                       
...

并调用(来自文件 ff.s):

...
.Ltmp2:                                       
    callq   llvm.x86.sse3.mwait.i32.i32   
    movl    $_ZStL8__ioinit, %edi         
    callq   _ZNSt8ios_base4InitC1Ev       
    movl    $_ZNSt8ios_base4InitD1Ev, %edi
    movl    $_ZStL8__ioinit, %esi         
    movl    $__dso_handle, %edx           
    callq   __cxa_atexit                  
    popq    %rax                          
    ret                                   
...

编辑 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);

EDIT:我目前正在编写一个 LLVM 通行证,它基本上是在做你在这个问题中尝试做的事情。您的代码的问题如下:

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

您正在尝试获取名为 llvm.x86.sse3.mwait.i32.i32 的内部函数的减速度,但该内部函数不存在。但是,llvm.x86.sse3.mwait 存在,因此您必须编写以下内容:

Function *mwait = Intrinsic::getDeclaration(m, Intrinsic::x86_sse3_mwait);

请注意调用中缺少的类型参数。这是因为 llvm.x86.sse3.mwait 没有重载。

我希望你同时想通了。


好吧,因为我想能够暂时回答你,这是一个疯狂的猜测答案。

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

下面是一些 C++ 代码,它仅使用内置的 clang 来获取 IR 内部的内部函数(我使用 clang 3.5,但这应该不会产生任何影响)。

int main ()
{
    __builtin_ia32_mwait(4,2);
}

编译它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 传递中将内在函数引入函数的方式是错误的。

Get the intrinsic function and call it:

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 */);
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

使用 LLVM pass 添加内在函数 的相关文章

随机推荐

  • JEdi​​torPane 中的超链接

    我在 JEditorPane ex 中显示了几个链接 http www google com finance q NYSE C http www google com finance q NYSE C http www google com
  • 从 FOSUserBundle 中的登录用户获取用户 ID

    我正在尝试创建一个任务管理器 我需要能够获取当前登录用户的用户 ID 以便在创建任务时将用户 ID 也输入到数据库中 我无法让它工作 它一直告诉我call to undefined function getUser 我不认为我必须定义它 我
  • 通过 Socket 发送 numpy 数组

    首先 我想做的是 使用套接字将照片从我的 Raspberry Pi 发送到我的笔记本电脑 Client usr bin python import socket import cv2 import numpy as np import pi
  • 如何使用 jQuery 禁用表单内的所有

  • 是否可以让 OpenGL 在内存表面上绘图?

    我开始学习 OpenGL 我想知道是否可以让它在我通过其他库获得的视频内存缓冲区上绘制 要绘制到视频内存中 您可以使用帧缓冲对象 http www songho ca opengl gl fbo html绘制到 OpenGL 纹理或渲染缓冲
  • 在 Angular 4+ 中处理两个 URL(矩阵 && 查询)参数

    目前我们在我的 Angular 4 应用程序中使用矩阵参数 Google Analytics 在读取 URL 时出现问题 所以我们决定将其更改为查询参数 然而 旧的符号 矩阵 必须可访问并重定向到新的符号并将此类事件保存到数据库中 我看到三
  • 如何在 WinApi 中从 HANDLE 生成 FILE*?

    有没有一种简单的方法可以从 WinApi HANDLE 创建指向管道一端的 FILE 就像我们在 unix 中所做的那样 fdopen fd
  • Java jar-Archive 工具 - 设置包含内容的文件夹的路径

    当我使用这个命令时 echo C Program Files Java jdk1 7 0 07 bin jar cf C file file jar C data 在 jar Archive 工具的 CMD 中 它会创建名为 file ja
  • Linus 演讲 - Git 与数据损坏? [关闭]

    就目前情况而言 这个问题不太适合我们的问答形式 我们希望答案得到事实 参考资料或专业知识的支持 但这个问题可能会引发辩论 争论 民意调查或扩展讨论 如果您觉得这个问题可以改进并可能重新开放 访问帮助中心 help reopen questi
  • 为什么 Android 通知 Intent 中不发送额外数据(整数)?

    以下代码显示通知并发送 int 数据 但在其他活动中getExtras 回报null Why int notificationID 1 NotificationManager nm NotificationManager getSystem
  • CoreBluetooth 从不在 iPhone 5S 上调用 didDiscoverServices

    大多数时候 我们正在编写的应用程序与我们的 BLE 外设配合得很好 通常 对于 iPhone 5S 用户来说 设备会陷入恐慌 每当我们扫描服务时 didDiscoverServices 永远不会调用委托方法 重新启动设备或删除所有设置 常规
  • 自定义 IPython 笔记本/Jupyter 幻灯片放映

    我使用 IPython Notebook Jupyter 的幻灯片功能创建了一个幻灯片 效果很好 我通过以下方式创建并托管了幻灯片ipython nbconvert 这也很好用 但我找不到任何如何自定义幻灯片的信息 显然我必须定制Revea
  • 如何在 flutter/dart 中进行 SSL 公钥固定?

    这里对 Flutter 以及一般编程 来说相对较新 只熟悉更基本的东西 但我现在遇到了在 flutter dart 中使用 CertificatePinner 的需要 https square github io okhttp 3 x ok
  • t-sql子串

    我基本上有一列需要进行子串化 该列的格式如下所示 Column A Root FOLDERPATH somesubfolderpath somedocument doc 第一个字符串 Root 将始终具有相同的长度和相同的字符 Root 之
  • ORB 计算错误:它删除了小图像的所有关键点

    我有一个 50x50 的小图像 我找到 ORB 关键点 请注意 我必须将 patchSize 的默认参数从 31 更改为 14 才能检测到一些关键点 OrbFeatureDetector det 500 1 2f 8 14 0 2 0 14
  • 会话在 IHttpModule 中不可用

    在我的程序中 我尝试在 IHttpModule 中使用会话变量 这是我的代码 这在 VS 2010 开发服务器中运行良好 但是当我尝试在 IIS7 中调试时 它显示异常System Web HttpException Session sta
  • 打开工作簿时关闭 Excel 后台错误检查

    我有一个 Excel 工作簿 里面有很多绿色的 错误检查 三角形 有什么方法可以使用 Excel VBA 在打开工作簿时关闭此功能 我认为这就是您正在寻找的 Application ErrorCheckingOptions Backgrou
  • Mongodb 聚合框架解释

    MongoDB 中的聚合框架有解释函数吗 我在文档中看不到它 如果没有 是否有其他方法可以检查查询在聚合框架内的执行情况 我知道你只是做 db collection find explain 但是使用聚合框架时出现错误 db collect
  • 使用 OraOLEDB 提供商部署应用程序

    我开发了一个使用Delphi 7 ADO和ORACLE的应用程序 我使用的提供程序是OraOLEDB 我需要使用这个提供程序 因为BLOB字段支持 现在我想与提供商一起分发此应用程序 我在网上搜索下载甲骨文提供商 http www orac
  • 使用 LLVM pass 添加内在函数

    我使用 LLVM 通道向输入代码添加了一个内在函数 我能够看到内部调用 但我无法弄清楚如何将代码编译到我的目标架构 x86 64 我正在运行以下命令 clang llvm config ldflags libs all ff s o foo