如何在LLVM IR中通过ConstantFP获取load/store指令的浮点值
问题描述
现有如下LLVM IR代码片段:
store float 1.000000e+00, float* %f, align 4, !dbg !860 %0 = load float, float* %f, align 4, !dbg !861
在已知变量名%f的前提下,需要分别从上述load、store指令中获取对应的浮点值1.000000e+00。
已知调用constant_int->getSExtValue()方法可获取整型常量值,但未找到ConstantFP类提供的同类取值函数。当前编写的C++实现代码如下:
if (auto *op = dyn_cast<LoadInst>(&I)) { Value *val = arg1; // HERE didn't work if (auto constant_int = dyn_cast<ConstantInt>(val)) { int number = constant_int->getSExtValue(); } else if (auto constant_fp = dyn_cast<ConstantFP>(val)) { // ?? } } if (auto *op = dyn_cast<StoreInst>(&I)) { Value *val = op->getValueOperand(); // HERE works! if (auto constant_int = dyn_cast<ConstantInt>(val)) { int number = constant_int->getSExtValue(); errs() << "store " << number << ".\n"; } else if (auto constant_fp = dyn_cast<ConstantFP>(val)) { // ?? } }
当前代码存在两个待解决问题:
store指令分支的整型常量提取逻辑可正常运行,但load指令分支取值逻辑失效- 两处
ConstantFP判断分支的浮点值提取逻辑尚未实现
解决方案
ConstantFP浮点值提取
ConstantFP没有和getSExtValue()完全对应的直接返回数值的方法,需要通过它持有的APFloat实例做转换:
- 32位单精度float:调用
getValueAPF().convertToFloat(),返回C++原生float类型 - 64位双精度double:调用
getValueAPF().convertToDouble(),返回C++原生double类型
对应分支代码直接写为:
else if (auto constant_fp = dyn_cast<ConstantFP>(val)) { float f32_val = constant_fp->getValueAPF().convertToFloat(); // double f64_val = constant_fp->getValueAPF().convertToDouble(); errs() << "float constant: " << f32_val << "\n"; }
可配合constant_fp->getType()->isFloatTy()/isDoubleTy()判断常量精度选择对应转换方法。
load指令取值失效修复
load分支取值逻辑错误原因有两个:
- 代码中取的
arg1不是load的合法操作数,LoadInst获取加载的源指针要调用getPointerOperand();同时LLVM是SSA形式,load指令本身仅代表从内存读值的操作,不会内嵌常量值 - 示例中的
1.0是store指令写入%f指向内存的值,不是load指令自带的立即数,必须追踪指针对应的写入操作才能拿到值
适配你给出的单store写入场景的load分支修正代码:
if (auto *load_op = dyn_cast<LoadInst>(&I)) { Value* target_ptr = load_op->getPointerOperand(); // 遍历指针的所有使用,找到对它写入的store指令 for (User* u : target_ptr->users()) { auto *store_op = dyn_cast<StoreInst>(u); if (!store_op || store_op->getPointerOperand() != target_ptr) continue; Value* stored_val = store_op->getValueOperand(); // 常量判断逻辑和store分支完全一致 if (auto ci = dyn_cast<ConstantInt>(stored_val)) { int i_val = ci->getSExtValue(); errs() << "load got int: " << i_val << "\n"; } else if (auto cf = dyn_cast<ConstantFP>(stored_val)) { float f_val = cf->getValueAPF().convertToFloat(); errs() << "load got float: " << f_val << "\n"; } break; } }
若存在控制流分支、多次写入、指针别名等复杂场景,需要额外配合支配树分析、别名分析、流敏感追踪才能保证拿到准确的常量值,上述代码仅适配单写入的简单场景。
内容的提问来源于stack exchange,提问作者Rong Luo
相关产品推荐
相关产品推荐

