【问题标题】:llvm - How to implement print function in my language?llvm - 如何用我的语言实现打印功能?
【发布时间】:2016-02-20 16:45:21
【问题描述】:

我正在关注 llvm 的教程,了解他们自己的简单编程语言“Kaleidoscope”,我的语言中有一个明显的功能,本教程似乎没有涵盖。我只是想像 C++ 那样将任何双精度输出打印到标准输出:

std::cout << 5.0;

我的语言会做类似的事情

print(5.0);

Third chapter of llvm's tutorial 涵盖函数调用。他们使用的代码是:

Value *CallExprAST::codegen() {
  // Look up the name in the global module table.
  Function *CalleeF = TheModule->getFunction(Callee);
  if (!CalleeF)
    return ErrorV("Unknown function referenced");

  // If argument mismatch error.
  if (CalleeF->arg_size() != Args.size())
    return ErrorV("Incorrect # arguments passed");

  std::vector<Value *> ArgsV;
  for (unsigned i = 0, e = Args.size(); i != e; ++i) {
    ArgsV.push_back(Args[i]->codegen());
    if (!ArgsV.back())
      return nullptr;
  }

  return Builder.CreateCall(CalleeF, ArgsV, "calltmp");
}

如何实现codegen() 方法来调用特定函数print(any fp number)

【问题讨论】:

  • 如果你用你的语言解释你希望从调用中降低什么 LLVM IR 会有所帮助

标签: c++ llvm


【解决方案1】:

下面是为 printf("%f", a); 生成的 llvm ir 代码;使用铿锵声。 printf 签名是 int printf(const char*, ...);

@.str = private unnamed_addr constant [3 x i8] c"%f\00", align 1

; Function Attrs: nounwind uwtable
define i32 @main() #0 {
%a = alloca double, align 8
%1 = load double* %a, align 8
%2 = call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([3 x i8]*  @.str, i32 0, i32 0), double %1)
ret i32 0
}

declare i32 @printf(i8*, ...) #1

要在 codegen 中实现,您首先需要检查该函数是否已经存在于模块中。如果没有,那么您需要添加声明,您可以一次调用。

Function *CalleeF = TheModule->getOrInsertFunction("printf",
                                                   FunctionType::get(IntegerType::getInt32Ty(Context), PointerType::get(Type::getInt8Ty(Context), 0), true /* this is var arg func type*/) 
                                                   );

上面将获取或添加函数声明的句柄

 declare i32 @printf(i8*, ...) #1

然后你可以通过匹配参数调用函数。

 std::vector<Value *> ArgsV;
 for (unsigned i = 0, e = Args.size(); i != e; ++i) 
   ArgsV.push_back(Args[i]->codegen());

return Builder.CreateCall(CalleeF, ArgsV, "printfCall");

【讨论】:

    【解决方案2】:

    您首先检查是否为Callee == "print",然后插入您想要的任何说明。

    LLVM IR 没有“打印”的概念,因为这并不是真正的语言考虑——它是操作系统提供的一种工具。可能对您来说最简单的选择是将调用转换为对printf 的调用,例如print(5.0) 变为 printf("%f\n", 5.0)

    您链接的教程确实显示了外部函数调用的工作原理——您必须插入具有正确签名的 printf 声明,然后构建对其的调用。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-06-26
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多