llvm生成rdrand指令
来源:互联网 发布:fannel扁平网络 编辑:程序博客网 时间:2024/06/08 03:38
问题
在做一个project的时候需要使用llvm的pass对函数进行插桩,在每一个函数头之前插入一条指令 rdrand %rax
,在寻找llvm基本指令之后发现并没有生成随机数的指令,这时就想到了llvm中intrinsic函数中是否有关于rdrand指令的函数,在对llvm整个源码进行扫描之后,发现有x86的rdrand的intrinsic函数:
X86_INTRINSIC_DATA(rdrand_16, RDRAND, X86ISD::RDRAND, 0), X86_INTRINSIC_DATA(rdrand_32, RDRAND, X86ISD::RDRAND, 0), X86_INTRINSIC_DATA(rdrand_64, RDRAND, X86ISD::RDRAND, 0),
既然有对它们的定义,那是否有关于它们的使用呢,又经过一番查找,终于在一个测试文件中(/test/CodeGen/X86/rdrand.ll)找到相应的使用:
declare {i16, i32} @llvm.x86.rdrand.16()declare {i32, i32} @llvm.x86.rdrand.32()declare {i64, i32} @llvm.x86.rdrand.64()define i32 @_rdrand16_step(i16* %random_val) { %call = call {i16, i32} @llvm.x86.rdrand.16() %randval = extractvalue {i16, i32} %call, 0 store i16 %randval, i16* %random_val %isvalid = extractvalue {i16, i32} %call, 1 ret i32 %isvalid; CHECK-LABEL: _rdrand16_step:; CHECK: rdrandw %ax; CHECK: movzwl %ax, %ecx; CHECK: movl $1, %eax; CHECK: cmovael %ecx, %eax; CHECK: movw %cx, (%r[[A0:di|cx]]); CHECK: ret}define i32 @_rdrand32_step(i32* %random_val) { %call = call {i32, i32} @llvm.x86.rdrand.32() %randval = extractvalue {i32, i32} %call, 0 store i32 %randval, i32* %random_val %isvalid = extractvalue {i32, i32} %call, 1 ret i32 %isvalid; CHECK-LABEL: _rdrand32_step:; CHECK: rdrandl %e[[T0:[a-z]+]]; CHECK: movl $1, %eax; CHECK: cmovael %e[[T0]], %eax; CHECK: movl %e[[T0]], (%r[[A0]]); CHECK: ret}define i32 @_rdrand64_step(i64* %random_val) { %call = call {i64, i32} @llvm.x86.rdrand.64() %randval = extractvalue {i64, i32} %call, 0 store i64 %randval, i64* %random_val %isvalid = extractvalue {i64, i32} %call, 1 ret i32 %isvalid; CHECK-LABEL: _rdrand64_step:; CHECK: rdrandq %r[[T1:[a-z]+]]; CHECK: movl $1, %eax; CHECK: cmovael %e[[T1]], %eax; CHECK: movq %r[[T1]], (%r[[A0]]); CHECK: ret}
这个系列函数是对rdrandx_step(address)系列函数的包装,在这些函数中是生成随机数,并将该随机数保存到address参数中。发现在该系列函数中对@llvm.x86.rdrand.xx()系列函数的调用,可以发现,在该函数第一个语句是对@llvm.x86.rdrand.xx() intrinsic函数的调用,该函数返回一个StructType类型的结果,该结果一共有两个成员组成,第一个成员是@llvm.x86.rdrand.xx()函数产生的随机数,第二个参数表示该函数是否调用成功。第二个语句就是从结果中取出随机数。弄清了该函数的逻辑后就可以通过llvm C API产生相应的IR指令。
llvm C API
下面是我通过llvm的C API产生的相应的IR指令的代码:
AllocaInst* AI3 = B.CreateAlloca(PtrTy, nullptr, "RandomValue");std::vector<Type *> arg_type;Function *fun = Intrinsic::getDeclaration(F->getParent(), Intrinsic::x86_rdrand_64, arg_type);CallInst* result = B.CreateCall(fun, {}); //B.CreateRet(result); //result->dump();if (dyn_cast<StructType>(result->getType())) { //errs() << "Hello\n"; Value* randomValue = B.CreateExtractValue(result, (uint64_t)0); Value* randomValuePtr = B.CreateIntToPtr(randomValue, Type::getInt8PtrTy(B.getContext())); B.CreateStore(randomValuePtr, AI3, true);}
注意事项
在生成了.ll文件后,需要用llc工具生成二进制文件,此时需要添加-mattr=rdrnd的属性:
llc -filetype=obj input.ll -mattr=+rdrnd -o output.o
否则会出现LLVM ERROR: Cannot select: t74: i64,i32,ch = X86ISD::RDRAND t0错误
- llvm生成rdrand指令
- LLVM 指令统计
- LLVM IR指令的抽象
- LLVM官方文档翻译---- LLVM原子指令与并发指引
- LLVM汇编语言指导手册之指令手册
- LLVM(四):指令描述td部分
- LLVM原子指令与并发指引
- LLVM
- LLVM
- llvm
- LLVM
- LLVM
- LLVM
- LLVM
- LLVM
- LLVM
- 管网:lldb,gdb 指令:http://lldb.llvm.org/varformats.html
- 科普LLVM中MSP430如何lower移位指令
- 【智能工厂】华龙讯达龙小昂:智能工厂建设的关键点
- 【两化融合】工业4.0视角看两化融合:两化融合发展水平对应工业2.0向3.0过渡
- 喜欢民谣
- InnoDB事务日志(redo log 和 undo log)
- BASE64编码的图片在网页中的显示问题
- llvm生成rdrand指令
- 【工业互联网】东方国信赵宏博:工业互联网平台助力智能制造
- 【淘工厂】阿里巴巴袁炜(观德):淘工厂——中国特色工业4.0创新
- 【工业互联网】国内外工业互联网平台对比分析研究
- 【工业互联网】新时代,中国服装行业会出现产业级的“阿里”和“滴滴”吗?
- Andirod 第一课 2017-11-18
- 【OpenCV】视频输入与相似度测量
- intelliJ IDEA快捷键整理自用版
- 常用的HTTP状态码