diff options
Diffstat (limited to 'tools')
-rw-r--r-- | tools/fdegen/fdegen.pro | 8 | ||||
-rw-r--r-- | tools/fdegen/main.cpp | 372 | ||||
-rw-r--r-- | tools/v4/main.cpp | 402 | ||||
-rw-r--r-- | tools/v4/v4.pro | 10 |
4 files changed, 792 insertions, 0 deletions
diff --git a/tools/fdegen/fdegen.pro b/tools/fdegen/fdegen.pro new file mode 100644 index 0000000000..a52533280e --- /dev/null +++ b/tools/fdegen/fdegen.pro @@ -0,0 +1,8 @@ +TEMPLATE = app +TARGET = fdegen +INCLUDEPATH += . + +# Input +SOURCES += main.cpp + +LIBS += -ldwarf -lelf diff --git a/tools/fdegen/main.cpp b/tools/fdegen/main.cpp new file mode 100644 index 0000000000..313be40351 --- /dev/null +++ b/tools/fdegen/main.cpp @@ -0,0 +1,372 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the V4VM module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** 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. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <libdwarf.h> +#include <dwarf.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <unistd.h> + +#define DEBUG + +#ifdef DEBUG +#include <libelf.h> +#endif + +#include <qglobal.h> + +enum DwarfRegs { +#if defined(Q_PROCESSOR_X86_64) + // X86-64 + RAX = 0, + RDX = 1, + RCX = 2, + RBX = 3, + RSI = 4, + RDI = 5, + RBP = 6, + RSP = 7, + R8 = 8, + R9 = 9, + R10 = 10, + R11 = 11, + R12 = 12, + R13 = 13, + R14 = 14, + R15 = 15, + RIP = 16, + + InstructionPointerRegister = RIP, + StackPointerRegister = RSP, + StackFrameRegister = RBP +#elif defined(Q_PROCESSOR_X86) + // x86 + EAX = 0, + EDX = 1, + ECX = 2, + EBX = 3, + ESI = 4, + EDI = 5, + EBP = 6, + ESP = 7, + EIP = 8, + + InstructionPointerRegister = EIP, + StackPointerRegister = ESP, + StackFrameRegister = EBP +#else +#error Not ported yet +#endif +}; + +static const DwarfRegs calleeSavedRegisters[] = { +#if defined(Q_PROCESSOR_X86_64) + R12, + R14 +#endif +}; +static const int calleeSavedRegisterCount = sizeof(calleeSavedRegisters) / sizeof(calleeSavedRegisters[0]); + +#if QT_POINTER_SIZE == 8 +#define Elf_Ehdr Elf64_Ehdr +#define elf_newehdr elf64_newehdr +#define Elf_Shdr Elf64_Shdr +#define elf_getshdr elf64_getshdr +#else +#define Elf_Ehdr Elf32_Ehdr +#define elf_newehdr elf32_newehdr +#define Elf_Shdr Elf32_Shdr +#define elf_getshdr elf32_getshdr +#endif + +static void die(const char *msg) +{ + fprintf(stderr, "error: %s\n", msg); + exit(1); +} + +static int createSectionCallback( + char *name, + int size, + Dwarf_Unsigned /*type*/, + Dwarf_Unsigned /*flags*/, + Dwarf_Unsigned /*link*/, + Dwarf_Unsigned /*info*/, + Dwarf_Unsigned* /*sect_name_index*/, + void * /*user_data*/, + int* /*error*/) +{ + if (strcmp(name, ".debug_frame")) + return 0; + fprintf(stderr, "createsection called with %s and size %d\n", name, size); + return 1; +} + +static unsigned char cie_init_instructions[] = { + DW_CFA_def_cfa, StackPointerRegister, /*offset in bytes */QT_POINTER_SIZE, + DW_CFA_offset | InstructionPointerRegister, 1, +}; + +int main() +{ + Dwarf_Error error = 0; + Dwarf_P_Debug dw = dwarf_producer_init_c(DW_DLC_WRITE | DW_DLC_SIZE_64, + createSectionCallback, + /* error handler */0, + /* error arg */0, + /* user data */0, + &error); + if (error != 0) + die("dwarf_producer_init_c failed"); + + Dwarf_Unsigned cie = dwarf_add_frame_cie(dw, + "", + /* code alignment factor */QT_POINTER_SIZE, + /* data alignment factor */-QT_POINTER_SIZE, + /* return address reg*/InstructionPointerRegister, + cie_init_instructions, + sizeof(cie_init_instructions), + &error); + if (error != 0) + die("dwarf_add_frame_cie failed"); + + Dwarf_P_Fde fde = dwarf_new_fde(dw, &error); + if (error != 0) + die("dwarf_new_fde failed"); + + /* New entry in state machine for code offset 1 after push rbp instruction */ + dwarf_add_fde_inst(fde, + DW_CFA_advance_loc, + /*offset in code alignment units*/ 1, + /* unused*/ 0, + &error); + + /* After "push rbp" the offset to the CFA is now 2 instead of 1 */ + dwarf_add_fde_inst(fde, + DW_CFA_def_cfa_offset_sf, + /*offset in code alignment units*/ -2, + /* unused*/ 0, + &error); + + /* After "push rbp" the value of rbp is now stored at offset 1 from CFA */ + dwarf_add_fde_inst(fde, + DW_CFA_offset, + StackFrameRegister, + 2, + &error); + + /* New entry in state machine for code offset 3 for mov rbp, rsp instruction */ + dwarf_add_fde_inst(fde, + DW_CFA_advance_loc, + /*offset in code alignment units*/ 3, + /* unused */ 0, + &error); + + /* After "mov rbp, rsp" the cfa is reachable via rbp */ + dwarf_add_fde_inst(fde, + DW_CFA_def_cfa_register, + StackFrameRegister, + /* unused */0, + &error); + + /* Callee saved registers */ + for (int i = 0; i < calleeSavedRegisterCount; ++i) { + dwarf_add_fde_inst(fde, + DW_CFA_offset, + calleeSavedRegisters[i], + i + 3, + &error); + } + + dwarf_add_frame_fde(dw, fde, + /* die */0, + cie, + /*virt addr */0, + /* length of code */0, + /* symbol index */0, + &error); + if (error != 0) + die("dwarf_add_frame_fde failed"); + + dwarf_transform_to_disk_form(dw, &error); + if (error != 0) + die("dwarf_transform_to_disk_form failed"); + + Dwarf_Unsigned len = 0; + Dwarf_Signed elfIdx = 0; + unsigned char *bytes = (unsigned char *)dwarf_get_section_bytes(dw, /* section */1, + &elfIdx, &len, &error); + if (error != 0) + die("dwarf_get_section_bytes failed"); + + // libdwarf doesn't add a terminating FDE with zero length, so let's add one + // ourselves. + unsigned char *newBytes = (unsigned char *)alloca(len + 4); + memcpy(newBytes, bytes, len); + newBytes[len] = 0; + newBytes[len + 1] = 0; + newBytes[len + 2] = 0; + newBytes[len + 3] = 0; + newBytes[len + 4] = 0; + bytes = newBytes; + len += 4; + + // Reset CIE-ID back to 0 as expected for .eh_frames + bytes[4] = 0; + bytes[5] = 0; + bytes[6] = 0; + bytes[7] = 0; + + unsigned fde_offset = bytes[0] + 4; + + bytes[fde_offset + 4] = fde_offset + 4; + + printf("static const unsigned char cie_fde_data[] = {\n"); + int i = 0; + while (i < len) { + printf(" "); + for (int j = 0; i < len && j < 8; ++j, ++i) + printf("0x%x, ", bytes[i]); + printf("\n"); + } + printf("};\n"); + + printf("static const int fde_offset = %d;\n", fde_offset); + printf("static const int initial_location_offset = %d;\n", fde_offset + 8); + printf("static const int address_range_offset = %d;\n", fde_offset + 8 + QT_POINTER_SIZE); + +#ifdef DEBUG + { + if (elf_version(EV_CURRENT) == EV_NONE) + die("wrong elf version"); + int fd = open("debug.o", O_WRONLY | O_CREAT, 0777); + if (fd < 0) + die("cannot create debug.o"); + + Elf *e = elf_begin(fd, ELF_C_WRITE, 0); + if (!e) + die("elf_begin failed"); + + Elf_Ehdr *ehdr = elf_newehdr(e); + if (!ehdr) + die(elf_errmsg(-1)); + + ehdr->e_ident[EI_DATA] = ELFDATA2LSB; +#if defined(Q_PROCESSOR_X86_64) + ehdr->e_machine = EM_X86_64; +#elif defined(Q_PROCESSOR_X86) + ehdr->e_machine = EM_386; +#else +#error port me :) +#endif + ehdr->e_type = ET_EXEC; + ehdr->e_version = EV_CURRENT; + + Elf_Scn *section = elf_newscn(e); + if (!section) + die("elf_newscn failed"); + + Elf_Data *data = elf_newdata(section); + if (!data) + die(elf_errmsg(-1)); + data->d_align = 4; + data->d_off = 0; + data->d_buf = bytes; + data->d_size = len; + data->d_type = ELF_T_BYTE; + data->d_version = EV_CURRENT; + + Elf_Shdr *shdr = elf_getshdr(section); + if (!shdr) + die(elf_errmsg(-1)); + + shdr->sh_name = 1; + shdr->sh_type = SHT_PROGBITS; + shdr->sh_entsize = 0; + + char stringTable[] = { + 0, + '.', 'e', 'h', '_', 'f', 'r', 'a', 'm', 'e', 0, + '.', 's', 'h', 's', 't', 'r', 't', 'a', 'b', 0 + }; + + section = elf_newscn(e); + if (!section) + die("elf_newscn failed"); + + data = elf_newdata(section); + if (!data) + die(elf_errmsg(-1)); + data->d_align = 1; + data->d_off = 0; + data->d_buf = stringTable; + data->d_size = sizeof(stringTable); + data->d_type = ELF_T_BYTE; + data->d_version = EV_CURRENT; + + shdr = elf_getshdr(section); + if (!shdr) + die(elf_errmsg(-1)); + + shdr->sh_name = 11; + shdr->sh_type = SHT_STRTAB; + shdr->sh_flags = SHF_STRINGS | SHF_ALLOC; + shdr->sh_entsize = 0; + + ehdr->e_shstrndx = elf_ndxscn(section); + + if (elf_update(e, ELF_C_WRITE) < 0) + die(elf_errmsg(-1)); + + elf_end(e); + close(fd); + } +#endif + + dwarf_producer_finish(dw, &error); + if (error != 0) + die("dwarf_producer_finish failed"); + return 0; +} diff --git a/tools/v4/main.cpp b/tools/v4/main.cpp new file mode 100644 index 0000000000..e61931cea4 --- /dev/null +++ b/tools/v4/main.cpp @@ -0,0 +1,402 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the V4VM module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** 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. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifdef QMLJS_WITH_LLVM +# include "private/qv4_llvm_p.h" +#endif // QMLJS_WITH_LLVM + +#include "private/debugging.h" +#include "private/qv4object.h" +#include "private/qv4runtime.h" +#include "private/qv4functionobject.h" +#include "private/qv4errorobject.h" +#include "private/qv4globalobject.h" +#include "private/qv4codegen_p.h" +#include "private/qv4isel_masm_p.h" +#include "private/qv4isel_moth_p.h" +#include "private/qv4vme_moth_p.h" +#include "private/qv4syntaxchecker_p.h" +#include "private/qv4objectproto.h" +#include "private/qv4isel_p.h" +#include "private/qv4mm.h" +#include "private/qv4context.h" + +#include <QtCore> +#include <private/qqmljsengine_p.h> +#include <private/qqmljslexer_p.h> +#include <private/qqmljsparser_p.h> +#include <private/qqmljsast_p.h> + +#include <iostream> + +namespace builtins { + +using namespace QQmlJS::VM; + +struct Print: FunctionObject +{ + Print(ExecutionContext *scope): FunctionObject(scope) { + vtbl = &static_vtbl; + name = scope->engine->newString("print"); + } + + static Value call(Managed *, ExecutionContext *ctx, const Value &, Value *args, int argc) + { + for (int i = 0; i < argc; ++i) { + String *s = args[i].toString(ctx); + if (i) + std::cout << ' '; + std::cout << qPrintable(s->toQString()); + } + std::cout << std::endl; + return Value::undefinedValue(); + } + + static const ManagedVTable static_vtbl; +}; + +DEFINE_MANAGED_VTABLE(Print); + +struct GC: public FunctionObject +{ + GC(ExecutionContext* scope) + : FunctionObject(scope) + { + vtbl = &static_vtbl; + name = scope->engine->newString("gc"); + } + static Value call(Managed *, ExecutionContext *ctx, const Value &, Value *, int) + { + ctx->engine->memoryManager->runGC(); + return Value::undefinedValue(); + } + + static const ManagedVTable static_vtbl; +}; + +DEFINE_MANAGED_VTABLE(GC); + +} // builtins + +static void showException(QQmlJS::VM::ExecutionContext *ctx, const QQmlJS::VM::Value &exception) +{ + QQmlJS::VM::ErrorObject *e = exception.asErrorObject(); + if (!e) { + std::cerr << "Uncaught exception: " << qPrintable(exception.toString(ctx)->toQString()) << std::endl; + return; + } + + if (QQmlJS::VM::SyntaxErrorObject *err = e->asSyntaxError()) { + QQmlJS::VM::DiagnosticMessage *msg = err->message(); + if (!msg) { + std::cerr << "Uncaught exception: Syntax error" << std::endl; + return; + } + + for (; msg; msg = msg->next) { + std::cerr << qPrintable(msg->buildFullMessage(ctx)->toQString()) << std::endl; + } + } else { + std::cerr << "Uncaught exception: " << qPrintable(e->get(ctx, ctx->engine->newString(QStringLiteral("message")), 0).toString(ctx)->toQString()) << std::endl; + } +} + +#ifdef QMLJS_WITH_LLVM +int executeLLVMCode(void *codePtr) +{ + using namespace QQmlJS; + + if (!codePtr) + return EXIT_FAILURE; + void (*code)(VM::ExecutionContext *) = (void (*)(VM::ExecutionContext *)) codePtr; + + QScopedPointer<QQmlJS::EvalISelFactory> iSelFactory(new QQmlJS::Moth::ISelFactory); + VM::ExecutionEngine vm(iSelFactory.data()); + VM::ExecutionContext *ctx = vm.rootContext; + +#if THIS_NEEDS_TO_BE_FIXED + QQmlJS::VM::Object *globalObject = vm.globalObject.objectValue(); + globalObject->__put__(ctx, vm.newIdentifier(QStringLiteral("print")), + QQmlJS::VM::Value::fromObject(new (ctx->engine->memoryManager) builtins::Print(ctx))); + + void * buf = __qmljs_create_exception_handler(ctx); + if (setjmp(*(jmp_buf *)buf)) { + showException(ctx); + return EXIT_FAILURE; + } + + code(ctx); +#else + Q_UNUSED(ctx); + Q_UNUSED(code); +#endif + return EXIT_SUCCESS; +} + +int compile(const QString &fileName, const QString &source, QQmlJS::LLVMOutputType outputType) +{ + using namespace QQmlJS; + + IR::Module module; + QQmlJS::Engine ee, *engine = ⅇ + Lexer lexer(engine); + lexer.setCode(source, 1, false); + Parser parser(engine); + + const bool parsed = parser.parseProgram(); + + foreach (const DiagnosticMessage &m, parser.diagnosticMessages()) { + std::cerr << qPrintable(fileName) << ':' + << m.loc.startLine << ':' + << m.loc.startColumn << ": error: " + << qPrintable(m.message) << std::endl; + } + + if (!parsed) + return EXIT_FAILURE; + + using namespace AST; + Program *program = AST::cast<Program *>(parser.rootNode()); + + class MyErrorHandler: public ErrorHandler { + public: + virtual void syntaxError(QQmlJS::VM::DiagnosticMessage *message) { + for (; message; message = message->next) { + std::cerr << qPrintable(message->fileName) << ':' + << message->startLine << ':' + << message->startColumn << ": " + << (message->type == QQmlJS::VM::DiagnosticMessage::Error ? "error" : "warning") << ": " + << qPrintable(message->message) << std::endl; + } + } + } errorHandler; + + Codegen cg(&errorHandler, false); + // FIXME: if the program is empty, we should we generate an empty %entry, or give an error? + /*IR::Function *globalCode =*/ cg(fileName, source, program, &module); + + int (*exec)(void *) = outputType == LLVMOutputJit ? executeLLVMCode : 0; + return compileWithLLVM(&module, fileName, outputType, exec); +} + +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, outputType); + if (result != EXIT_SUCCESS) + return result; + } else { + std::cerr << "Error: cannot open file " << fileName.toUtf8().constData() << std::endl; + return EXIT_FAILURE; + } + } + return EXIT_SUCCESS; +} + +int evaluateCompiledCode(const QStringList &files) +{ + using namespace QQmlJS; + + foreach (const QString &libName, files) { + QFileInfo libInfo(libName); + QLibrary lib(libInfo.absoluteFilePath()); + lib.load(); + QFunctionPointer ptr = lib.resolve("%entry"); +// qDebug("_%%entry resolved to address %p", ptr); + int result = executeLLVMCode((void *) ptr); + if (result != EXIT_SUCCESS) + return result; + } + + return EXIT_SUCCESS; +} +#endif // QMLJS_WITH_LLVM + + +int main(int argc, char *argv[]) +{ + QCoreApplication app(argc, argv); + QStringList args = app.arguments(); + args.removeFirst(); + + enum { + use_masm, + use_moth, + use_llvm_compiler, + use_llvm_runtime, + use_llvm_jit + } mode = use_masm; + +#ifdef QMLJS_WITH_LLVM + QQmlJS::LLVMOutputType fileType = QQmlJS::LLVMOutputObject; +#endif // QMLJS_WITH_LLVM + bool enableDebugging = false; + + if (!args.isEmpty()) { + if (args.first() == QLatin1String("-d") || args.first() == QLatin1String("--debug")) { + enableDebugging = true; + args.removeFirst(); + } + } + + if (!args.isEmpty()) { + if (args.first() == QLatin1String("--jit")) { + mode = use_masm; + args.removeFirst(); + } + + if (args.first() == QLatin1String("--interpret")) { + mode = use_moth; + args.removeFirst(); + } + +#ifdef QMLJS_WITH_LLVM + 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")) { + mode = use_llvm_runtime; + args.removeFirst(); + } + + if (args.first() == QLatin1String("--llvm-jit")) { + mode = use_llvm_jit; + args.removeFirst(); + } +#endif // QMLJS_WITH_LLVM + if (args.first() == QLatin1String("--help")) { + std::cerr << "Usage: v4 [|--debug|-d] [|--jit|--interpret|--compile|--aot|--llvm-jit] file..." << std::endl; + return EXIT_SUCCESS; + } + } + + switch (mode) { +#ifdef QMLJS_WITH_LLVM + case use_llvm_jit: + return compileFiles(args, QQmlJS::LLVMOutputJit); + case use_llvm_compiler: + return compileFiles(args, fileType); + case use_llvm_runtime: + return evaluateCompiledCode(args); +#else // !QMLJS_WITH_LLVM + case use_llvm_compiler: + case use_llvm_runtime: + case use_llvm_jit: + std::cerr << "LLVM backend was not built, compiler is unavailable." << std::endl; + return EXIT_FAILURE; +#endif // QMLJS_WITH_LLVM + case use_masm: + case use_moth: { + QQmlJS::EvalISelFactory* iSelFactory = 0; + if (mode == use_moth) { + iSelFactory = new QQmlJS::Moth::ISelFactory; + } else { + iSelFactory = new QQmlJS::MASM::ISelFactory; + } + + QQmlJS::VM::ExecutionEngine vm(iSelFactory); + + QScopedPointer<QQmlJS::Debugging::Debugger> debugger; + if (enableDebugging) + debugger.reset(new QQmlJS::Debugging::Debugger(&vm)); + vm.debugger = debugger.data(); + + QQmlJS::VM::ExecutionContext *ctx = vm.rootContext; + + QQmlJS::VM::Object *globalObject = vm.globalObject; + QQmlJS::VM::Object *print = new (ctx->engine->memoryManager) builtins::Print(ctx); + print->prototype = ctx->engine->objectPrototype; + globalObject->put(ctx, vm.newIdentifier(QStringLiteral("print")), + QQmlJS::VM::Value::fromObject(print)); + QQmlJS::VM::Object *gc = new (ctx->engine->memoryManager) builtins::GC(ctx); + gc->prototype = ctx->engine->objectPrototype; + globalObject->put(ctx, vm.newIdentifier(QStringLiteral("gc")), + QQmlJS::VM::Value::fromObject(gc)); + + foreach (const QString &fn, args) { + QFile file(fn); + if (file.open(QFile::ReadOnly)) { + const QString code = QString::fromUtf8(file.readAll()); + file.close(); + + try { + QQmlJS::VM::Function *f = QQmlJS::VM::EvalFunction::parseSource(ctx, fn, code, QQmlJS::Codegen::GlobalCode, + /*strictMode =*/ false, /*inheritContext =*/ false); + if (!f) + continue; + QQmlJS::VM::Value result = vm.run(f); + if (!result.isUndefined()) { + if (! qgetenv("SHOW_EXIT_VALUE").isEmpty()) + std::cout << "exit value: " << qPrintable(result.toString(ctx)->toQString()) << std::endl; + } + } catch (QQmlJS::VM::Exception& ex) { + ex.accept(ctx); + showException(ctx, ex.value()); + return EXIT_FAILURE; + } + + } else { + std::cerr << "Error: cannot open file " << fn.toUtf8().constData() << std::endl; + return EXIT_FAILURE; + } + } + + vm.memoryManager->dumpStats(); + } return EXIT_SUCCESS; + } // switch (mode) +} diff --git a/tools/v4/v4.pro b/tools/v4/v4.pro new file mode 100644 index 0000000000..fcf1b28582 --- /dev/null +++ b/tools/v4/v4.pro @@ -0,0 +1,10 @@ +TEMPLATE = app +QT = v4-private core-private qmldevtools-private +SOURCES = main.cpp + +include(../../src/v4/v4.pri) + +llvm-libs { + DEFINES += QMLJS_WITH_LLVM +} +load(qt_tool) |