aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml/compiler
diff options
context:
space:
mode:
authorLars Knoll <lars.knoll@qt.io>2018-06-30 19:19:18 +0200
committerLars Knoll <lars.knoll@qt.io>2018-07-03 08:09:05 +0000
commit6d8dbba4624c8a453ba13ff009f011f2946422bb (patch)
treeec1aec45c122a31d7e5c1c19daa9ba5d4f824355 /src/qml/compiler
parentdeaa99f66ddedc2ea79e6902c665925b04665e68 (diff)
Add support for super calls
Implement super call support for class constructor functions. Change-Id: I3c64276234689cf4f644b095e0fc8ca1c634ac53 Reviewed-by: Simon Hausmann <simon.hausmann@qt.io>
Diffstat (limited to 'src/qml/compiler')
-rw-r--r--src/qml/compiler/qv4bytecodehandler.cpp3
-rw-r--r--src/qml/compiler/qv4codegen.cpp97
-rw-r--r--src/qml/compiler/qv4codegen_p.h6
-rw-r--r--src/qml/compiler/qv4instr_moth.cpp3
-rw-r--r--src/qml/compiler/qv4instr_moth_p.h2
5 files changed, 80 insertions, 31 deletions
diff --git a/src/qml/compiler/qv4bytecodehandler.cpp b/src/qml/compiler/qv4bytecodehandler.cpp
index 3e683cc8bf..b96c04dc01 100644
--- a/src/qml/compiler/qv4bytecodehandler.cpp
+++ b/src/qml/compiler/qv4bytecodehandler.cpp
@@ -364,6 +364,9 @@ std::vector<int> ByteCodeHandler::collectLabelsInBytecode(const char *code, uint
COLLECTOR_BEGIN_INSTR(ConvertThisToObject)
COLLECTOR_END_INSTR(ConvertThisToObject)
+ COLLECTOR_BEGIN_INSTR(LoadSuperConstructor)
+ COLLECTOR_END_INSTR(LoadSuperConstructor)
+
COLLECTOR_BEGIN_INSTR(ToObject)
COLLECTOR_END_INSTR(ToObject)
diff --git a/src/qml/compiler/qv4codegen.cpp b/src/qml/compiler/qv4codegen.cpp
index 40aac8f7bb..36f959b301 100644
--- a/src/qml/compiler/qv4codegen.cpp
+++ b/src/qml/compiler/qv4codegen.cpp
@@ -1108,6 +1108,8 @@ bool Codegen::visit(ArrayMemberExpression *ast)
if (hasError)
return false;
base = base.storeOnStack();
+ if (hasError)
+ return false;
if (AST::StringLiteral *str = AST::cast<AST::StringLiteral *>(ast->expression)) {
QString s = str->value.toString();
uint arrayIndex = QV4::String::toArrayIndex(s);
@@ -1736,6 +1738,9 @@ bool Codegen::visit(CallExpression *ast)
break;
case Reference::Name:
break;
+ case Reference::Super:
+ handleConstruct(base, ast->arguments);
+ return false;
default:
base = base.storeOnStack();
break;
@@ -2015,12 +2020,12 @@ bool Codegen::visit(FalseLiteral *)
return false;
}
-bool Codegen::visit(SuperLiteral *ast)
+bool Codegen::visit(SuperLiteral *)
{
if (hasError)
return false;
- throwSyntaxError(ast->superToken, QLatin1String("Support for 'super' keyword not implemented"));
+ _expr.setResult(Reference::fromSuper(this));
return false;
}
@@ -2207,6 +2212,43 @@ bool Codegen::visit(NestedExpression *ast)
return false;
}
+void Codegen::handleConstruct(const Reference &base, ArgumentList *arguments)
+{
+ Reference constructor;
+ if (base.isSuper()) {
+ Instruction::LoadSuperConstructor super;
+ bytecodeGenerator->addInstruction(super);
+ constructor = Reference::fromAccumulator(this).storeOnStack();
+ } else {
+ constructor = base.storeOnStack();
+ }
+
+ auto calldata = pushArgs(arguments);
+ if (hasError)
+ return;
+
+ if (base.isSuper()) {
+ Reference::fromStackSlot(this, CallData::Function).loadInAccumulator();
+ } else {
+ constructor.loadInAccumulator();
+ }
+
+ if (calldata.hasSpread) {
+ Instruction::ConstructWithSpread create;
+ create.func = constructor.stackSlot();
+ create.argc = calldata.argc;
+ create.argv = calldata.argv;
+ bytecodeGenerator->addInstruction(create);
+ } else {
+ Instruction::Construct create;
+ create.func = constructor.stackSlot();
+ create.argc = calldata.argc;
+ create.argv = calldata.argv;
+ bytecodeGenerator->addInstruction(create);
+ }
+ _expr.setResult(Reference::fromAccumulator(this));
+}
+
bool Codegen::visit(NewExpression *ast)
{
if (hasError)
@@ -2217,16 +2259,12 @@ bool Codegen::visit(NewExpression *ast)
Reference base = expression(ast->expression);
if (hasError)
return false;
+ if (base.isSuper()) {
+ throwSyntaxError(ast->expression->firstSourceLocation(), QStringLiteral("Cannot use new with super."));
+ return false;
+ }
- base = base.storeOnStack();
- base.loadInAccumulator();
-
- Instruction::Construct create;
- create.func = base.stackSlot();
- create.argc = 0;
- create.argv = 0;
- bytecodeGenerator->addInstruction(create);
- _expr.setResult(Reference::fromAccumulator(this));
+ handleConstruct(base, nullptr);
return false;
}
@@ -2240,28 +2278,12 @@ bool Codegen::visit(NewMemberExpression *ast)
Reference base = expression(ast->base);
if (hasError)
return false;
- base = base.storeOnStack();
-
- auto calldata = pushArgs(ast->arguments);
- if (hasError)
+ if (base.isSuper()) {
+ throwSyntaxError(ast->base->firstSourceLocation(), QStringLiteral("Cannot use new with super."));
return false;
-
- base.loadInAccumulator();
-
- if (calldata.hasSpread) {
- Instruction::ConstructWithSpread create;
- create.func = base.stackSlot();
- create.argc = calldata.argc;
- create.argv = calldata.argv;
- bytecodeGenerator->addInstruction(create);
- } else {
- Instruction::Construct create;
- create.func = base.stackSlot();
- create.argc = calldata.argc;
- create.argv = calldata.argv;
- bytecodeGenerator->addInstruction(create);
}
- _expr.setResult(Reference::fromAccumulator(this));
+
+ handleConstruct(base, ast->arguments);
return false;
}
@@ -3684,6 +3706,8 @@ Codegen::Reference &Codegen::Reference::operator =(const Reference &other)
case Invalid:
case Accumulator:
break;
+ case Super:
+ break;
case StackSlot:
theStackSlot = other.theStackSlot;
break;
@@ -3733,6 +3757,8 @@ bool Codegen::Reference::operator==(const Codegen::Reference &other) const
case Invalid:
case Accumulator:
break;
+ case Super:
+ return true;
case StackSlot:
return theStackSlot == other.theStackSlot;
case ScopedLocal:
@@ -3776,6 +3802,9 @@ Codegen::Reference Codegen::Reference::asLValue() const
case Invalid:
case Accumulator:
Q_UNREACHABLE();
+ case Super:
+ codegen->throwSyntaxError(AST::SourceLocation(), QStringLiteral("Super lvalues not implemented."));
+ return *this;
case Member:
if (!propertyBase.isStackSlot()) {
Reference r = *this;
@@ -3909,6 +3938,9 @@ void Codegen::Reference::storeAccumulator() const
return;
}
switch (type) {
+ case Super:
+ codegen->throwSyntaxError(SourceLocation(), QStringLiteral("storing super properties not implemented."));
+ return;
case StackSlot: {
Instruction::StoreReg store;
store.reg = theStackSlot;
@@ -3986,6 +4018,9 @@ void Codegen::Reference::loadInAccumulator() const
switch (type) {
case Accumulator:
return;
+ case Super:
+ codegen->throwSyntaxError(AST::SourceLocation(), QStringLiteral("Super property access not implemented."));
+ return;
case Const: {
QT_WARNING_PUSH
QT_WARNING_DISABLE_GCC("-Wmaybe-uninitialized") // the loads below are empty structs.
diff --git a/src/qml/compiler/qv4codegen_p.h b/src/qml/compiler/qv4codegen_p.h
index cac8da4e71..814754aea2 100644
--- a/src/qml/compiler/qv4codegen_p.h
+++ b/src/qml/compiler/qv4codegen_p.h
@@ -179,6 +179,7 @@ public:
enum Type {
Invalid,
Accumulator,
+ Super,
StackSlot,
ScopedLocal,
Name,
@@ -215,6 +216,7 @@ public:
}
bool isConstant() const { return type == Const; }
bool isAccumulator() const { return type == Accumulator; }
+ bool isSuper() const { return type == Super; }
bool isStackSlot() const { return type == StackSlot; }
bool isRegister() const {
return isStackSlot();
@@ -245,6 +247,9 @@ public:
static Reference fromAccumulator(Codegen *cg) {
return Reference(cg, Accumulator);
}
+ static Reference fromSuper(Codegen *cg) {
+ return Reference(cg, Super);
+ }
static Reference fromStackSlot(Codegen *cg, int tempIndex = -1, bool isLocal = false) {
Reference r(cg, StackSlot);
if (tempIndex == -1)
@@ -704,6 +709,7 @@ protected:
private:
VolatileMemoryLocations scanVolatileMemoryLocations(AST::Node *ast) const;
+ void handleConstruct(const Reference &base, AST::ArgumentList *args);
};
}
diff --git a/src/qml/compiler/qv4instr_moth.cpp b/src/qml/compiler/qv4instr_moth.cpp
index 2d2f7bc27f..2ce06c9552 100644
--- a/src/qml/compiler/qv4instr_moth.cpp
+++ b/src/qml/compiler/qv4instr_moth.cpp
@@ -504,6 +504,9 @@ void dumpBytecode(const char *code, int len, int nLocals, int nFormals, int /*st
MOTH_BEGIN_INSTR(ConvertThisToObject)
MOTH_END_INSTR(ConvertThisToObject)
+ MOTH_BEGIN_INSTR(LoadSuperConstructor)
+ MOTH_END_INSTR(LoadSuperConstructor)
+
MOTH_BEGIN_INSTR(ToObject)
MOTH_END_INSTR(ToObject)
diff --git a/src/qml/compiler/qv4instr_moth_p.h b/src/qml/compiler/qv4instr_moth_p.h
index 3bd60288c3..00ed76e6c2 100644
--- a/src/qml/compiler/qv4instr_moth_p.h
+++ b/src/qml/compiler/qv4instr_moth_p.h
@@ -142,6 +142,7 @@ QT_BEGIN_NAMESPACE
#define INSTR_CreateUnmappedArgumentsObject(op) INSTRUCTION(op, CreateUnmappedArgumentsObject, 0)
#define INSTR_CreateRestParameter(op) INSTRUCTION(op, CreateRestParameter, 1, argIndex)
#define INSTR_ConvertThisToObject(op) INSTRUCTION(op, ConvertThisToObject, 0)
+#define INSTR_LoadSuperConstructor(op) INSTRUCTION(op, LoadSuperConstructor, 0)
#define INSTR_ToObject(op) INSTRUCTION(op, ToObject, 0)
#define INSTR_Jump(op) INSTRUCTION(op, Jump, 1, offset)
#define INSTR_JumpTrue(op) INSTRUCTION(op, JumpTrue, 1, offset)
@@ -271,6 +272,7 @@ QT_BEGIN_NAMESPACE
F(CreateUnmappedArgumentsObject) \
F(CreateRestParameter) \
F(ConvertThisToObject) \
+ F(LoadSuperConstructor) \
F(ToObject) \
F(Jump) \
F(JumpTrue) \