From 3fd7a3a8e9bb3c42c1ecb954d99ee3b4218c011e Mon Sep 17 00:00:00 2001 From: Erik Verbruggen Date: Thu, 18 Oct 2012 11:07:10 +0200 Subject: [PATCH] Moved LLVM specific code out of main.cpp. Change-Id: I16c79667625d5034acb91cec13c22ed58b74984f Reviewed-by: Simon Hausmann --- main.cpp | 65 ++++-------------------------- qv4_llvm_p.h | 43 ++++++++++++++++++++ qv4isel_llvm.cpp | 118 +++++++++++++++++++++++++++++++++++++++++++++++++++---- qv4isel_llvm_p.h | 14 ++++++- v4.pro | 3 +- 5 files changed, 175 insertions(+), 68 deletions(-) create mode 100644 qv4_llvm_p.h diff --git a/main.cpp b/main.cpp index becd301..261aeff 100644 --- a/main.cpp +++ b/main.cpp @@ -40,22 +40,7 @@ ****************************************************************************/ #ifndef QMLJS_NO_LLVM -// These includes have to come first, because WTF/Platform.h defines some macros -// with very unfriendly names that collide with class fields in LLVM. -# include -# include -# include -# include -# include -# include -# include -# include -# include -# include -# include -# include - -# include "qv4isel_llvm_p.h" +# include "qv4_llvm_p.h" #endif #include "qmljs_objects.h" @@ -138,50 +123,16 @@ void compile(const QString &fileName, const QString &source) << ": error: " << qPrintable(m.message) << std::endl; } - if (parsed) { - using namespace AST; - Program *program = AST::cast(parser.rootNode()); + if (!parsed) + return; - Codegen cg; - /*IR::Function *globalCode =*/ cg(program, &module); + using namespace AST; + Program *program = AST::cast(parser.rootNode()); - LLVMInstructionSelection llvmIsel(llvm::getGlobalContext()); - if (llvm::Module *llvmModule = llvmIsel.getLLVMModule(&module)) { - llvm::PassManager PM; + Codegen cg; + /*IR::Function *globalCode =*/ cg(program, &module); - const std::string triple = llvm::sys::getDefaultTargetTriple(); - - LLVMInitializeX86TargetInfo(); - LLVMInitializeX86Target(); - LLVMInitializeX86AsmPrinter(); - LLVMInitializeX86AsmParser(); - LLVMInitializeX86Disassembler(); - LLVMInitializeX86TargetMC(); - - std::string err; - const llvm::Target *target = llvm::TargetRegistry::lookupTarget(triple, err); - if (! err.empty()) { - std::cerr << err << ", triple: " << triple << std::endl; - assert(!"cannot create target for the host triple"); - } - - - std::string cpu; - std::string features; - llvm::TargetOptions options; - llvm::TargetMachine *targetMachine = target->createTargetMachine(triple, cpu, features, options, llvm::Reloc::PIC_); - assert(targetMachine); - - llvm::formatted_raw_ostream out(llvm::outs()); - PM.add(llvm::createScalarReplAggregatesPass()); - PM.add(llvm::createInstructionCombiningPass()); - PM.add(llvm::createGlobalOptimizerPass()); - PM.add(llvm::createFunctionInliningPass(25)); - targetMachine->addPassesToEmitFile(PM, out, llvm::TargetMachine::CGFT_AssemblyFile); - PM.run(*llvmModule); - delete llvmModule; - } - } + compileWithLLVM(&module, fileName); } int compileFiles(const QStringList &files) diff --git a/qv4_llvm_p.h b/qv4_llvm_p.h new file mode 100644 index 0000000..729da2d --- /dev/null +++ b/qv4_llvm_p.h @@ -0,0 +1,43 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#ifndef QV4_LLVM_P_H +#define QV4_LLVM_P_H + +#include "qv4ir_p.h" + +#include + +namespace QQmlJS { + +void compileWithLLVM(IR::Module *module, const QString &fileName); + +} // QQmlJS + +#endif // QV4_LLVM_P_H diff --git a/qv4isel_llvm.cpp b/qv4isel_llvm.cpp index c2cc4c1..f6e79c9 100644 --- a/qv4isel_llvm.cpp +++ b/qv4isel_llvm.cpp @@ -39,16 +39,117 @@ ** ****************************************************************************/ -#include "qv4isel_llvm_p.h" -#include "qv4ir_p.h" - -#include +#ifdef __clang__ +# pragma clang diagnostic push +# pragma clang diagnostic ignored "-Wunused-parameter" +#endif // __clang__ -#include -#include +#include +#include #include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include #include + +#ifdef __clang__ +# pragma clang diagnostic pop +#endif // __clang__ + +#include +#include +#include +#include #include +#include + +// These includes have to come last, because WTF/Platform.h defines some macros +// with very unfriendly names that collide with class fields in LLVM. +#include "qv4isel_llvm_p.h" +#include "qv4ir_p.h" + +namespace QQmlJS { + +void compileWithLLVM(IR::Module *module, const QString &fileName) +{ + Q_ASSERT(module); + + const QString moduleName = QFileInfo(fileName).fileName(); + + LLVMInstructionSelection llvmIsel(llvm::getGlobalContext()); + llvm::Module *llvmModule = llvmIsel.getLLVMModule(module, moduleName); + if (!llvmModule) + return; + + // TODO: if output type is .ll, print the module to file + + llvm::PassManager PM; + + const std::string triple = llvm::sys::getDefaultTargetTriple(); + + LLVMInitializeX86TargetInfo(); + LLVMInitializeX86Target(); + LLVMInitializeX86AsmPrinter(); + LLVMInitializeX86AsmParser(); + LLVMInitializeX86Disassembler(); + LLVMInitializeX86TargetMC(); + + std::string err; + const llvm::Target *target = llvm::TargetRegistry::lookupTarget(triple, err); + if (! err.empty()) { + std::cerr << err << ", triple: " << triple << std::endl; + assert(!"cannot create target for the host triple"); + } + + std::string cpu; + std::string features; + llvm::TargetOptions options; + llvm::TargetMachine *targetMachine = target->createTargetMachine(triple, cpu, features, options, llvm::Reloc::PIC_); + assert(targetMachine); + + llvm::TargetMachine::CodeGenFileType ft; + QString ofName; + + ft = llvm::TargetMachine::CGFT_ObjectFile; + ofName = fileName + QLatin1String(".o"); + + // TODO: +// ft = llvm::TargetMachine::CGFT_AssemblyFile; +// ofName = fileName + QLatin1String(".s"); + + llvm::raw_fd_ostream dest(ofName.toUtf8().constData(), err, llvm::raw_fd_ostream::F_Binary); + llvm::formatted_raw_ostream destf(dest); + if (!err.empty()) { + std::cerr << err << std::endl; + delete llvmModule; + } + + PM.add(llvm::createScalarReplAggregatesPass()); + PM.add(llvm::createInstructionCombiningPass()); + PM.add(llvm::createGlobalOptimizerPass()); + PM.add(llvm::createFunctionInliningPass(25)); + if (targetMachine->addPassesToEmitFile(PM, destf, ft)) { + std::cerr << err << " (probably no DataLayout in TargetMachine)" << std::endl; + } else { + PM.run(*llvmModule); + + destf.flush(); + dest.flush(); + } + + delete llvmModule; +} + +} // QQmlJS using namespace QQmlJS; @@ -72,9 +173,10 @@ LLVMInstructionSelection::LLVMInstructionSelection(llvm::LLVMContext &context) { } -llvm::Module *LLVMInstructionSelection::getLLVMModule(IR::Module *module) +llvm::Module *LLVMInstructionSelection::getLLVMModule(IR::Module *module, const QString &moduleName) { - llvm::Module *llvmModule = new llvm::Module("a.out", getContext()); + llvm::StringRef moduleId(moduleName.toUtf8().constData()); + llvm::Module *llvmModule = new llvm::Module(moduleId, getContext()); qSwap(_llvmModule, llvmModule); _numberTy = getDoubleTy(); diff --git a/qv4isel_llvm_p.h b/qv4isel_llvm_p.h index 6c661ca..a2446a5 100644 --- a/qv4isel_llvm_p.h +++ b/qv4isel_llvm_p.h @@ -41,10 +41,20 @@ #ifndef QV4ISEL_LLVM_P_H #define QV4ISEL_LLVM_P_H -#include "qv4ir_p.h" +#ifdef __clang__ +# pragma clang diagnostic push +# pragma clang diagnostic ignored "-Wunused-parameter" +#endif // __clang__ + #include #include +#ifdef __clang__ +# pragma clang diagnostic pop +#endif // __clang__ + +#include "qv4ir_p.h" + namespace QQmlJS { class LLVMInstructionSelection: @@ -55,7 +65,7 @@ class LLVMInstructionSelection: public: LLVMInstructionSelection(llvm::LLVMContext &context); - llvm::Module *getLLVMModule(IR::Module *module); + llvm::Module *getLLVMModule(IR::Module *module, const QString &moduleName); llvm::Function *getLLVMFunction(IR::Function *function); llvm::Function *compileLLVMFunction(IR::Function *function); llvm::BasicBlock *getLLVMBasicBlock(IR::BasicBlock *block); diff --git a/v4.pro b/v4.pro index b51850e..2740936 100644 --- a/v4.pro +++ b/v4.pro @@ -38,7 +38,8 @@ SOURCES += \ qv4isel_llvm.cpp HEADERS += \ - qv4isel_llvm_p.h + qv4isel_llvm_p.h \ + qv4_llvm_p.h INCLUDEPATH += \ $$system($$LLVM_CONFIG --includedir) -- 2.7.4