2016-02-20 2 views
2

Я слежу за учебником llvm за собственный простой язык программирования «Kaleidoscope», и на моем языке очевидна функциональность, на которую этот учебник не охватывает. Я просто хочу, чтобы напечатать любой двойной стандартный вывод в значительной степени, как C++ будет делать:llvm - Как реализовать функцию печати на моем языке?

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)?

+0

Это помогло бы, если бы вы объяснили, что LLVM IR вы бы хотели понизить от звонка на вашем языке –

ответ

3

ниже - код llvm ir, сгенерированный для printf ("% f", a); используя clang. 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 

Для реализации в кодегене вам сначала нужно проверить, присутствует ли эта функция в модуле или нет. если нет, то вам нужно добавить объявление, вы можете сделать это за один вызов.

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 

, то вы можете вызвать функцию с помощью соответствующего 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

Сначала вы должны проверить, Callee == "print", а затем вставить любые необходимые инструкции.

LLVM IR не имеет понятия «печать», поскольку на самом деле это не вопрос языка - это средство, предоставляемое ОС. Вероятно, самым простым вариантом для вас было бы перевести вызов в звонок на printf, так что, например, print(5.0) будет printf("%f\n", 5.0).

Урок, который вы связали, показывает, как работают внешние вызовы функций - вам нужно будет вставить объявление для printf с правильной сигнатурой, а затем построить вызов.

Смежные вопросы