Commit ec489ae6 authored by Mccaskey, Alex's avatar Mccaskey, Alex
Browse files

creating qcor_frontend_action

parent 558209bd
Loading
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -3,7 +3,8 @@ add_library(${LIBRARY_NAME}
            SHARED
            fuzzy_parsing.cpp
            qcor_ast_visitor.cpp
            qcor_ast_consumer.cpp)
            qcor_ast_consumer.cpp
            qcor_frontend_action.cpp)

target_include_directories(${LIBRARY_NAME}
                           PUBLIC .
+7 −127
Original line number Diff line number Diff line
#include "clang/Frontend/FrontendAction.h"

#include "clang/AST/ASTConsumer.h"
#include "clang/AST/RecursiveASTVisitor.h"
#include "clang/Basic/Diagnostic.h"
#include "clang/Basic/DiagnosticOptions.h"
#include "clang/Basic/FileManager.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/Basic/TargetOptions.h"
#include "clang/Frontend/CompilerInstance.h"
#include "clang/Frontend/TextDiagnosticPrinter.h"
#include "clang/Lex/Lexer.h"
#include "clang/Lex/Preprocessor.h"
#include "clang/Parse/ParseAST.h"
#include "clang/Rewrite/Core/Rewriter.h"
#include "clang/Rewrite/Frontend/Rewriters.h"

#include "clang/Tooling/Tooling.h"
#include <fstream>
#include <string>

#include "fuzzy_parsing.hpp"

#include "qcor_ast_consumer.hpp"
#include "xacc.hpp"
#include "xacc_service.hpp"

using namespace clang;

class QCORFrontendAction : public clang::ASTFrontendAction {

public:
  QCORFrontendAction(Rewriter &rw, const std::string file)
      : rewriter(rw), fileName(file) {}

protected:
  Rewriter &rewriter;
  std::string fileName;
  std::unique_ptr<clang::ASTConsumer>
  CreateASTConsumer(clang::CompilerInstance &Compiler,
                    llvm::StringRef /* dummy */) override {
    return std::make_unique<qcor::compiler::QCORASTConsumer>(Compiler,
                                                             rewriter);
  }

  void ExecuteAction() override {

    CompilerInstance &CI = getCompilerInstance();
    CI.createSema(getTranslationUnitKind(), nullptr);
    rewriter.setSourceMgr(CI.getSourceManager(), CI.getLangOpts());

    auto fuzzyParser =
        std::make_shared<qcor::compiler::FuzzyParsingExternalSemaSource>(CI);
    fuzzyParser->initialize();
    // fuzzyParser->setASTContext(&CI.getASTContext());
    // fuzzyParser->setFileManager(&CI.getFileManager());
    CI.getSema().addExternalSource(fuzzyParser.get());

    // FIXME Hook this back up
    // auto pragmaHandlers =
    // xacc::getServices<qcor::compiler::QCORPragmaHandler>(); for (auto p :
    // pragmaHandlers) {
    //     p->setRewriter(&rewriter);
    //     CI.getSema().getPreprocessor().AddPragmaHandler(p.get());
    // }

    ParseAST(CI.getSema());

    // for (auto& p : pragmaHandlers) {
    //     CI.getSema().getPreprocessor().RemovePragmaHandler(p.get());
    // }

    CI.getDiagnosticClient().EndSourceFile();

    // Get the rewrite buffer
    const RewriteBuffer *RewriteBuf =
        rewriter.getRewriteBufferFor(CI.getSourceManager().getMainFileID());

    // if not null, rewrite to .fileName_out.cpp
    if (RewriteBuf) {
      auto getFileName = [](const std::string &s) {
        char sep = '/';

        size_t i = s.rfind(sep, s.length());
        if (i != std::string::npos) {
          return (s.substr(i + 1, s.length() - i));
        }

        return std::string("");
      };

      auto fileNameNoPath = getFileName(fileName);

      if (!fileNameNoPath.empty()) {
        fileName = fileNameNoPath;
      }

      std::string outName(fileName);
      size_t ext = outName.rfind(".");
      if (ext == std::string::npos)
        ext = outName.length();
      outName.insert(ext, "_out");
      outName = "." + outName;

      std::error_code OutErrorInfo;
      std::error_code ok;
      llvm::raw_fd_ostream outFile(llvm::StringRef(outName), OutErrorInfo,
                                   llvm::sys::fs::F_None);

      if (OutErrorInfo == ok) {
        auto s = std::string(RewriteBuf->begin(), RewriteBuf->end());
        outFile << s;
      } else {
        llvm::errs() << "Cannot open " << outName << " for writing\n";
        llvm::errs() << OutErrorInfo.message() << "\n";
      }
      outFile.close();
    } else {

      // Do we need to do anything here?
    }
  }
};
#include "qcor_frontend_action.hpp"

int main(int argc, char **argv) {

  xacc::Initialize(); // argc, argv);
  xacc::Initialize();

  // Get filename
  // FIXME, we assume it is the last arg...
  std::string fileName(argv[argc - 1]);
  if (!xacc::fileExists(fileName)) {
    xacc::error("File " + fileName + " does not exist.");
@@ -140,14 +18,16 @@ int main(int argc, char **argv) {
  // Initialize rewriter
  Rewriter Rewrite;

  auto action = new QCORFrontendAction(Rewrite, fileName);
  auto action = new qcor::compiler::QCORFrontendAction(Rewrite, fileName);
  std::vector<std::string> args{"-Wno-dangling", "-std=c++14",
                                "-I@CMAKE_INSTALL_PREFIX@/include/qcor",
                                "-I@CMAKE_INSTALL_PREFIX@/include/xacc"};

  // Do a little bit of argument analysis
  // We need to know any new include paths
  // and the accelerator backend
  std::string accName = "";
  std::vector<std::string> arguments(argv + 1, argv + argc);
  // Add incoming includes...
  for (int i = 0; i < arguments.size(); i++) {
    if (arguments[i] == "-I") {
      if (arguments[i + 1] != "@CMAKE_INSTALL_PREFIX@/include/qcor" &&
+83 −0
Original line number Diff line number Diff line
#include "qcor_frontend_action.hpp"

namespace qcor {
namespace compiler {
void QCORFrontendAction::ExecuteAction() {

  CompilerInstance &CI = getCompilerInstance();
  CI.createSema(getTranslationUnitKind(), nullptr);
  rewriter.setSourceMgr(CI.getSourceManager(), CI.getLangOpts());

  auto fuzzyParser =
      std::make_shared<qcor::compiler::FuzzyParsingExternalSemaSource>(CI);
  fuzzyParser->initialize();
  // fuzzyParser->setASTContext(&CI.getASTContext());
  // fuzzyParser->setFileManager(&CI.getFileManager());
  CI.getSema().addExternalSource(fuzzyParser.get());

  // FIXME Hook this back up
  // auto pragmaHandlers =
  // xacc::getServices<qcor::compiler::QCORPragmaHandler>(); for (auto p :
  // pragmaHandlers) {
  //     p->setRewriter(&rewriter);
  //     CI.getSema().getPreprocessor().AddPragmaHandler(p.get());
  // }

  ParseAST(CI.getSema());

  // for (auto& p : pragmaHandlers) {
  //     CI.getSema().getPreprocessor().RemovePragmaHandler(p.get());
  // }

  CI.getDiagnosticClient().EndSourceFile();

  // Get the rewrite buffer
  const RewriteBuffer *RewriteBuf =
      rewriter.getRewriteBufferFor(CI.getSourceManager().getMainFileID());

  // if not null, rewrite to .fileName_out.cpp
  if (RewriteBuf) {
    auto getFileName = [](const std::string &s) {
      char sep = '/';

      size_t i = s.rfind(sep, s.length());
      if (i != std::string::npos) {
        return (s.substr(i + 1, s.length() - i));
      }

      return std::string("");
    };

    auto fileNameNoPath = getFileName(fileName);

    if (!fileNameNoPath.empty()) {
      fileName = fileNameNoPath;
    }

    std::string outName(fileName);
    size_t ext = outName.rfind(".");
    if (ext == std::string::npos)
      ext = outName.length();
    outName.insert(ext, "_out");
    outName = "." + outName;

    std::error_code OutErrorInfo;
    std::error_code ok;
    llvm::raw_fd_ostream outFile(llvm::StringRef(outName), OutErrorInfo,
                                 llvm::sys::fs::F_None);

    if (OutErrorInfo == ok) {
      auto s = std::string(RewriteBuf->begin(), RewriteBuf->end());
      outFile << s;
    } else {
      llvm::errs() << "Cannot open " << outName << " for writing\n";
      llvm::errs() << OutErrorInfo.message() << "\n";
    }
    outFile.close();
  } else {

    // Do we need to do anything here?
  }
}
} // namespace compiler
} // namespace qcor
 No newline at end of file
+55 −0
Original line number Diff line number Diff line
#ifndef COMPILER_QCORFRONTENDACTION_HPP_
#define COMPILER_QCORFRONTENDACTION_HPP_

#include "clang/Frontend/FrontendAction.h"

#include "clang/AST/ASTConsumer.h"
#include "clang/AST/RecursiveASTVisitor.h"
#include "clang/Basic/Diagnostic.h"
#include "clang/Basic/DiagnosticOptions.h"
#include "clang/Basic/FileManager.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/Basic/TargetOptions.h"
#include "clang/Frontend/CompilerInstance.h"
#include "clang/Frontend/TextDiagnosticPrinter.h"
#include "clang/Lex/Lexer.h"
#include "clang/Lex/Preprocessor.h"
#include "clang/Parse/ParseAST.h"
#include "clang/Rewrite/Core/Rewriter.h"
#include "clang/Rewrite/Frontend/Rewriters.h"

#include "clang/Tooling/Tooling.h"
#include <fstream>
#include <string>

#include "fuzzy_parsing.hpp"

#include "qcor_ast_consumer.hpp"
#include "xacc.hpp"
#include "xacc_service.hpp"

using namespace clang;

namespace qcor {
namespace compiler {
class QCORFrontendAction : public clang::ASTFrontendAction {
public:
  QCORFrontendAction(Rewriter &rw, const std::string file)
      : rewriter(rw), fileName(file) {}

protected:
  Rewriter &rewriter;
  std::string fileName;
  std::unique_ptr<clang::ASTConsumer>
  CreateASTConsumer(clang::CompilerInstance &Compiler,
                    llvm::StringRef /* dummy */) override {
    return std::make_unique<qcor::compiler::QCORASTConsumer>(Compiler,
                                                             rewriter);
  }

  void ExecuteAction() override;
};
} // namespace compiler
} // namespace qcor
#endif
 No newline at end of file
+32 −80
Original line number Diff line number Diff line
#include <gtest/gtest.h>
#include <llvm/Support/raw_ostream.h>

#include "clang/AST/ASTConsumer.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/RecursiveASTVisitor.h"
#include "clang/Frontend/CompilerInstance.h"
#include "clang/Frontend/FrontendAction.h"
#include "clang/Frontend/FrontendOptions.h"
#include "clang/Tooling/CommonOptionsParser.h"
#include "clang/Tooling/Tooling.h"

#include "clang/Lex/PreprocessorOptions.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/raw_ostream.h"

#include "fuzzy_parsing.hpp"
#include "qcor_ast_visitor.hpp"
#include "qcor_ast_consumer.hpp"

#include "CommonGates.hpp"
#include "CountGatesOfTypeVisitor.hpp"
@@ -25,55 +7,14 @@

#include "clang/Parse/ParseAST.h"

#include "qcor_frontend_action.hpp"

#include <fstream>
using namespace llvm;
using namespace clang;
using namespace qcor;
using namespace qcor::compiler;

class TestQCORFrontendAction : public clang::ASTFrontendAction {

public:
  TestQCORFrontendAction(Rewriter &rw) : rewriter(rw) {}

protected:
  Rewriter &rewriter;
  std::unique_ptr<clang::ASTConsumer>
  CreateASTConsumer(clang::CompilerInstance &Compiler,
                    llvm::StringRef /* dummy */) override {
    return std::make_unique<compiler::QCORASTConsumer>(Compiler, rewriter);
  }

  void ExecuteAction() override {
    CompilerInstance &CI = getCompilerInstance();
    CI.createSema(getTranslationUnitKind(), nullptr);
    compiler::FuzzyParsingExternalSemaSource fuzzyParser(CI);
    fuzzyParser.initialize();
    // fuzzyParser.setASTContext(&CI.getASTContext());
    CI.getSema().addExternalSource(&fuzzyParser);

    rewriter.setSourceMgr(CI.getSourceManager(), CI.getLangOpts());

    ParseAST(CI.getSema());
    CI.getDiagnosticClient().EndSourceFile();

    std::error_code error_code;
    llvm::raw_fd_ostream outFile(".output.cpp", error_code,
                                 llvm::sys::fs::F_None);
    rewriter.getEditBuffer(CI.getSourceManager().getMainFileID())
        .write(outFile);
  }
};

const std::string bell = R"bell(#include <vector>
using qbit = std::vector<int>;
int main() {
    auto l = [&](qbit q) {
        H(q[0]);
        CX(q[0],q[1]);
        Measure(q[0]);
    };
    return 0;
})bell";
const std::string param0 = R"param0(#include <vector>
using qbit = std::vector<int>;
int main() {
@@ -150,13 +91,24 @@ int main() {

TEST(LambdaVisitorTester, checkSimple) {
  Rewriter rewriter1, rewriter2;
  auto action1 = new TestQCORFrontendAction(rewriter1);
  auto action2 = new TestQCORFrontendAction(rewriter2);
  auto action1 = new QCORFrontendAction(rewriter1, "temp.cpp");
//   auto action2 = new TestQCORFrontendAction(rewriter2);

  xacc::setOption("qcor-compiled-filename", "lambda_visitor_tester");

  std::vector<std::string> args{"-std=c++14","-I/usr/lib/gcc/x86_64-linux-gnu/8/include"};

const std::string bell = R"bell(#include <vector>
using qbit = std::vector<int>;
int main() {
    auto l = [&](qbit q) {
        H(q[0]);
        CX(q[0],q[1]);
        Measure(q[0]);
    };
    return 0;
})bell";

  EXPECT_TRUE(tooling::runToolOnCodeWithArgs(action1, bell, args));

  const std::string expectedSrc = R"expectedSrc(
@@ -164,30 +116,30 @@ int main() {
    auto l = [&](){return "lambda_visitor_tester";};
    return 0;
})expectedSrc";
  std::ifstream t(".output.cpp");
  std::ifstream t(".temp_out.cpp");
  std::string src((std::istreambuf_iterator<char>(t)),
                  std::istreambuf_iterator<char>());
  std::remove(".output.cpp");
  std::remove(".temp_out.cpp");
  std::cout << "OUTPUT:\n" << src << "\n";


//   EXPECT_EQ(expectedSrc, src);
  EXPECT_EQ(R"()", src);

//   auto function = qcor::loadCompiledCircuit("lambda_visitor_tester");
//   xacc::quantum::CountGatesOfTypeVisitor<xacc::quantum::Hadamard> h(function);
//   xacc::quantum::CountGatesOfTypeVisitor<xacc::quantum::CNOT> cx(function);
//   xacc::quantum::CountGatesOfTypeVisitor<xacc::quantum::Measure> m(function);
// //   auto function = qcor::loadCompiledCircuit("lambda_visitor_tester");
// //   xacc::quantum::CountGatesOfTypeVisitor<xacc::quantum::Hadamard> h(function);
// //   xacc::quantum::CountGatesOfTypeVisitor<xacc::quantum::CNOT> cx(function);
// //   xacc::quantum::CountGatesOfTypeVisitor<xacc::quantum::Measure> m(function);

//   EXPECT_EQ(1, h.countGates());
//   EXPECT_EQ(1, cx.countGates());
//   EXPECT_EQ(1, m.countGates());
// //   EXPECT_EQ(1, h.countGates());
// //   EXPECT_EQ(1, cx.countGates());
// //   EXPECT_EQ(1, m.countGates());

  EXPECT_TRUE(tooling::runToolOnCodeWithArgs(action2, param0, args));
//   EXPECT_TRUE(tooling::runToolOnCodeWithArgs(action2, param0, args));

  std::ifstream t2(".output.cpp");
  std::string src2((std::istreambuf_iterator<char>(t2)),
                   std::istreambuf_iterator<char>());
  std::remove(".output.cpp");
  std::cout << "OUTPUT:\n" << src2 << "\n";
//   std::ifstream t2(".output.cpp");
//   std::string src2((std::istreambuf_iterator<char>(t2)),
//                    std::istreambuf_iterator<char>());
//   std::remove(".output.cpp");

//   EXPECT_EQ(expectedSrc, src2);
}
Loading