2014-12-13 5 views
1

Я создаю инструмент clang, и я хочу сгенерировать LLVM IR от clang AST. Я знаю параметр -emit-llvm, который я могу использовать для получения файла * .ll, но есть ли способ генерировать IR-код внутри? Какой-то метод, который я могу назвать тем, который принимает контекст AST или AST и возвращает llvm::Module? Я не могу найти ни одного примера, который показывает это.Способ создания LLVM IR

Отредактировано: Для этого я попытался использовать CodeGenAction, но я не могу заставить его работать. Я заканчиваю неразрешенную ошибку внешнего символа. Я что-то упускаю?

#include <clang/CodeGen/CodeGenAction.h> 
#include <clang/Frontend/CompilerInstance.h> 
#include <clang/Frontend/CompilerInvocation.h> 
#include <clang/Basic/DiagnosticOptions.h> 
#include <clang/Frontend/TextDiagnosticPrinter.h> 
#include <llvm/ADT/IntrusiveRefCntPtr.h> 
#include <llvm/IR/Module.h> 
#include <llvm/IR/LLVMContext.h> 

using namespace std; 

clang::CodeGenAction * getAction(void) 
{ 
    // Path to the C file 
    string inputPath = "test.c"; 

    // Arguments to pass to the clang frontend 
    vector<const char *> args; 
    args.push_back(inputPath.c_str()); 

    // The compiler invocation needs a DiagnosticsEngine so it can report problems 
    clang::DiagnosticOptions opt = clang::DiagnosticOptions(); 
    clang::TextDiagnosticPrinter *DiagClient = new clang::TextDiagnosticPrinter(llvm::errs(), &opt); 
    llvm::IntrusiveRefCntPtr<clang::DiagnosticIDs> DiagID(new clang::DiagnosticIDs()); 
    clang::DiagnosticsEngine Diags(DiagID, &opt, DiagClient); 

    // Create the compiler invocation 
    clang::CompilerInvocation* CI(new clang::CompilerInvocation()); 
    clang::CompilerInvocation::CreateFromArgs(*CI, &args[0], &args[0] + args.size(), Diags); 

    // Create the compiler instance 
    clang::CompilerInstance Clang; 
    Clang.setInvocation(CI); 

    // Get ready to report problems 
    Clang.createDiagnostics(&Diags.getDiagnosticOptions()); 
    if (!Clang.hasDiagnostics()) 
     return NULL; 

    // Create an action and make the compiler instance carry it out 
    clang::CodeGenAction *Act = new clang::EmitLLVMOnlyAction(&llvm::getGlobalContext()); 
    if (!Clang.ExecuteAction(*Act)) 
     return NULL; 

    return Act; 
} 

int main(void) 
{ 
    clang::CodeGenAction* Act = getAction(); 

    // Grab the module built by the EmitLLVMOnlyAction 
    std::unique_ptr<llvm::Module> module = Act->takeModule(); 

    // Print all functions in the module 
    for (llvm::Module::FunctionListType::iterator i = module->getFunctionList().begin(); i != module->getFunctionList().end(); ++i) 
     printf("%s\n", i->getName().str().c_str()); 

    return 0; 
} 

Ошибки, которые я получил во время связывания:

LNK1120: 2 unresolved externals 

LNK2001: unresolved external symbol "public: __thiscall clang::EmitLLVMOnlyAction::EmitLLVMOnlyAction(class llvm::LLVMContext *)" ([email protected]@@[email protected]@[email protected]@@Z) 

LNK2001: unresolved external symbol "public: class std::unique_ptr<class llvm::Module,struct std::default_delete<class llvm::Module> > __thiscall clang::CodeGenAction::takeModule(void)" ([email protected]@[email protected]@[email protected]@[email protected]@[email protected]@[email protected]@@[email protected]@@[email protected]@XZ) 

ответ

1

В лязг генерации кода происходит в CodeGenModule классе. Там вы можете получить текущий модуль через llvm::Module & getModule() const. CodeGenModule обрабатывает генерацию кода на уровне модуля, а CodeGenFunction делает это для определенной функции. Там вы найдете Emit* функции для каждого узла АСТ.

+0

Спасибо, я попробовал, но я не мог заставить его работать. Я закончил с нерешенными внешними ошибками, поэтому я попробовал его с помощью CodeGenAction и получил аналогичные ошибки. Я отредактировал оригинальный ответ. Любые намеки? – benderto

+0

@benderto символ отсутствует в коде CodeGenAction.cpp, поэтому вам необходимо: скомпилировать CodeGenAction.cpp с вашим приложением или b: связать clang CodeGen libs с вашим приложением. –

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