return EXIT_SUCCESS;
}
-int compile(const QString &fileName, const QString &source, bool runInJit)
+int compile(const QString &fileName, const QString &source, QQmlJS::LLVMOutputType outputType)
{
using namespace QQmlJS;
Codegen cg;
/*IR::Function *globalCode =*/ cg(program, &module);
- int (*exec)(void *) = runInJit ? executeLLVMCode : 0;
- return compileWithLLVM(&module, fileName, exec);
+ int (*exec)(void *) = outputType == LLVMOutputJit ? executeLLVMCode : 0;
+ return compileWithLLVM(&module, fileName, outputType, exec);
}
-int compileFiles(const QStringList &files, bool runInJit)
+int compileFiles(const QStringList &files, QQmlJS::LLVMOutputType outputType)
{
foreach (const QString &fileName, files) {
QFile file(fileName);
if (file.open(QFile::ReadOnly)) {
QString source = QString::fromUtf8(file.readAll());
- int result = compile(fileName, source, runInJit);
+ int result = compile(fileName, source, outputType);
if (result != EXIT_SUCCESS)
return result;
}
use_llvm_jit
} mode = use_masm;
+#ifndef QMLJS_NO_LLVM
+ QQmlJS::LLVMOutputType fileType = QQmlJS::LLVMOutputObject;
+#endif // QMLJS_NO_LLVM
+
if (!args.isEmpty()) {
if (args.first() == QLatin1String("--jit")) {
mode = use_masm;
if (args.first() == QLatin1String("--compile")) {
mode = use_llvm_compiler;
args.removeFirst();
+
+ if (!args.isEmpty() && args.first() == QLatin1String("-t")) {
+ args.removeFirst();
+ // Note: keep this list in sync with the enum!
+ static QStringList fileTypes = QStringList() << QLatin1String("ll") << QLatin1String("bc") << QLatin1String("asm") << QLatin1String("obj");
+ if (args.isEmpty() || !fileTypes.contains(args.first())) {
+ std::cerr << "file types: ll, bc, asm, obj" << std::endl;
+ return EXIT_FAILURE;
+ }
+ fileType = (QQmlJS::LLVMOutputType) fileTypes.indexOf(args.first());
+ args.removeFirst();
+ }
}
if (args.first() == QLatin1String("--aot")) {
return EXIT_FAILURE;
#else // QMLJS_NO_LLVM
case use_llvm_jit:
- return compileFiles(args, true);
+ return compileFiles(args, QQmlJS::LLVMOutputJit);
case use_llvm_compiler:
- return compileFiles(args, false);
+ return compileFiles(args, fileType);
case use_llvm_runtime:
return evaluateCompiledCode(args);
#endif // QMLJS_NO_LLVM
namespace QQmlJS {
-int compileWithLLVM(IR::Module *module, const QString &fileName, int (*exec)(void *))
+int compileWithLLVM(IR::Module *module, const QString &fileName, LLVMOutputType outputType, int (*exec)(void *))
{
Q_ASSERT(module);
+ Q_ASSERT(exec || outputType != LLVMOutputJit);
// TODO: should this be done here?
LLVMInitializeX86TargetInfo();
llvm::StringRef moduleId(moduleName.toUtf8().constData());
llvm::Module *llvmModule = new llvm::Module(moduleId, llvmIsel.getContext());
- if (exec) {
+ if (outputType == LLVMOutputJit) {
// The execution engine takes ownership of the model. No need to delete it anymore.
std::string errStr;
llvm::ExecutionEngine *execEngine = llvm::EngineBuilder(llvmModule)
- .setUseMCJIT(true)
-// .setJITMemoryManager(llvm::JITMemoryManager::CreateDefaultMemManager())
+// .setUseMCJIT(true)
.setErrorStr(&errStr).create();
if (!execEngine) {
std::cerr << "Could not create LLVM JIT: " << errStr << std::endl;
return EXIT_FAILURE;
}
- llvm::FunctionPassManager fpm(llvmModule);
+ llvm::FunctionPassManager functionPassManager(llvmModule);
// Set up the optimizer pipeline. Start with registering info about how the
// target lays out data structures.
- fpm.add(new llvm::DataLayout(*execEngine->getDataLayout()));
+ functionPassManager.add(new llvm::DataLayout(*execEngine->getDataLayout()));
+ // Promote allocas to registers.
+ functionPassManager.add(llvm::createPromoteMemoryToRegisterPass());
// Provide basic AliasAnalysis support for GVN.
- fpm.add(llvm::createBasicAliasAnalysisPass());
+ functionPassManager.add(llvm::createBasicAliasAnalysisPass());
// Do simple "peephole" optimizations and bit-twiddling optzns.
- fpm.add(llvm::createInstructionCombiningPass());
+ functionPassManager.add(llvm::createInstructionCombiningPass());
// Reassociate expressions.
- fpm.add(llvm::createReassociatePass());
+ functionPassManager.add(llvm::createReassociatePass());
// Eliminate Common SubExpressions.
- fpm.add(llvm::createGVNPass());
+ functionPassManager.add(llvm::createGVNPass());
// Simplify the control flow graph (deleting unreachable blocks, etc).
- fpm.add(llvm::createCFGSimplificationPass());
+ functionPassManager.add(llvm::createCFGSimplificationPass());
- fpm.doInitialization();
+ functionPassManager.doInitialization();
- llvmIsel.buildLLVMModule(module, llvmModule, &fpm);
+ llvmIsel.buildLLVMModule(module, llvmModule, &functionPassManager);
llvm::Function *entryPoint = llvmModule->getFunction("%entry");
Q_ASSERT(entryPoint);
void *funcPtr = execEngine->getPointerToFunction(entryPoint);
return exec(funcPtr);
} else {
- // TODO: add a FunctionPassManager
- llvmIsel.buildLLVMModule(module, llvmModule, 0);
+ llvm::FunctionPassManager functionPassManager(llvmModule);
+ // Set up the optimizer pipeline.
+ // Promote allocas to registers.
+ functionPassManager.add(llvm::createPromoteMemoryToRegisterPass());
+ // Provide basic AliasAnalysis support for GVN.
+ functionPassManager.add(llvm::createBasicAliasAnalysisPass());
+ // Do simple "peephole" optimizations and bit-twiddling optzns.
+ functionPassManager.add(llvm::createInstructionCombiningPass());
+ // Reassociate expressions.
+ functionPassManager.add(llvm::createReassociatePass());
+ // Eliminate Common SubExpressions.
+ functionPassManager.add(llvm::createGVNPass());
+ // Simplify the control flow graph (deleting unreachable blocks, etc).
+ functionPassManager.add(llvm::createCFGSimplificationPass());
+
+ functionPassManager.doInitialization();
+
+ llvmIsel.buildLLVMModule(module, llvmModule, &functionPassManager);
// TODO: if output type is .ll, print the module to file
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");
+ if (outputType == LLVMOutputObject) {
+ ft = llvm::TargetMachine::CGFT_ObjectFile;
+ ofName = fileName + QLatin1String(".o");
+ } else if (outputType == LLVMOutputAssembler) {
+ ft = llvm::TargetMachine::CGFT_AssemblyFile;
+ ofName = fileName + QLatin1String(".s");
+ } else {
+ // ft is not used.
+ ofName = fileName + QLatin1String(".ll");
+ }
llvm::raw_fd_ostream dest(ofName.toUtf8().constData(), err, llvm::raw_fd_ostream::F_Binary);
llvm::formatted_raw_ostream destf(dest);
delete llvmModule;
}
- llvm::PassManager PM;
- 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);
+ llvm::PassManager globalPassManager;
+ globalPassManager.add(llvm::createScalarReplAggregatesPass());
+ globalPassManager.add(llvm::createInstructionCombiningPass());
+ globalPassManager.add(llvm::createGlobalOptimizerPass());
+ globalPassManager.add(llvm::createFunctionInliningPass(25));
+// globalPassManager.add(llvm::createFunctionInliningPass(125));
+
+ if (outputType == LLVMOutputObject || outputType == LLVMOutputAssembler) {
+ if (targetMachine->addPassesToEmitFile(globalPassManager, destf, ft)) {
+ std::cerr << err << " (probably no DataLayout in TargetMachine)" << std::endl;
+ } else {
+ globalPassManager.run(*llvmModule);
+
+ destf.flush();
+ dest.flush();
+ }
+ } else { // .ll
+ globalPassManager.run(*llvmModule);
+ llvmModule->print(destf, 0);
destf.flush();
dest.flush();
foreach (IR::Function *function, module->functions)
(void) compileLLVMFunction(function);
+ qSwap(_fpm, fpm);
qSwap(_llvmModule, llvmModule);
}