clang 分析OpenCL 代码

来源:互联网 发布:伊藤润二的漫画 知乎 编辑:程序博客网 时间:2024/05/16 13:45

目前仅实现了对参数qualifier的提取,可以很方便在ast上加入其他操作。

#include <iostream>

#include "llvm/Support/Host.h"
#include "llvm/ADT/IntrusiveRefCntPtr.h"


#include "clang/Basic/DiagnosticOptions.h"
#include "clang/Frontend/TextDiagnosticPrinter.h"
#include "clang/Frontend/CompilerInstance.h"
#include "clang/Basic/TargetOptions.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/Basic/FileManager.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Lex/Preprocessor.h"
#include "clang/Basic/Diagnostic.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/ASTConsumer.h"
#include "clang/Parse/Parser.h"
#include "clang/Parse/ParseAST.h"
class MyASTConsumer : public clang::ASTConsumer
{
public:
    MyASTConsumer() : clang::ASTConsumer() { }
    virtual ~MyASTConsumer() { }


    virtual bool HandleTopLevelDecl( clang::DeclGroupRef d)
    {
        clang::DeclGroupRef::iterator it;
        for( it = d.begin(); it != d.end(); it++)
        {
            clang::FunctionDecl *fd=llvm::dyn_cast<clang::FunctionDecl>(*it);
            if(!fd)
            {
                continue;
            }

              if( fd->isFunctionOrMethod()) {

                std::string res=clang::QualType::getAsString(fd->getResultType().split());
                std::size_t found = res.find("__attribute__((address_space(8)))"); /* find __kernel qualifer */
                if (found != std::string::npos) {
                    std::cout << fd->getNameInfo().getAsString() << "\n";
                    std::cout << fd->getNumParams()<<"\n"; /*number paramters */
                    clang::ParmVarDecl* pd;
                    for(int i = 0; i < fd->getNumParams(); i++) {
                        pd=fd->getParamDecl(i);
                        std::cout << clang::QualType::getAsString(pd->getType().split()) <<"\n"; /* parameter type */
                    }
                }
            }
        }
        return true;
    }
};


int main(int argc, char **argv)
{
    using clang::CompilerInstance;
    using clang::TargetOptions;
    using clang::TargetInfo;
    using clang::FileEntry;
    using clang::Token;
    using clang::ASTContext;
    using clang::ASTConsumer;
    using clang::Parser;
    using clang::DiagnosticOptions;
    using clang::TextDiagnosticPrinter;
    using clang::CompilerInvocation;
    using clang::LangOptions;


    CompilerInstance ci;
    DiagnosticOptions diagnosticOptions;
    ci.createDiagnostics();


    CompilerInvocation *Invocation = new CompilerInvocation;
    ci.setInvocation(Invocation);
    LangOptions langOpts;
    langOpts.RTTI = 1;
    langOpts.Bool = 1;
    langOpts.OpenCL= 1;
    Invocation->setLangDefaults(langOpts,

                              clang::IK_OpenCL,
                              clang::LangStandard::lang_opencl);


    llvm::IntrusiveRefCntPtr<TargetOptions> pto( new TargetOptions());
    pto->Triple = llvm::sys::getDefaultTargetTriple();
    TargetInfo *pti = TargetInfo::CreateTargetInfo(ci.getDiagnostics(), pto.getPtr());
    ci.setTarget(pti);


    ci.createFileManager();
    ci.createSourceManager(ci.getFileManager());
    ci.createPreprocessor();
    ci.getPreprocessorOpts().UsePredefines = false;
    MyASTConsumer *astConsumer = new MyASTConsumer();
    ci.setASTConsumer(astConsumer);


    ci.createASTContext();


    const FileEntry *pFile = ci.getFileManager().getFile(argv[1]);
    ci.getSourceManager().createMainFileID(pFile);
    ci.getDiagnosticClient().BeginSourceFile(ci.getLangOpts(),
                                           &ci.getPreprocessor());
    clang::ParseAST(ci.getPreprocessor(), astConsumer, ci.getASTContext());
    ci.getDiagnosticClient().EndSourceFile();


    return 0;
}


makefile


CXX := clang++
LLVMCOMPONENTS := cppbackend
RTTIFLAG := -fno-rtti
LLVMCONFIG := /sandbox/xiuxia/llvm_build/Debug+Asserts/bin/llvm-config


CXXFLAGS := -I$(shell $(LLVMCONFIG) --src-root)/tools/clang/include -I$(shell $(LLVMCONFIG) --obj-root)/tools/clang/include $(shell $(LLVMCONFIG) --cxxflags) $(RTTIFLAG)
LLVMLDFLAGS := $(shell $(LLVMCONFIG) --ldflags --libs $(LLVMCOMPONENTS))


SOURCES = CI_opencl.cpp


OBJECTS = $(SOURCES:.cpp=.o)
EXES = $(OBJECTS:.o=)
CLANGLIBS = \
                -lclangTooling\
                -lclangFrontendTool\
                -lclangFrontend\
                -lclangDriver\
                -lclangSerialization\
                -lclangCodeGen\
                -lclangParse\
                -lclangSema\
                -lclangStaticAnalyzerFrontend\
                -lclangStaticAnalyzerCheckers\
                -lclangStaticAnalyzerCore\
                -lclangAnalysis\
                -lclangARCMigrate\
                -lclangRewriteFrontend\

                -lclangRewriteCore\
                -lclangEdit\
                -lclangAST\
                -lclangLex\
                -lclangBasic\
                $(shell $(LLVMCONFIG) --libs)\
                -lcurses


all: $(OBJECTS) $(EXES)


%: %.o
    $(CXX) -o $@ $< $(CLANGLIBS) $(LLVMLDFLAGS)


clean:
    -rm -f $(EXES) $(OBJECTS) *~

0 0