You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在LLVM/C++中识别各类指令?求算术类指令提取方法

解决LLVM识别算术及其他类型指令的问题

嘿,我来帮你搞定LLVM里识别算术和其他类型指令的难题!你已经用dyn_cast成功识别了CallInst、LoadInst、StoreInst和BranchInst,接下来咱们把算术指令和其他剩余类型的指令也覆盖到,这里有两种实用的方案:

方案一:利用指令子类(面向对象方式)

LLVM为不同类型的指令提供了专门的子类,比如算术指令大多属于BinaryOperator(二元操作,如加减乘除)或UnaryOperator(一元操作,如取负、按位取反)。你可以延续之前的dyn_cast思路,针对这些子类做判断,还能进一步通过操作码区分具体类型:

for (const Function &F : *M) {
  for (const BasicBlock &BB : F) {
    for (const Instruction &I : BB) {
      // 处理你已经识别的指令
      if (const StoreInst *SI = dyn_cast<StoreInst>(&I)) {
        // 统计或处理Store指令
        continue;
      }
      if (const LoadInst *LI = dyn_cast<LoadInst>(&I)) {
        // 统计或处理Load指令
        continue;
      }
      if (const BranchInst *BI = dyn_cast<BranchInst>(&I)) {
        // 统计或处理Branch指令
        continue;
      }
      if (const CallInst *CI = dyn_cast<CallInst>(&I)) {
        // 统计或处理Call指令
        continue;
      }

      // 处理二元算术/逻辑指令(Add、Sub、Mul、Div、And、Or等)
      if (const BinaryOperator *BO = dyn_cast<BinaryOperator>(&I)) {
        Instruction::Opcode op = BO->getOpcode();
        switch(op) {
          case Instruction::Add:
          case Instruction::FAdd: // 区分整数加法和浮点数加法
            // 处理加法指令
            break;
          case Instruction::Sub:
          case Instruction::FSub:
            // 处理减法指令
            break;
          case Instruction::Mul:
          case Instruction::FMul:
            // 处理乘法指令
            break;
          case Instruction::UDiv:
          case Instruction::SDiv:
          case Instruction::FDiv:
            // 处理除法指令(无符号、有符号、浮点数)
            break;
          // 还可以添加更多二元操作,比如取余、逻辑运算等
          default:
            // 其他二元操作类型
            break;
        }
        continue;
      }

      // 处理一元算术指令(Neg、Not等)
      if (const UnaryOperator *UO = dyn_cast<UnaryOperator>(&I)) {
        Instruction::Opcode op = UO->getOpcode();
        if (op == Instruction::Neg || op == Instruction::FNeg) {
          // 处理取负指令(整数/浮点数)
        } else if (op == Instruction::Not) {
          // 处理按位取反指令
        }
        continue;
      }

      // 处理其他常见指令类型
      if (const ReturnInst *RI = dyn_cast<ReturnInst>(&I)) {
        // 处理返回指令
      } else if (const ICmpInst *ICI = dyn_cast<ICmpInst>(&I)) {
        // 处理整数比较指令
      } else if (const FCmpInst *FCI = dyn_cast<FCmpInst>(&I)) {
        // 处理浮点数比较指令
      } else if (const AllocaInst *AI = dyn_cast<AllocaInst>(&I)) {
        // 处理内存分配指令
      }
    }
  }
}

方案二:直接判断指令操作码(简洁高效)

如果你不需要获取指令子类的特定方法,只是想快速分类统计,可以直接通过getOpcode()获取指令的操作码,用switch-case统一处理:

for (const Function &F : *M) {
  for (const BasicBlock &BB : F) {
    for (const Instruction &I : BB) {
      Instruction::Opcode op = I.getOpcode();
      switch(op) {
        // 处理已识别的指令
        case Instruction::Store: {
          const StoreInst *SI = cast<StoreInst>(&I);
          // 处理Store指令
          break;
        }
        case Instruction::Load: {
          const LoadInst *LI = cast<LoadInst>(&I);
          // 处理Load指令
          break;
        }
        case Instruction::Br: {
          const BranchInst *BI = cast<BranchInst>(&I);
          // 处理Branch指令
          break;
        }
        case Instruction::Call: {
          const CallInst *CI = cast<CallInst>(&I);
          // 处理Call指令
          break;
        }

        // 处理算术指令
        case Instruction::Add:
        case Instruction::FAdd:
          // 加法指令
          break;
        case Instruction::Sub:
        case Instruction::FSub:
          // 减法指令
          break;
        case Instruction::Mul:
        case Instruction::FMul:
          // 乘法指令
          break;
        case Instruction::UDiv:
        case Instruction::SDiv:
        case Instruction::FDiv:
          // 除法指令
          break;

        // 处理其他指令
        case Instruction::Ret: {
          const ReturnInst *RI = cast<ReturnInst>(&I);
          // 返回指令
          break;
        }
        case Instruction::ICmp: {
          const ICmpInst *ICI = cast<ICmpInst>(&I);
          // 整数比较
          break;
        }
        // 更多指令操作码可以参考LLVM的Instruction枚举
      }
    }
  }
}

小技巧:快速统计所有算术指令

如果只是想统计所有算术指令的数量,不用区分具体类型,可以直接用isa模板快速判断:

if (isa<BinaryOperator>(I) || isa<UnaryOperator>(I)) {
  arithmetic_instruction_count++;
}

两种方案各有优势:子类方式更适合需要获取指令详细信息的场景,操作码方式则更简洁高效,你可以根据自己的需求选择~

内容的提问来源于stack exchange,提问作者Neitral

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.27 07:25:52