【问题标题】:Method to create LLVM IR创建 LLVM IR 的方法
【发布时间】:2014-12-13 18:53:45
【问题描述】:

我正在创建 clang 工具,我想从 clang AST 生成 LLVM IR。我知道-emit-llvm 可以用来获取*.ll 文件的选项,但是有没有办法在代码中生成IR?我可以调用的某些方法采用 clang AST 或 AST 上下文并返回 llvm::Module?我找不到任何可以说明这一点的例子。

已编辑: 所以我尝试为此使用 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 *)" (??0EmitLLVMOnlyAction@clang@@QAE@PAVLLVMContext@llvm@@@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)" (?takeModule@CodeGenAction@clang@@QAE?AV?$unique_ptr@VModule@llvm@@U?$default_delete@VModule@llvm@@@std@@@std@@XZ)

【问题讨论】:

    标签: clang llvm abstract-syntax-tree llvm-clang llvm-ir


    【解决方案1】:

    在 clang 中,代码生成发生在 CodeGenModule 类中。在那里您可以通过llvm::Module &amp; getModule () const 获取当前模块。 CodeGenModule 处理模块级别的代码生成,而 CodeGenFunction 为特定功能执行此操作。在那里您可以找到 AST 的每个节点的 Emit* 函数。

    【讨论】:

    • 谢谢,我试过了,但我不能让它工作。我最终遇到了未解决的外部错误,因此我使用CodeGenAction 进行了尝试,并最终遇到了类似的错误。我编辑了原始答案。有什么提示吗?
    • @benderto 缺少的符号在 CodeGenAction.cpp 中声明,因此您必须 a:使用您的应用程序编译 CodeGenAction.cpp 或 b:将 clang CodeGen 库链接到您的应用程序。
    猜你喜欢
    • 1970-01-01
    • 2018-02-09
    • 1970-01-01
    • 1970-01-01
    • 2013-11-17
    • 1970-01-01
    • 1970-01-01
    • 2017-04-09
    • 2014-10-30
    相关资源
    最近更新 更多