LLVM和clang的工作流程

时间:2018-07-06 15:20:47

标签: llvm llvm-clang llvm-ir

我只是LLVM和(https://www.cs.cornell.edu/~asampson/blog/llvm.html)网页以及堆栈溢出的初学者,而我的研究员也为我提供了很多帮助。 首先,我想说明一下我正在尝试解决的问题,然后将介绍解决该问题所采用的方法。 然后,如果我有任何缺失,我需要您的建议和指导。

工作问题

我的输入是一个C程序,输出是它的SSA形式,其前缀表示形式打印在输出文件中。 例如,如果C代码段是:

x=4;
x++;
z=x+7;

以前缀表示的输出SSA形式为:

( = x0 4) 
( = x1 (+ x0 1) )
( = z (x1 + 7) )

请暂时忽略实际的IR指令,仅假设我能够读取IR并将其转换为这种形式,并带有一些额外的语句(为便于阅读,此处不再赘述)。

使用LLVM的无知方法(请在下面找到完整的程序)

using namespace llvm;
namespace {
struct TestPass: public ModulePass {
    IRssa::ptr ir_ssa = IRssa::ptr(new IRssa());
    static char ID; 
    typedef std::list<std::pair<std::string, std::list<Instruction *> > > funcDump;
    TestPass() : ModulePass(ID) { }
        std::map<std::string, funcDump> workingList;
        bool runOnModule(Module &M) {
            std::string funcName, bkName;
            for (Function &F : M) {    //Found a new Function
                if (isa<Function>(F) && !(F.getName().startswith("llvm."))) {
                    funcName = F.getName();
                    std::pair<std::string, std::list<Instruction *> > funcBlockList;
                    std::list<std::pair<std::string, std::list<Instruction *> > > wholeFuncBlocks;
                    for (BasicBlock &B : F) {    //Blocks of the Function
                        if (isa<BasicBlock>(B)) {
                            bkName = B.getName();
                        }
                        std::list<Instruction *> listInst;
                        for (auto &I : B) {
                            Instruction *ins;
                            ins = &I;
                            listInst.push_back(ins);       
                        }
                        funcBlockList.first = bkName;
                        funcBlockList.second = listInst;
                        wholeFuncBlocks.push_back(funcBlockList);
                    }
                    workingList[funcName] = wholeFuncBlocks;//Mapping of the functions
                }
            }
            ir_ssa->setFunctionDump(workingList); 
            funcDump funcData;
            funcData = workingList["start_program"];    //Starting from the start_program function
                 convertFunctionToSSA(funcData, ir_ssa);
            std::ofstream outFile;
            outFile.open("Out.ssa");
            printSSA_toFile(outFile, ir_ssa);
        return false;
    }
    };
}
    char TestPass::ID = 0;
    static RegisterPass<TestPass> X("testPass", "Testing A Pass");
    static void registerTestPass(const PassManagerBuilder &, legacy::PassManagerBase &PM) {
                    PM.add(new TestPass());
            }
    static RegisterStandardPasses RegisterMyPass(PassManagerBuilder::EP_ModuleOptimizerEarly, registerTestPass);
    static RegisterStandardPasses RegisterMyPass0(PassManagerBuilder::EP_EnabledOnOptLevel0, registerTestPass);
    //Automatically enable the pass (http://adriansampson.net/blog/clangpass.html)

说明:

如上所述,我正在调用runOnModule()并将程序中每个功能的所有块的所有IR指令收集到workingList数据结构中(在这种情况下为std :: map)。给定程序中的所有功能读取完后,我便一次完成读取红外线指令的必要任务,逐个功能逐个块读取(在用户定义的函数convertFunctionToSSA(funcData,ir_ssa)中使用整个函数将IR作为参数,并在参数ir_ssa中返回处理这些IR的结果。我还将ir_ssa的结果值打印到输出文件outFile中。

现在如何运行(我输入以下内容)

clang -O1 -g -Xclang -emit-llvm -c someProgram.c -o test.bc
opt -O1 -instnamer -mem2reg -simplifycfg  -loops  -lcssa -loop-simplify -loop-rotate -loop-unroll -unroll-count=15 -unroll-allow-partial -load src/libTestPass.so -testPass test.bc -o test

我的期望

根据我的理解,我假设以上两个命令将执行以下操作。 第一个clang使用程序someProgram.c并生成IR作为输出文件“ test.bc”。 下一个命令opt,使用文件“ test.bc”,然后逐个应用上述所有步骤,直到最后一个步骤“ -unroll-allow-partial”,并且它还链接了我的库libTestPass.so(此.so文件是然后在编译上述ModulePass程序时生成),最后,传递“ -testPass”,我认为这是我正在执行我的过程(转换为SSA前缀表示形式)的传递。

您的建议和评论

我不确定LLVM是否按照我所假设的顺序实际运行(我的期望)。如果我缺少任何东西或我的假设不正确,请发表评论。另外,如有必要,请随时询问更多详细信息。

当前面临的问题

我能够成功转换大多数C程序,但是在一个特定程序上,我遇到了一些错误。调试该错误使我认为我对LLVM的这种工作方式缺乏思索,或者关于clang和opt的调用顺序的假设是不正确的。

我们非常感谢您的帮助。

0 个答案:

没有答案