编写LLVM转换过程以在每个函数的开头注入延迟

问题描述

我是LLVM的新手,我正在尝试编写LLVM转换遍历,该遍历将在运行时为每个被调用函数的开始注入延迟。

我发现以下代码将printf语句插入每个函数的开头。

我如何相应地更改代码以注入延迟而不是printf? (我正在使用LLVM 10。)

下面是代码:

bool InjectFuncCall::runOnModule(Module &M) {
  bool InsertedAtLeastOnePrintf = false;

  auto &CTX = M.getContext();
  PointerType *PrintfArgTy = PointerType::getUnqual(Type::getInt8Ty(CTX));

  // STEP 1: Inject the declaration of printf
  // ----------------------------------------
  // Create (or _get_ in cases where it's already available) the following
  // declaration in the IR module:
  //    declare i32 @printf(i8*,...)
  // It corresponds to the following C declaration:
  //    int printf(char *,...)
  FunctionType *PrintfTy = FunctionType::get(
      IntegerType::getInt32Ty(CTX),PrintfArgTy,/*IsVarArgs=*/true);

  FunctionCallee Printf = M.getOrInsertFunction("printf",PrintfTy);

  // Set attributes as per inferLibFuncAttributes in BuildLibCalls.cpp
  Function *PrintfF = dyn_cast<Function>(Printf.getCallee());
  PrintfF->setDoesNotThrow();
  PrintfF->addParamAttr(0,Attribute::NoCapture);
  PrintfF->addParamAttr(0,Attribute::ReadOnly);


  // STEP 2: Inject a global variable that will hold the printf format string
  // ------------------------------------------------------------------------
  llvm::Constant *PrintfFormatStr = llvm::ConstantDataArray::getString(
      CTX,"(llvm-tutor) Hello from: %s\n(llvm-tutor)   number of arguments: %d\n");

  Constant *PrintfFormatStrVar =
      M.getOrInsertGlobal("PrintfFormatStr",PrintfFormatStr->getType());
  dyn_cast<GlobalVariable>(PrintfFormatStrVar)->setInitializer(PrintfFormatStr);

  // STEP 3: For each function in the module,inject a call to printf
  // ----------------------------------------------------------------
  for (auto &F : M) {
    if (F.isDeclaration())
      continue;

    // Get an IR builder. Sets the insertion point to the top of the function
    IRBuilder<> Builder(&*F.getEntryBlock().getFirstInsertionPt());

    // Inject a global variable that contains the function name
    auto FuncName = Builder.CreateGlobalStringPtr(F.getName());

    // Printf requires i8*,but PrintfFormatStrVar is an array: [n x i8]. Add
    // a cast: [n x i8] -> i8*
    llvm::Value *FormatStrPtr =
        Builder.CreatePointerCast(PrintfFormatStrVar,"formatStr");

    // The following is visible only if you pass -debug on the command line
    // *and* you have an assert build.
    LLVM_DEBUG(dbgs() << " Injecting call to printf inside " << F.getName()
                      << "\n");

    // Finally,inject a call to printf
    Builder.CreateCall(
        Printf,{FormatStrPtr,FuncName,Builder.getInt32(F.arg_size())});

    InsertedAtLeastOnePrintf = true;
  }

  return InsertedAtLeastOnePrintf;
}

如果有适合初学者的LLVM优秀教程的链接,那也很好。

解决方法

除了必须将参数类型从delay更改为printf之外,您必须像声明i8*一样声明i32函数。对于教程,您可以查看这些 https://anoopsarkar.github.io/compilers-class/llvm-practice.html\

https://www.usna.edu/Users/cs/wcbrown/courses/F19SI413/lab/l13/lab.html

https://osterlund.xyz/posts/2017-11-28-LLVM-pass.html

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...