aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--debugging.cpp183
-rw-r--r--debugging.h137
-rw-r--r--main.cpp26
-rw-r--r--moth/qv4isel_moth.cpp4
-rw-r--r--moth/qv4vme_moth.cpp20
-rw-r--r--qmljs_engine.cpp1
-rw-r--r--qmljs_engine.h8
-rw-r--r--qmljs_environment.cpp8
-rw-r--r--qmljs_objects.cpp3
-rw-r--r--qmljs_objects.h4
-rw-r--r--qmljs_runtime.cpp4
-rw-r--r--qv4codegen.cpp18
-rw-r--r--qv4codegen_p.h7
-rw-r--r--qv4ecmaobjects.cpp2
-rw-r--r--qv4isel_llvm.cpp1
-rw-r--r--v4.pro6
16 files changed, 421 insertions, 11 deletions
diff --git a/debugging.cpp b/debugging.cpp
new file mode 100644
index 0000000000..741d5daee4
--- /dev/null
+++ b/debugging.cpp
@@ -0,0 +1,183 @@
+/****************************************************************************
+**
+** 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.
+**
+****************************************************************************/
+
+#include "debugging.h"
+#include "qmljs_objects.h"
+
+#include <iostream>
+
+using namespace QQmlJS;
+using namespace QQmlJS::Debugging;
+
+FunctionState::FunctionState(VM::ExecutionContext *context)
+ : _context(context)
+{
+ if (debugger())
+ debugger()->enterFunction(this);
+}
+
+FunctionState::~FunctionState()
+{
+ if (debugger())
+ debugger()->leaveFunction(this);
+}
+
+VM::Value *FunctionState::argument(unsigned idx)
+{
+ if (idx < _context->variableEnvironment->argumentCount)
+ return _context->variableEnvironment->arguments + idx;
+ else
+ return 0;
+}
+
+VM::Value *FunctionState::local(unsigned idx)
+{
+ if (idx < _context->variableEnvironment->varCount)
+ return _context->variableEnvironment->locals + idx;
+ else
+ return 0;
+}
+
+Debugger::Debugger(VM::ExecutionEngine *engine)
+ : _engine(engine)
+{
+}
+
+Debugger::~Debugger()
+{
+ qDeleteAll(_functionInfo.values());
+}
+
+void Debugger::addFunction(IR::Function *function)
+{
+ _functionInfo.insert(function, new FunctionDebugInfo(function));
+}
+
+void Debugger::addaddBasicBlockOffset(IR::Function *function, IR::BasicBlock *block, ptrdiff_t blockOffset)
+{
+ _functionInfo[function]->addBasicBlockOffset(block, blockOffset);
+}
+
+void Debugger::setSourceLocation(IR::Function *function, unsigned line, unsigned column)
+{
+ _functionInfo[function]->setSourceLocation(line, column);
+}
+
+FunctionDebugInfo *Debugger::debugInfo(VM::FunctionObject *function) const
+{
+ if (!function)
+ return 0;
+
+ if (VM::ScriptFunction *sf = function->asScriptFunction())
+ return _functionInfo[sf->function];
+ else
+ return 0;
+}
+
+QString Debugger::name(VM::FunctionObject *function) const
+{
+ if (FunctionDebugInfo *i = debugInfo(function))
+ if (i->function)
+ if (const QString *n = i->function->name)
+ return *n;
+
+ return QString();
+}
+
+void Debugger::aboutToCall(VM::FunctionObject *function, VM::ExecutionContext *context)
+{
+ _callStack.append(CallInfo(context, function));
+}
+
+void Debugger::justLeft(VM::ExecutionContext *context)
+{
+ int idx = callIndex(context);
+ if (idx < 0)
+ qDebug() << "Oops, leaving a function that was not registered...?";
+ else
+ _callStack.resize(idx);
+}
+
+void Debugger::enterFunction(FunctionState *state)
+{
+ _callStack[callIndex(state->context())].state = state;
+
+#ifdef DO_TRACE_INSTR
+ QString n = name(_callStack[callIndex(state->context())].function);
+ std::cerr << "*** Entering \"" << qPrintable(n) << "\" with" << state->context()->variableEnvironment->argumentCount << "args" << std::endl;
+ for (unsigned i = 0; i < state->context()->variableEnvironment->argumentCount; ++i)
+ std::cerr << " " << i << ": " << currentArg(i) << std::endl;
+#endif // DO_TRACE_INSTR
+}
+
+void Debugger::leaveFunction(FunctionState *state)
+{
+ _callStack[callIndex(state->context())].state = 0;
+}
+
+void Debugger::aboutToThrow(VM::Value *value)
+{
+ qDebug() << "*** We are about to throw...:" << value->toString(currentState()->context())->toQString();
+}
+
+FunctionState *Debugger::currentState() const
+{
+ if (_callStack.isEmpty())
+ return 0;
+ else
+ return _callStack.last().state;
+}
+
+const char *Debugger::currentArg(unsigned idx) const
+{
+ FunctionState *state = currentState();
+ return qPrintable(state->argument(idx)->toString(state->context())->toQString());
+}
+
+const char *Debugger::currentLocal(unsigned idx) const
+{
+ FunctionState *state = currentState();
+ return qPrintable(state->local(idx)->toString(state->context())->toQString());
+}
+
+const char *Debugger::currentTemp(unsigned idx) const
+{
+ FunctionState *state = currentState();
+ return qPrintable(state->temp(idx)->toString(state->context())->toQString());
+}
+
+int Debugger::callIndex(VM::ExecutionContext *context)
+{
+ for (int idx = _callStack.size() - 1; idx >= 0; --idx) {
+ if (_callStack[idx].context == context)
+ return idx;
+ }
+
+ return -1;
+}
diff --git a/debugging.h b/debugging.h
new file mode 100644
index 0000000000..7a0a27dfdb
--- /dev/null
+++ b/debugging.h
@@ -0,0 +1,137 @@
+/****************************************************************************
+**
+** 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 DEBUGGING_H
+#define DEBUGGING_H
+
+#include "qmljs_engine.h"
+#include "qmljs_environment.h"
+
+#include <QHash>
+
+namespace QQmlJS {
+
+namespace IR {
+struct BasicBlock;
+struct Function;
+} // namespace IR
+
+namespace Debugging {
+
+class Debugger;
+
+struct FunctionDebugInfo { // TODO: use opaque d-pointers here
+ IR::Function *function;
+ QHash<ptrdiff_t, IR::BasicBlock *> blockOffsets;
+ unsigned startLine, startColumn;
+
+ FunctionDebugInfo(IR::Function *function): function(function), startLine(0), startColumn(0) {}
+
+ void addBasicBlockOffset(IR::BasicBlock *block, ptrdiff_t offset) {
+ blockOffsets.insert(offset, block);
+ }
+
+ void setSourceLocation(unsigned line, unsigned column)
+ { startLine = line; startColumn = column; }
+};
+
+class FunctionState
+{
+public:
+ FunctionState(VM::ExecutionContext *context);
+ virtual ~FunctionState();
+
+ virtual VM::Value *argument(unsigned idx);
+ virtual VM::Value *local(unsigned idx);
+ virtual VM::Value *temp(unsigned idx) = 0;
+
+ VM::ExecutionContext *context() const
+ { return _context; }
+
+ Debugger *debugger() const
+ { return _context->engine->debugger; }
+
+private:
+ VM::ExecutionContext *_context;
+};
+
+struct CallInfo
+{
+ VM::ExecutionContext *context;
+ VM::FunctionObject *function;
+ FunctionState *state;
+
+ CallInfo(VM::ExecutionContext *context = 0, VM::FunctionObject *function = 0, FunctionState *state = 0)
+ : context(context)
+ , function(function)
+ , state(state)
+ {}
+};
+
+class Debugger
+{
+public:
+ Debugger(VM::ExecutionEngine *_engine);
+ ~Debugger();
+
+public: // compile-time interface
+ void addFunction(IR::Function *function);
+ void addaddBasicBlockOffset(IR::Function *function, IR::BasicBlock *block, ptrdiff_t blockOffset);
+ void setSourceLocation(IR::Function *function, unsigned line, unsigned column);
+
+public: // run-time querying interface
+ FunctionDebugInfo *debugInfo(VM::FunctionObject *function) const;
+ QString name(VM::FunctionObject *function) const;
+
+public: // execution hooks
+ void aboutToCall(VM::FunctionObject *function, VM::ExecutionContext *context);
+ void justLeft(VM::ExecutionContext *context);
+ void enterFunction(FunctionState *state);
+ void leaveFunction(FunctionState *state);
+ void aboutToThrow(VM::Value *value);
+
+public: // debugging hooks
+ FunctionState *currentState() const;
+ const char *currentArg(unsigned idx) const;
+ const char *currentLocal(unsigned idx) const;
+ const char *currentTemp(unsigned idx) const;
+
+private:
+ int callIndex(VM::ExecutionContext *context);
+
+private: // TODO: use opaque d-pointers here
+ VM::ExecutionEngine *_engine;
+ QHash<IR::Function *, FunctionDebugInfo *> _functionInfo;
+ QVector<CallInfo> _callStack;
+};
+
+} // namespace Debugging
+} // namespace QQmlJS
+
+#endif // DEBUGGING_H
diff --git a/main.cpp b/main.cpp
index dccac7edce..8418dc16fd 100644
--- a/main.cpp
+++ b/main.cpp
@@ -43,6 +43,7 @@
# include "qv4_llvm_p.h"
#endif
+#include "debugging.h"
#include "qmljs_objects.h"
#include "qmljs_runtime.h"
#include "qv4codegen_p.h"
@@ -183,7 +184,7 @@ int compile(const QString &fileName, const QString &source, QQmlJS::LLVMOutputTy
using namespace AST;
Program *program = AST::cast<Program *>(parser.rootNode());
- Codegen cg;
+ Codegen cg(0);
// FIXME: if the program is empty, we should we generate an empty %entry, or give an error?
/*IR::Function *globalCode =*/ cg(program, &module);
@@ -246,6 +247,14 @@ int main(int argc, char *argv[])
#ifndef QMLJS_NO_LLVM
QQmlJS::LLVMOutputType fileType = QQmlJS::LLVMOutputObject;
#endif // QMLJS_NO_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")) {
@@ -287,7 +296,7 @@ int main(int argc, char *argv[])
}
#endif // QMLJS_NO_LLVM
if (args.first() == QLatin1String("--help")) {
- std::cerr << "Usage: v4 [|--jit|--interpret|--compile|--aot|--llvm-jit] file..." << std::endl;
+ std::cerr << "Usage: v4 [|--debug|-d] [|--jit|--interpret|--compile|--aot|--llvm-jit] file..." << std::endl;
return EXIT_SUCCESS;
}
}
@@ -314,7 +323,14 @@ int main(int argc, char *argv[])
iSelFactory.reset(new QQmlJS::Moth::ISelFactory);
else
iSelFactory.reset(new QQmlJS::MASM::ISelFactory);
+
QQmlJS::VM::ExecutionEngine vm(iSelFactory.data());
+
+ 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.objectValue();
@@ -338,11 +354,15 @@ int main(int argc, char *argv[])
return EXIT_FAILURE;
}
- QQmlJS::IR::Function *f = QQmlJS::VM::EvalFunction::parseSource(vm.rootContext, fn, code, QQmlJS::Codegen::GlobalCode);
+ QQmlJS::IR::Function *f = QQmlJS::VM::EvalFunction::parseSource(ctx, fn, code, QQmlJS::Codegen::GlobalCode);
if (!f)
continue;
ctx->lexicalEnvironment->strictMode = f->isStrict;
+ if (debugger)
+ debugger->aboutToCall(0, ctx);
QQmlJS::VM::Value result = f->code(ctx, f->codeData);
+ if (debugger)
+ debugger->justLeft(ctx);
if (!result.isUndefined()) {
if (! qgetenv("SHOW_EXIT_VALUE").isEmpty())
std::cout << "exit value: " << qPrintable(result.toString(ctx)->toQString()) << std::endl;
diff --git a/moth/qv4isel_moth.cpp b/moth/qv4isel_moth.cpp
index 94a06d393b..482d0633b0 100644
--- a/moth/qv4isel_moth.cpp
+++ b/moth/qv4isel_moth.cpp
@@ -1,6 +1,7 @@
#include "qv4isel_util_p.h"
#include "qv4isel_moth_p.h"
#include "qv4vme_moth_p.h"
+#include "debugging.h"
using namespace QQmlJS;
using namespace QQmlJS::Moth;
@@ -209,7 +210,10 @@ void InstructionSelection::operator()(IR::Function *function)
addInstruction(push);
foreach (_block, _function->basicBlocks) {
+ ptrdiff_t blockOffset = _ccode - _code;
_addrs.insert(_block, _ccode - _code);
+ if (_engine->debugger)
+ _engine->debugger->addaddBasicBlockOffset(_function, _block, blockOffset);
foreach (IR::Stmt *s, _block->statements)
s->accept(this);
diff --git a/moth/qv4vme_moth.cpp b/moth/qv4vme_moth.cpp
index 87d50a36d0..92e7c7c206 100644
--- a/moth/qv4vme_moth.cpp
+++ b/moth/qv4vme_moth.cpp
@@ -1,6 +1,9 @@
#include "qv4vme_moth_p.h"
#include "qv4instr_moth_p.h"
#include "qmljs_value.h"
+#include "debugging.h"
+
+#include <iostream>
#ifdef DO_TRACE_INSTR
# define TRACE_INSTR(I) fprintf(stderr, "executing a %s\n", #I);
@@ -92,6 +95,22 @@ static inline VM::Value *tempValue(QQmlJS::VM::ExecutionContext *context, QVecto
}
}
+class FunctionState: public Debugging::FunctionState
+{
+public:
+ FunctionState(QQmlJS::VM::ExecutionContext *context, QVector<VM::Value> *stack, const uchar **code)
+ : Debugging::FunctionState(context)
+ , stack(stack)
+ , code(code)
+ {}
+
+ virtual VM::Value *temp(unsigned idx) { return stack->data() + idx; }
+
+private:
+ QVector<VM::Value> *stack;
+ const uchar **code;
+};
+
#define TEMP(index) *tempValue(context, stack, index)
VM::Value VME::operator()(QQmlJS::VM::ExecutionContext *context, const uchar *code
@@ -114,6 +133,7 @@ VM::Value VME::operator()(QQmlJS::VM::ExecutionContext *context, const uchar *co
#endif
QVector<VM::Value> stack;
+ FunctionState state(context, &stack, &code);
#ifdef MOTH_THREADED_INTERPRETER
const Instr *genericInstr = reinterpret_cast<const Instr *>(code);
diff --git a/qmljs_engine.cpp b/qmljs_engine.cpp
index a1b3256fc7..1609559659 100644
--- a/qmljs_engine.cpp
+++ b/qmljs_engine.cpp
@@ -62,6 +62,7 @@ struct StringPool
ExecutionEngine::ExecutionEngine(EvalISelFactory *factory)
: iselFactory(factory)
+ , debugger(0)
{
stringPool = new StringPool;
diff --git a/qmljs_engine.h b/qmljs_engine.h
index dcae173fef..9b91f01c04 100644
--- a/qmljs_engine.h
+++ b/qmljs_engine.h
@@ -47,6 +47,11 @@
#include <setjmp.h>
namespace QQmlJS {
+
+namespace Debugging {
+class Debugger;
+} // namespace Debugging
+
namespace VM {
struct Value;
@@ -87,6 +92,8 @@ struct ExecutionEngine
ExecutionContext *current;
ExecutionContext *rootContext;
+ Debugging::Debugger *debugger;
+
Value globalObject;
Value objectCtor;
@@ -184,7 +191,6 @@ struct ExecutionEngine
Object *newForEachIteratorObject(Object *o);
};
-
} // namespace VM
} // namespace QQmlJS
diff --git a/qmljs_environment.cpp b/qmljs_environment.cpp
index 1b073ef119..e9b55a89f7 100644
--- a/qmljs_environment.cpp
+++ b/qmljs_environment.cpp
@@ -38,6 +38,8 @@
** $QT_END_LICENSE$
**
****************************************************************************/
+
+#include "debugging.h"
#include <qmljs_environment.h>
#include <qmljs_objects.h>
#include <qv4ecmaobjects_p.h>
@@ -315,6 +317,9 @@ void ExecutionContext::initCallContext(ExecutionContext *parent, const Value tha
lexicalEnvironment = variableEnvironment;
thisObject = that;
+
+ if (engine->debugger)
+ engine->debugger->aboutToCall(f, this);
}
void ExecutionContext::leaveCallContext()
@@ -327,6 +332,9 @@ void ExecutionContext::leaveCallContext()
delete variableEnvironment;
variableEnvironment = 0;
+
+ if (engine->debugger)
+ engine->debugger->justLeft(this);
}
void ExecutionContext::initConstructorContext(ExecutionContext *parent, Value that, FunctionObject *f, Value *args, unsigned argc)
diff --git a/qmljs_objects.cpp b/qmljs_objects.cpp
index 28932e371c..302e5749ca 100644
--- a/qmljs_objects.cpp
+++ b/qmljs_objects.cpp
@@ -39,7 +39,6 @@
**
****************************************************************************/
-
#include "qmljs_objects.h"
#include "qv4ir_p.h"
#include "qv4isel_p.h"
@@ -564,7 +563,7 @@ QQmlJS::IR::Function *EvalFunction::parseSource(QQmlJS::VM::ExecutionContext *ct
return 0;
}
- Codegen cg;
+ Codegen cg(ctx->engine->debugger);
globalCode = cg(program, &module, mode);
if (globalCode) {
// only generate other functions if global code generation succeeded.
diff --git a/qmljs_objects.h b/qmljs_objects.h
index 957a562d97..4e0af583d1 100644
--- a/qmljs_objects.h
+++ b/qmljs_objects.h
@@ -516,6 +516,8 @@ struct FunctionObject: Object {
Value construct(ExecutionContext *context, Value *args, int argc);
virtual Value call(ExecutionContext *context, Value thisObject, Value *args, int argc);
+ virtual struct ScriptFunction *asScriptFunction() { return 0; }
+
protected:
virtual Value call(ExecutionContext *ctx);
virtual Value construct(ExecutionContext *ctx);
@@ -537,6 +539,8 @@ struct ScriptFunction: FunctionObject {
virtual Value call(ExecutionContext *ctx);
virtual Value construct(ExecutionContext *ctx);
+
+ virtual ScriptFunction *asScriptFunction() { return this; }
};
struct EvalFunction : FunctionObject
diff --git a/qmljs_runtime.cpp b/qmljs_runtime.cpp
index 1aa3c94f2c..6779f86d11 100644
--- a/qmljs_runtime.cpp
+++ b/qmljs_runtime.cpp
@@ -39,6 +39,7 @@
**
****************************************************************************/
+#include "debugging.h"
#include "qmljs_runtime.h"
#include "qmljs_objects.h"
#include "qv4ir_p.h"
@@ -777,6 +778,9 @@ void __qmljs_throw(Value value, ExecutionContext *context)
{
assert(!context->engine->unwindStack.isEmpty());
+ if (context->engine->debugger)
+ context->engine->debugger->aboutToThrow(&value);
+
ExecutionEngine::ExceptionHandler &handler = context->engine->unwindStack.last();
// clean up call contexts
diff --git a/qv4codegen.cpp b/qv4codegen.cpp
index 0f3cedb55c..1980ed95a4 100644
--- a/qv4codegen.cpp
+++ b/qv4codegen.cpp
@@ -40,6 +40,7 @@
****************************************************************************/
#include "qv4codegen_p.h"
+#include "debugging.h"
#include <QtCore/QStringList>
#include <QtCore/QSet>
@@ -352,7 +353,7 @@ protected:
QStack<Environment *> _envStack;
};
-Codegen::Codegen()
+Codegen::Codegen(Debugging::Debugger *debugger)
: _module(0)
, _function(0)
, _block(0)
@@ -363,6 +364,7 @@ Codegen::Codegen()
, _env(0)
, _loop(0)
, _labelledStatement(0)
+ , _debugger(debugger)
{
}
@@ -377,6 +379,12 @@ IR::Function *Codegen::operator()(Program *node, IR::Module *module, Mode mode)
scan(node);
IR::Function *globalCode = defineFunction(QStringLiteral("%entry"), node, 0, node->elements, mode);
+ if (_debugger) {
+ if (node->elements->element) {
+ SourceLocation loc = node->elements->element->firstSourceLocation();
+ _debugger->setSourceLocation(globalCode, loc.startLine, loc.startColumn);
+ }
+ }
foreach (IR::Function *function, _module->functions) {
linearize(function);
@@ -397,6 +405,8 @@ IR::Function *Codegen::operator()(AST::FunctionExpression *ast, IR::Module *modu
scan(ast);
IR::Function *function = defineFunction(ast->name.toString(), ast, ast->formals, ast->body ? ast->body->elements : 0);
+ if (_debugger)
+ _debugger->setSourceLocation(function, ast->functionToken.startLine, ast->functionToken.startColumn);
foreach (IR::Function *function, _module->functions) {
linearize(function);
@@ -1168,6 +1178,8 @@ bool Codegen::visit(FieldMemberExpression *ast)
bool Codegen::visit(FunctionExpression *ast)
{
IR::Function *function = defineFunction(ast->name.toString(), ast, ast->formals, ast->body ? ast->body->elements : 0);
+ if (_debugger)
+ _debugger->setSourceLocation(function, ast->functionToken.startLine, ast->functionToken.startColumn);
_expr.code = _block->CLOSURE(function);
return false;
}
@@ -1570,6 +1582,8 @@ IR::Function *Codegen::defineFunction(const QString &name, AST::Node *ast,
enterEnvironment(ast);
IR::Function *function = _module->newFunction(name);
+ if (_debugger)
+ _debugger->addFunction(function);
IR::BasicBlock *entryBlock = function->newBasicBlock();
IR::BasicBlock *exitBlock = function->newBasicBlock(IR::Function::DontInsertBlock);
IR::BasicBlock *throwBlock = function->newBasicBlock();
@@ -1626,6 +1640,8 @@ IR::Function *Codegen::defineFunction(const QString &name, AST::Node *ast,
foreach (AST::FunctionDeclaration *f, _env->functions) {
IR::Function *function = defineFunction(f->name.toString(), f, f->formals,
f->body ? f->body->elements : 0);
+ if (_debugger)
+ _debugger->setSourceLocation(function, f->functionToken.startLine, f->functionToken.startColumn);
if (! _env->parent)
move(_block->NAME(f->name.toString(), f->identifierToken.startLine, f->identifierToken.startColumn),
_block->CLOSURE(function));
diff --git a/qv4codegen_p.h b/qv4codegen_p.h
index 4952c690b8..27c910fd8b 100644
--- a/qv4codegen_p.h
+++ b/qv4codegen_p.h
@@ -50,10 +50,14 @@ namespace AST {
class UiParameterList;
}
+namespace Debugging {
+class Debugger;
+} // namespace Debugging
+
class Codegen: protected AST::Visitor
{
public:
- Codegen();
+ Codegen(Debugging::Debugger *debugger);
enum Mode {
GlobalCode,
@@ -330,6 +334,7 @@ private:
AST::LabelledStatement *_labelledStatement;
QHash<AST::Node *, Environment *> _envMap;
QHash<AST::FunctionExpression *, int> _functionMap;
+ Debugging::Debugger *_debugger;
class ScanFunctions;
};
diff --git a/qv4ecmaobjects.cpp b/qv4ecmaobjects.cpp
index 9fd95b94a0..7adb16ed15 100644
--- a/qv4ecmaobjects.cpp
+++ b/qv4ecmaobjects.cpp
@@ -1892,7 +1892,7 @@ Value FunctionCtor::construct(ExecutionContext *ctx)
IR::Module module;
- Codegen cg;
+ Codegen cg(ctx->engine->debugger);
IR::Function *irf = cg(fe, &module);
EvalInstructionSelection *isel = ctx->engine->iselFactory->create(ctx->engine);
diff --git a/qv4isel_llvm.cpp b/qv4isel_llvm.cpp
index 80c55d201a..5ea5df9d58 100644
--- a/qv4isel_llvm.cpp
+++ b/qv4isel_llvm.cpp
@@ -720,6 +720,7 @@ void LLVMInstructionSelection::visitClosure(IR::Closure *e)
{
llvm::Value *tmp = newLLVMTemp(_valueTy);
llvm::Value *clos = getLLVMFunction(e->value);
+ assert("!broken: pass function name!");
CreateCall3(_llvmModule->getFunction("__qmljs_llvm_init_native_function"),
_llvmFunction->arg_begin(), tmp, clos);
_llvmValue = CreateLoad(tmp);
diff --git a/v4.pro b/v4.pro
index 1a6e2a41ab..24ab7c0d0e 100644
--- a/v4.pro
+++ b/v4.pro
@@ -23,7 +23,8 @@ SOURCES += main.cpp \
qv4array.cpp \
qv4isel_masm.cpp \
llvm_runtime.cpp \
- qv4isel_p.cpp
+ qv4isel_p.cpp \
+ debugging.cpp
HEADERS += \
qv4codegen_p.h \
@@ -39,7 +40,8 @@ HEADERS += \
qv4array_p.h \
qv4isel_masm_p.h \
qv4isel_p.h \
- qv4isel_util_p.h
+ qv4isel_util_p.h \
+ debugging.h
llvm {