Commit 13a04c3a authored by Mccaskey, Alex's avatar Mccaskey, Alex
Browse files

moved to clang tooling rewriter approach to enable use with any host compiler....


moved to clang tooling rewriter approach to enable use with any host compiler. moved qpu_handler to using algorithm interface
Signed-off-by: Mccaskey, Alex's avatarAlex McCaskey <mccaskeyaj@ornl.gov>
parent 5f136652
Pipeline #45685 passed with stages
in 2 minutes and 21 seconds
......@@ -29,7 +29,6 @@ endif()
set(CppMicroServicesConfig_DIR "${XACC_ROOT}/share/cppmicroservices4/cmake")
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${XACC_ROOT}/share/xacc")
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CppMicroServicesConfig_DIR}")
include(tests)
include(CppMicroServicesConfig)
include_directories(${XACC_INCLUDE_DIRS})
......
......@@ -17,7 +17,7 @@ const std::shared_ptr<Function>
QCORCompiler::compile(std::shared_ptr<Function> f, std::shared_ptr<Accelerator> acc) {
if (acc) {
xacc::info("[qcor] Compiling for " + acc->name());
// xacc::info("[qcor] Compiling for " + acc->name());
}
// Hardware Independent Transformation
......@@ -27,7 +27,7 @@ QCORCompiler::compile(std::shared_ptr<Function> f, std::shared_ptr<Accelerator>
if (acc) {
}
// Program Verification???
return f;
......
set(LIBRARY_NAME qcor-ast-plugin)
add_library(${LIBRARY_NAME}
SHARED
QCORPluginAction.cpp
FuzzyParsingExternalSemaSource.cpp
LambdaVisitor.cpp
QCORASTConsumer.cpp)
......@@ -14,7 +13,7 @@ target_include_directories(${LIBRARY_NAME}
${XACC_INCLUDE_ROOT}/xacc
${XACC_INCLUDE_ROOT}/cppmicroservices4)
target_link_libraries(${LIBRARY_NAME}
PUBLIC ${CLANG_LIBS} ${XACC_LIBRARIES} qcor)
PUBLIC ${CLANG_LIBS} ${LLVM_LIBS} ${XACC_LIBRARIES} qcor)
if(APPLE)
set_target_properties(${LIBRARY_NAME} PROPERTIES INSTALL_RPATH "@loader_path")
set_target_properties(${LIBRARY_NAME} PROPERTIES LINK_FLAGS "-undefined dynamic_lookup")
......@@ -23,3 +22,13 @@ else()
set_target_properties(${LIBRARY_NAME} PROPERTIES LINK_FLAGS "-shared")
endif()
install(TARGETS ${LIBRARY_NAME} DESTINATION lib)
if(QCOR_BUILD_TESTS)
add_subdirectory(tests)
endif()
configure_file(qcor-driver.in.cpp
${CMAKE_BINARY_DIR}/compiler/clang/qcor-driver.cpp)
add_executable(qcor-driver ${CMAKE_BINARY_DIR}/qcor-driver.cpp)
target_link_libraries(qcor-driver PRIVATE qcor-ast-plugin qcor xacc)
install(PROGRAMS ${CMAKE_BINARY_DIR}/compiler/clang/qcor-driver DESTINATION bin)
\ No newline at end of file
......@@ -2,6 +2,8 @@
#include "IRProvider.hpp"
#include "XACC.hpp"
#include "IRGenerator.hpp"
#include "xacc_service.hpp"
using namespace clang;
......@@ -14,6 +16,11 @@ FuzzyParsingExternalSemaSource::FuzzyParsingExternalSemaSource(
auto irProvider = xacc::getService<xacc::IRProvider>("gate");
validInstructions = irProvider->getInstructions();
validInstructions.push_back("CX");
auto irgens = xacc::getRegisteredIds<xacc::IRGenerator>();
for (auto& irg : irgens) {
validInstructions.push_back(irg);
}
}
bool FuzzyParsingExternalSemaSource::LookupUnqualified(clang::LookupResult &R,
......
#include "LambdaVisitor.hpp"
#include "IRGenerator.hpp"
#include "IRProvider.hpp"
#include "XACC.hpp"
#include "xacc_service.hpp"
#include "qcor.hpp"
#include "clang/AST/Decl.h"
#include "clang/Basic/IdentifierTable.h"
#include "clang/Basic/SourceLocation.h"
#include "clang/Sema/Sema.h"
#include "clang/Tooling/Tooling.h"
using namespace clang;
using namespace xacc;
......@@ -16,6 +22,10 @@ LambdaVisitor::IsQuantumKernelVisitor::IsQuantumKernelVisitor(ASTContext &c)
auto irProvider = xacc::getService<xacc::IRProvider>("gate");
validInstructions = irProvider->getInstructions();
validInstructions.push_back("CX");
auto irgens = xacc::getRegisteredIds<xacc::IRGenerator>();
for (auto &irg : irgens) {
validInstructions.push_back(irg);
}
}
bool LambdaVisitor::IsQuantumKernelVisitor::VisitDeclRefExpr(
......@@ -33,6 +43,11 @@ LambdaVisitor::CppToXACCIRVisitor::CppToXACCIRVisitor(ASTContext &c)
: context(c) {
provider = xacc::getService<IRProvider>("gate");
function = provider->createFunction("tmp", {});
auto irgens = xacc::getRegisteredIds<xacc::IRGenerator>();
for (auto &irg : irgens) {
irGeneratorNames.push_back(irg);
}
}
bool LambdaVisitor::CppToXACCIRVisitor::VisitCallExpr(CallExpr *expr) {
......@@ -42,8 +57,16 @@ bool LambdaVisitor::CppToXACCIRVisitor::VisitCallExpr(CallExpr *expr) {
gateName = "CNOT";
}
auto inst = provider->createInstruction(gateName, bits, parameters);
function->addInstruction(inst);
if (std::find(irGeneratorNames.begin(), irGeneratorNames.end(), gateName) !=
irGeneratorNames.end()) {
std::cout << "This is an IR Generator\n";
auto irg = xacc::getService<IRGenerator>(gateName);
function->addInstruction(irg);
} else {
auto inst = provider->createInstruction(gateName, bits, parameters);
function->addInstruction(inst);
}
}
gateName = "";
bits.clear();
......@@ -65,6 +88,11 @@ bool LambdaVisitor::CppToXACCIRVisitor::VisitDeclRefExpr(DeclRefExpr *expr) {
return true;
}
bool LambdaVisitor::CppToXACCIRVisitor::VisitParmVarDecl(ParmVarDecl *decl) {
// std::cout << "FOUND PARM VAR DECL, " << decl->getNameAsString() << "\n";
parameters.push_back(InstructionParameter(decl->getNameAsString()));
return true;
}
bool LambdaVisitor::CppToXACCIRVisitor::VisitIntegerLiteral(
IntegerLiteral *literal) {
......@@ -91,12 +119,19 @@ std::shared_ptr<Function> LambdaVisitor::CppToXACCIRVisitor::getFunction() {
gateName = "CNOT";
}
auto inst = provider->createInstruction(gateName, bits, parameters);
function->addInstruction(inst);
if (std::find(irGeneratorNames.begin(), irGeneratorNames.end(), gateName) !=
irGeneratorNames.end()) {
std::cout << "This is an IR Generator " << gateName << "\n";
auto irg = xacc::getService<IRGenerator>(gateName);
function->addInstruction(irg);
} else {
auto inst = provider->createInstruction(gateName, bits, parameters);
function->addInstruction(inst);
}
}
return function;
}
LambdaVisitor::LambdaVisitor(CompilerInstance &c) : ci(c) {}
LambdaVisitor::LambdaVisitor(CompilerInstance &c, Rewriter& rw) : ci(c), rewriter(rw) {}
bool LambdaVisitor::VisitLambdaExpr(LambdaExpr *LE) {
......@@ -106,16 +141,13 @@ bool LambdaVisitor::VisitLambdaExpr(LambdaExpr *LE) {
// Double check... Is this a Quantum Kernel Lambda?
IsQuantumKernelVisitor isqk(ci.getASTContext());
isqk.TraverseStmt(LE->getBody());
// LE->dump();
// If it is, then map it to XACC IR
if (isqk.isQuantumKernel()) {
// For debugging for now
// std::cout << "\n\n";
// q_kernel_body->dump();
CppToXACCIRVisitor visitor(ci.getASTContext());
visitor.TraverseStmt(LE->getBody());
visitor.TraverseStmt(LE);
auto function = visitor.getFunction();
// std::cout << "\n\nXACC IR:\n" << function->toString() << "\n";
......@@ -130,39 +162,43 @@ bool LambdaVisitor::VisitLambdaExpr(LambdaExpr *LE) {
function = qcor->compile(function, targetAccelerator);
auto fileName = qcor::persistCompiledCircuit(function);
auto fileName = qcor::persistCompiledCircuit(function, targetAccelerator);
// Create the const char * QualType
auto sr = LE->getSourceRange();
rewriter.ReplaceText(sr, "[&](){return \"" + fileName + "\";}");
// Here we update the AST Node to change the
// function prototype to string ()
SourceLocation sl;
QualType StrTy = ci.getASTContext().getConstantArrayType(
ci.getASTContext().adjustStringLiteralBaseType(
ci.getASTContext().CharTy.withConst()),
llvm::APInt(32, fileName.length() + 1), ArrayType::Normal, 0);
auto fnameSL = StringLiteral::Create(ci.getASTContext(), StringRef(fileName.c_str()),
StringLiteral::Ascii,
/*Pascal*/ false, StrTy, &sl, 1);
auto fnameSL =
StringLiteral::Create(ci.getASTContext(), StringRef(fileName.c_str()),
StringLiteral::Ascii, false, StrTy, &sl, 1);
// Create New Return type for CallOperator
std::vector<QualType> ParamTypes;
auto D = LE->getCallOperator()->getAsFunction();
FunctionProtoType::ExtProtoInfo fpi;
fpi.Variadic = D->isVariadic();
std::vector<QualType> ParamTypes;
llvm::ArrayRef<QualType> Args(ParamTypes);
QualType newFT = D->getASTContext().getFunctionType(StrTy, Args, fpi);
D->setType(newFT);
// Create the return statement that will return
// the string literal
auto rtrn =
ReturnStmt::Create(ci.getASTContext(), SourceLocation(), fnameSL, nullptr);
std::vector<Stmt *> svec;
// Create the return statement that will return
// the string literal file name
auto rtrn = ReturnStmt::Create(ci.getASTContext(), SourceLocation(),
fnameSL, nullptr);
svec.push_back(rtrn);
llvm::ArrayRef<Stmt *> stmts(svec);
auto cmp = CompoundStmt::Create(ci.getASTContext(), stmts, SourceLocation(),
SourceLocation());
LE->getCallOperator()->setBody(cmp);
}
return true;
}
......@@ -171,6 +207,66 @@ bool LambdaVisitor::VisitLambdaExpr(LambdaExpr *LE) {
} // namespace qcor
// LE->getType().dump();
// Create the const char * QualType
// SourceLocation sl;
// QualType StrTy = ci.getASTContext().getConstantArrayType(
// ci.getASTContext().adjustStringLiteralBaseType(
// ci.getASTContext().CharTy.withConst()),
// llvm::APInt(32, fileName.length() + 1), ArrayType::Normal, 0);
// auto fnameSL =
// StringLiteral::Create(ci.getASTContext(), StringRef(fileName.c_str()),
// StringLiteral::Ascii, false, StrTy, &sl, 1);
// // // Create New Return type for CallOperator
// std::vector<QualType> ParamTypes;
// auto D = LE->getCallOperator()->getAsFunction();
// FunctionProtoType::ExtProtoInfo fpi;
// fpi.Variadic = D->isVariadic();
// llvm::ArrayRef<QualType> Args(ParamTypes);
// QualType newFT = D->getASTContext().getFunctionType(StrTy, Args, fpi);
// D->setType(newFT);
// /*
// Here we need to create instructions that add capture variables
// to a runtime parameter map, so that when this lambda is called,
// any runtime valued variables are added to the map and available
// on the qcor runtime side.
// */
// std::vector<Stmt *> svec;
// auto cb = LE->implicit_capture_begin();
// auto ce = LE->implicit_capture_end();
// for (auto it = cb; it != ce; ++it) {
// it->getCapturedVar()->dump();
// auto e = it->getCapturedVar()->getInit();
// auto value = dyn_cast<IntegerLiteral>(e);
// if (value) {
// std::cout << "THIS VALUE IS KNOWN AT COMPILE TIME: "
// << (int)value->getValue().signedRoundToDouble()
// << "\n"; // getAsString(ci.getASTContext(),
// // it->getCapturedVar()->getType()) << "\n";
// }
// auto varName = it->getCapturedVar()->getNameAsString();
// auto varType =
// it->getCapturedVar()->getType().getCanonicalType().getAsString();
// std::cout << "TYPE: " << varType << "\n";
// }
// Create the return statement that will return
// the string literal file name
// auto rtrn = ReturnStmt::Create(ci.getASTContext(), SourceLocation(),
// fnameSL, nullptr);
// svec.push_back(rtrn);
// llvm::ArrayRef<Stmt *> stmts(svec);
// auto cmp = CompoundStmt::Create(ci.getASTContext(), stmts, SourceLocation(),
// SourceLocation());
// LE->getCallOperator()->setBody(cmp);
// LE->getCallOperator()->dump();
// create empty statement, does nothing
// Stmt *tmp = (Stmt *)new (ci.getASTContext()) NullStmt(nopos);
// std::vector<Stmt *> stmts;
......
......@@ -5,6 +5,12 @@
#include "clang/AST/RecursiveASTVisitor.h"
#include "clang/AST/Stmt.h"
#include "clang/Frontend/CompilerInstance.h"
#include "clang/Frontend/FrontendAction.h"
#include "clang/Parse/ParseAST.h"
#include "clang/Tooling/Tooling.h"
#include "clang/Rewrite/Core/Rewriter.h"
#include "QCORASTConsumer.hpp"
#include "XACC.hpp"
......@@ -39,6 +45,7 @@ protected:
std::shared_ptr<Function> function;
std::shared_ptr<xacc::IRProvider> provider;
std::vector<std::string> irGeneratorNames;
std::string gateName = "";
std::vector<int> bits;
......@@ -50,16 +57,19 @@ protected:
bool VisitDeclRefExpr(DeclRefExpr *expr);
bool VisitIntegerLiteral(IntegerLiteral *literal);
bool VisitFloatingLiteral(FloatingLiteral *literal);
bool VisitParmVarDecl(ParmVarDecl *decl);
std::shared_ptr<Function> getFunction();
};
public:
LambdaVisitor(CompilerInstance &c);
LambdaVisitor(CompilerInstance &c, Rewriter& rw);
bool VisitLambdaExpr(LambdaExpr *LE);
private:
CompilerInstance &ci;
Rewriter& rewriter;
};
} // namespace compiler
} // namespace qcor
......
#include "QCORASTConsumer.hpp"
#include "LambdaVisitor.hpp"
using namespace clang;
namespace qcor {
namespace compiler {
QCORASTConsumer::QCORASTConsumer(CompilerInstance &c)
QCORASTConsumer::QCORASTConsumer(CompilerInstance &c, Rewriter& rw)
: ci(c), fuzzyParser(std::make_shared<FuzzyParsingExternalSemaSource>(
c.getASTContext())) {}
c.getASTContext())), rewriter(rw) {}
bool QCORASTConsumer::HandleTopLevelDecl(DeclGroupRef DR) {
LambdaVisitor Visitor(ci);
LambdaVisitor visitor(ci, rewriter);
ci.getSema().addExternalSource(fuzzyParser.get());
for (DeclGroupRef::iterator b = DR.begin(), e = DR.end(); b != e; ++b) {
Visitor.TraverseDecl(*b);
visitor.TraverseDecl(*b);
}
return true;
}
} // namespace compiler
......
......@@ -2,23 +2,27 @@
#define COMPILER_QCORASTCONSUMER_HPP_
#include "clang/AST/ASTConsumer.h"
#include "clang/Rewrite/Core/Rewriter.h"
#include "FuzzyParsingExternalSemaSource.hpp"
#include "LambdaVisitor.hpp"
namespace clang {
class CompilerInstance;
}
using namespace clang;
namespace qcor {
namespace compiler {
class QCORASTConsumer : public ASTConsumer {
public:
QCORASTConsumer(CompilerInstance &c);
QCORASTConsumer(CompilerInstance &c, Rewriter& rw);
bool HandleTopLevelDecl(DeclGroupRef DR) override;
private:
CompilerInstance &ci;
std::shared_ptr<FuzzyParsingExternalSemaSource> fuzzyParser;
Rewriter& rewriter;
};
} // namespace compiler
} // namespace qcor
......
......@@ -19,9 +19,6 @@ bool QCORPluginAction::ParseArgs(const CompilerInstance &ci,
xacc::Initialize(local);
}
// for (auto a : args) {
// xacc::info("qcor argument: " + a);
// }
auto it = std::find(args.begin(), args.end(), "accelerator");
if (it != args.end()) {
......@@ -46,14 +43,14 @@ bool QCORPluginAction::ParseArgs(const CompilerInstance &ci,
for (int i = 1; i < transformations.size(); ++i) {
transformNames += "," + transformations[i];
}
xacc::setOption("qcor-transforms",transformNames);
xacc::setOption("qcor-transforms", transformNames);
}
return true;
}
PluginASTAction::ActionType QCORPluginAction::getActionType() {
return PluginASTAction::AddBeforeMainAction;
}
// PluginASTAction::ActionType QCORPluginAction::getActionType() {
// return PluginASTAction::AddBeforeMainAction;
// }
} // namespace compiler
} // namespace qcor
......
......@@ -16,9 +16,9 @@ protected:
llvm::StringRef) override;
bool ParseArgs(const CompilerInstance &CI,
const std::vector<std::string> &args) override;
PluginASTAction::ActionType getActionType() override;
// PluginASTAction::ActionType getActionType() override;
};
}
} // namespace compiler
} // namespace qcor
#endif
\ No newline at end of file
#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 "QCORASTConsumer.hpp"
#include "XACC.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 llvm::make_unique<qcor::compiler::QCORASTConsumer>(Compiler,
rewriter);
}
void ExecuteAction() override {
CompilerInstance &CI = getCompilerInstance();
CI.createSema(getTranslationUnitKind(), nullptr);
rewriter.setSourceMgr(CI.getSourceManager(), CI.getLangOpts());
ParseAST(CI.getSema());
CI.getDiagnosticClient().EndSourceFile();
std::string outName(fileName);
size_t ext = outName.rfind(".");
if (ext == std::string::npos)
ext = outName.length();
outName.insert(ext, "_out");
outName = "."+outName;
llvm::errs() << "Output to: " << outName << "\n";
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) {
const RewriteBuffer *RewriteBuf = rewriter.getRewriteBufferFor(
CI.getSourceManager().getMainFileID());
outFile << std::string(RewriteBuf->begin(), RewriteBuf->end());
} else {
llvm::errs() << "Cannot open " << outName << " for writing\n";
}
outFile.close();
}
};
int main(int argc, char **argv) {
xacc::Initialize(argc, argv);
// Get filename
std::string fileName(argv[argc - 1]);
if (!xacc::fileExists(fileName)) {
xacc::error("File " + fileName + " does not exist.");
}
std::ifstream t(fileName);
std::string src((std::istreambuf_iterator<char>(t)),
std::istreambuf_iterator<char>());
// Initialize rewriter
Rewriter Rewrite;
auto action = new QCORFrontendAction(Rewrite, fileName);
std::vector<std::string> args{
"-std=c++11", "-I@CMAKE_INSTALL_PREFIX@/include/qcor",
"-I@CMAKE_INSTALL_PREFIX@/include/xacc",
"-I@CMAKE_INSTALL_PREFIX@/include/cppmicroservices4",
"-I@CMAKE_INSTALL_PREFIX@/include/quantum/gate"};
if (!tooling::runToolOnCodeWithArgs(action, src, args)) {
xacc::error("Error running qcor compiler.");
}
return 0;
}
\ No newline at end of file
configure_file(LambdaVisitorTester.in.cpp
${CMAKE_BINARY_DIR}/compiler/clang/tests/LambdaVisitorTester.cpp)
include_directories(${CMAKE_SOURCE_DIR}/compiler/clang)
add_xacc_test(LambdaVisitor)
target_link_libraries(LambdaVisitorTester qcor qcor-ast-plugin ${CLANG_LIBS})
\ No newline at end of file
#include <gtest/gtest.h>
#include <llvm-9/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 "FuzzyParsingExternalSemaSource.hpp"
#include "LambdaVisitor.hpp"
#include "QCORASTConsumer.hpp"
#include "QCORPluginAction.hpp"
#include "XACC.hpp"
#include "CountGatesOfTypeVisitor.hpp"
#include "Hadamard.hpp"
#include "CNOT.hpp"
#include "Measure.hpp"
#include "qcor.hpp"
#include "clang/Parse/ParseAST.h"
#include <fstream>
using namespace llvm;
using namespace clang;
using namespace qcor;
class TestQCORFrontendAction : public clang::ASTFrontendAction {
public:
TestQCORFrontendAction(Rewriter &rw) : rewriter(rw) {
}