问题
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