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

LLVM中invoke指令的判断信号及转为call指令的实现方法

Great question! Let's break this down into two key parts: detecting the "signal" for normal return conditions in an LLVM IR Pass, and converting invoke instructions to call instructions with proper exception handling.

Checking for Normal Return Conditions in an LLVM IR Pass

First, let's clarify: there's no single "signal" variable that directly tells you if an invoke will take its normal branch. Instead, the distinction between normal and abnormal returns is encoded in the invoke instruction's control flow edges and the behavior of the called function. Here's how you can track this in a Pass:

  1. Access the invoke's destination blocks
    Every invoke instruction has two explicit successors:

    • The normal destination (where execution goes if the callee returns via ret)
    • The unwind destination (where execution goes if the callee exits via unwind or resume)
      In your Pass, you can retrieve these blocks using:
    if (auto *invokeInst = dyn_cast<InvokeInst>(&currentInstruction)) {
      BasicBlock *normalDest = invokeInst->getNormalDest();
      BasicBlock *unwindDest = invokeInst->getUnwindDest();
    }
    
  2. Check the callee's attributes and body
    To predict whether the invoke will take the normal branch, analyze the called function:

    • If the callee has the nounwind attribute, it guarantees no exceptions will be thrown—so the unwind branch is never taken. You can check this with callee->doesNotThrow().
    • For non-declaration functions (functions with a body), scan for return and exit instructions:
      • Presence of ReturnInst means the function can return normally.
      • Presence of UnwindInst or ResumeInst means the function can exit abnormally.
        Example code for this analysis:
    Function *callee = invokeInst->getCalledFunction();
    if (callee && !callee->isDeclaration()) {
      bool canReturnNormally = false;
      bool canThrow = false;
      for (BasicBlock &bb : *callee) {
        for (Instruction &inst : bb) {
          if (isa<ReturnInst>(&inst)) canReturnNormally = true;
          else if (isa<UnwindInst>(&inst) || isa<ResumeInst>(&inst)) canThrow = true;
        }
      }
      // Use these flags to reason about the invoke's behavior
    }
    

Converting invoke to call with Exception Handling

Converting an invoke to a call requires preserving the original exception handling logic, since call instructions don't have explicit unwind destinations—exceptions from a call propagate up the call stack unless caught by an enclosing EH pad. Here's how to do it properly:

  1. Replace the invoke with a call
    Use IRBuilder to create a CallInst that mirrors the invoke's arguments, calling convention, and metadata:

    IRBuilder<> builder(invokeInst);
    CallInst *callInst = builder.CreateCall(
      invokeInst->getCalledFunction(),
      invokeInst->getArgOperands(),
      "" // Optional name
    );
    // Copy over all metadata and attributes
    callInst->copyMetadata(*invokeInst);
    callInst->setCallingConv(invokeInst->getCallingConv());
    
  2. Preserve the normal control flow
    After creating the call, replace the invoke's normal branch with a direct br instruction to the original normal destination:

    // Remove the original invoke
    invokeInst->eraseFromParent();
    // Jump to the normal destination
    builder.CreateBr(normalDest);
    
  3. Ensure exception handling is preserved
    The original unwind destination (from the invoke) must still be a valid EH pad (a block starting with landingpad or catchswitch). If the callee can throw exceptions, the call will automatically unwind to this pad if an exception occurs—no extra code is needed here, as long as the EH pad's structure remains intact.

    If the callee has the nounwind attribute, you can safely discard the unwind destination entirely, as exceptions will never be thrown.


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.26 10:01:51