llvm - How to implement print function in my language?

谁说胖子不能爱 提交于 2021-02-07 07:44:41

问题


I'm following llvm's tutorial for their own simple programming language "Kaleidoscope" and there's an obvious functionality in my language which this tutorial doesn't seem to cover. I simply want to print any double to standard output pretty much as C++ would do:

std::cout << 5.0;

my language would do something like

print(5.0);

Third chapter of llvm's tutorial covers function calls. The code they use is:

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");
}

How could I implement codegen() method for specific function call print(any fp number)?


回答1:


below is the llvm ir code generated for printf("%f", a); using clang. printf signature is 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

to implement in codegen you first need to check if the function is already present in module or not. if not then you need to add the declaration, you can do both in one call.

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

above will get or add you the handle to function declaration

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

then you can call function via matching params.

 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:


You'd first check if Callee == "print" and then insert any instructions you want.

LLVM IR has no concept of "printing" since that's not really a language consideration -- it's a facility provided by the OS. Probably the simplest option for you would be to translate the call into a call to printf, so that e.g. print(5.0) becomes printf("%f\n", 5.0).

The tutorial you linked does show how external function calls work -- you'd have to insert a declaration for printf with the correct signature, then build a call to that.



来源:https://stackoverflow.com/questions/35526075/llvm-how-to-implement-print-function-in-my-language

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!