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

LLVM Pass插入打印基本块名称时运行时错误求助

LLVM Pass插入打印Basic Block名称语句的错误修复

错误原因

报错信息Call parameter type does not match function signature!明确指出核心问题:

  • printBBname函数要求参数类型为i8*(对应C语言的const char*)
  • 原代码用ConstantDataArray::getString生成的是[N x i8]类型的常量数组,直接传递给函数调用导致类型不兼容
  • 额外问题:每次遍历Basic Block时重复创建printBBname函数,会导致模块中出现多个同名函数定义

修复方案

  1. 参数类型适配:使用IRBuilder::CreateGlobalStringPtr直接生成i8*类型的字符串指针,替代ConstantDataArray::getString
  2. 避免重复定义函数:在遍历Basic Block前,先检查当前模块是否已存在printBBname函数,仅在不存在时创建一次

修改后的完整Pass代码

#include "llvm/Pass.h"    
#include "llvm/IR/Function.h"    
#include "llvm/Support/raw_ostream.h"    
#include "llvm/IR/Module.h"    
#include "llvm/IR/BasicBlock.h"    
#include "llvm/IR/Instructions.h"    
#include "llvm/IR/IRBuilder.h"    
#include "llvm/IR/Value.h"    
#include "llvm/IR/Instruction.h"    

using namespace llvm;    
using namespace std;    

extern "C" void printBBname(const char *name) {    
        printf("Basic Block: %s\n", name);    
}    

namespace {    
    struct Hello : public FunctionPass {    
        static char ID;    
        Hello() : FunctionPass(ID) {}    

        bool runOnFunction(Function &F) override {    
            errs() << "Hello: ";    
            errs().write_escaped(F.getName()) << '\n';    
            unsigned count = 0;    
            LLVMContext& context = F.getContext();    
            Module *m = F.getParent();
            assert(m != nullptr && "Module is null");

            // 仅创建一次printBBname函数
            Function *printFunc = m->getFunction("printBBname");
            if (!printFunc) {
                Type *returnType = Type::getVoidTy(context);
                PointerType *argType = PointerType::get(Type::getInt8Ty(context), 0);
                FunctionType *FuncType = FunctionType::get(returnType, argType, false);
                printFunc = Function::Create(FuncType, Function::ExternalLinkage, "printBBname", m);
                assert(printFunc != nullptr && "Failed to create printBBname function");
            }

            for(Function::iterator bb = F.begin(), e = F.end(); bb != e; ++bb){    
                bb->setName(F.getName() + "_" + to_string(count++));    
                errs() << "Basic Block name: " << bb->getName() << ", size: " << bb->size() << "\n";
                IRBuilder<> Builder(context);

                // 创建i8*类型的字符串指针
                Value *strPtr = Builder.CreateGlobalStringPtr(bb->getName());
                Builder.SetInsertPoint(&*bb, bb->getFirstInsertionPt());
                Builder.CreateCall(printFunc, strPtr);
            }
            return true;
        }
    }; 
} 

char Hello::ID = 0;
static RegisterPass<Hello> X("hello", "Hello World Pass",
                             false /* Only looks at CFG */,
                             false /* Analysis Pass */);

测试验证

  1. 重新编译Pass:
cd ../skeleton/build
cmake ..
make
  1. 重新生成测试IR并运行Pass:
clang -emit-llvm -c hello.c -o hello.bc
opt -load ../skeleton/build/libSkeletonPass.so --hello <hello.bc> out.bc
  1. 生成可执行文件并运行:
clang out.bc -o hello
./hello

运行后会输出每个Basic Block的名称,符合预期。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.11 07:43:21