Commit 7957886b authored by Tobias Tebbi's avatar Tobias Tebbi Committed by Commit Bot

[torque] allow overloading generic macros

Previously, we requested instantiation of generics prior to selecting
a template overload, which resulted in unused templates being
instantiated, possibly triggering unnecessary compile errors.

Bug: v8:7793
Change-Id: I45f4bdbf8aa93749ece416c6c7458d64e6e051f5
Reviewed-on: https://chromium-review.googlesource.com/1154977
Commit-Queue: Tobias Tebbi <tebbi@chromium.org>
Reviewed-by: 's avatarDaniel Clifford <danno@chromium.org>
Cr-Commit-Position: refs/heads/master@{#54950}
parent 690bda84
......@@ -20,6 +20,7 @@ namespace torque {
class Scope;
class ScopeChain;
class Generic;
class Declarable {
public:
......@@ -223,35 +224,37 @@ class Callable : public Declarable {
}
void IncrementReturns() { ++returns_; }
bool HasReturns() const { return returns_; }
base::Optional<Generic*> generic() const { return generic_; }
protected:
Callable(Declarable::Kind kind, const std::string& name,
const Signature& signature)
: Declarable(kind), name_(name), signature_(signature), returns_(0) {}
const Signature& signature, base::Optional<Generic*> generic)
: Declarable(kind),
name_(name),
signature_(signature),
returns_(0),
generic_(generic) {}
private:
std::string name_;
Signature signature_;
size_t returns_;
base::Optional<Generic*> generic_;
};
class Macro : public Callable {
public:
DECLARE_DECLARABLE_BOILERPLATE(Macro, macro);
protected:
Macro(Declarable::Kind type, const std::string& name,
const Signature& signature)
: Callable(type, name, signature) {
private:
friend class Declarations;
Macro(const std::string& name, const Signature& signature,
base::Optional<Generic*> generic)
: Callable(Declarable::kMacro, name, signature, generic) {
if (signature.parameter_types.var_args) {
ReportError("Varargs are not supported for macros.");
}
}
private:
friend class Declarations;
Macro(const std::string& name, const Signature& signature)
: Macro(Declarable::kMacro, name, signature) {}
};
class MacroList : public Declarable {
......@@ -283,8 +286,8 @@ class Builtin : public Callable {
private:
friend class Declarations;
Builtin(const std::string& name, Builtin::Kind kind, bool external,
const Signature& signature)
: Callable(Declarable::kBuiltin, name, signature),
const Signature& signature, base::Optional<Generic*> generic)
: Callable(Declarable::kBuiltin, name, signature, generic),
kind_(kind),
external_(external) {}
......@@ -298,8 +301,9 @@ class RuntimeFunction : public Callable {
private:
friend class Declarations;
RuntimeFunction(const std::string& name, const Signature& signature)
: Callable(Declarable::kRuntimeFunction, name, signature) {}
RuntimeFunction(const std::string& name, const Signature& signature,
base::Optional<Generic*> generic)
: Callable(Declarable::kRuntimeFunction, name, signature, generic) {}
};
class Generic : public Declarable {
......
......@@ -272,8 +272,8 @@ MacroList* Declarations::GetMacroListForName(const std::string& name,
Macro* Declarations::DeclareMacro(const std::string& name,
const Signature& signature,
base::Optional<std::string> op) {
Macro* macro =
RegisterDeclarable(std::unique_ptr<Macro>(new Macro(name, signature)));
Macro* macro = RegisterDeclarable(
std::unique_ptr<Macro>(new Macro(name, signature, GetCurrentGeneric())));
GetMacroListForName(name, signature)->AddMacro(macro);
if (op) GetMacroListForName(*op, signature)->AddMacro(macro);
return macro;
......@@ -283,7 +283,8 @@ Builtin* Declarations::DeclareBuiltin(const std::string& name,
Builtin::Kind kind, bool external,
const Signature& signature) {
CheckAlreadyDeclared(name, "builtin");
Builtin* result = new Builtin(name, kind, external, signature);
Builtin* result =
new Builtin(name, kind, external, signature, GetCurrentGeneric());
Declare(name, std::unique_ptr<Declarable>(result));
return result;
}
......@@ -291,7 +292,8 @@ Builtin* Declarations::DeclareBuiltin(const std::string& name,
RuntimeFunction* Declarations::DeclareRuntimeFunction(
const std::string& name, const Signature& signature) {
CheckAlreadyDeclared(name, "runtime function");
RuntimeFunction* result = new RuntimeFunction(name, signature);
RuntimeFunction* result =
new RuntimeFunction(name, signature, GetCurrentGeneric());
Declare(name, std::unique_ptr<Declarable>(result));
return result;
}
......@@ -370,6 +372,13 @@ TypeVector Declarations::GetCurrentSpecializationTypeNamesVector() {
return result;
}
base::Optional<Generic*> Declarations::GetCurrentGeneric() {
if (current_generic_specialization_ != nullptr) {
return current_generic_specialization_->first;
}
return base::nullopt;
}
std::string GetGeneratedCallableName(const std::string& name,
const TypeVector& specialized_types) {
std::string result = name;
......
......@@ -108,6 +108,7 @@ class Declarations {
GenericDeclaration* generic);
TypeVector GetCurrentSpecializationTypeNamesVector();
base::Optional<Generic*> GetCurrentGeneric();
ScopeChain::Snapshot GetScopeChainSnapshot() { return chain_.TaskSnapshot(); }
......
......@@ -1174,11 +1174,17 @@ void FailMacroLookup(const std::string& reason, const std::string& name,
} // namespace
Callable* ImplementationVisitor::LookupCall(const std::string& name,
const Arguments& arguments) {
Callable* ImplementationVisitor::LookupCall(
const std::string& name, const Arguments& arguments,
const TypeVector& specialization_types) {
Callable* result = nullptr;
TypeVector parameter_types(arguments.parameters.GetTypeVector());
Declarable* declarable = declarations()->Lookup(name);
bool has_template_arguments = !specialization_types.empty();
std::string mangled_name = name;
if (has_template_arguments) {
mangled_name = GetGeneratedCallableName(name, specialization_types);
}
Declarable* declarable = declarations()->Lookup(mangled_name);
if (declarable->IsBuiltin()) {
result = Builtin::cast(declarable);
} else if (declarable->IsRuntimeFunction()) {
......@@ -1250,6 +1256,16 @@ Callable* ImplementationVisitor::LookupCall(const std::string& name,
ReportError(stream.str());
}
if (has_template_arguments) {
Generic* generic = *result->generic();
CallableNode* callable = generic->declaration()->callable;
if (generic->declaration()->body) {
QueueGenericSpecialization({generic, specialization_types}, callable,
callable->signature.get(),
generic->declaration()->body);
}
}
return result;
}
......@@ -1665,8 +1681,10 @@ VisitResult ImplementationVisitor::GeneratePointerCall(
}
VisitResult ImplementationVisitor::GenerateCall(
const std::string& callable_name, Arguments arguments, bool is_tailcall) {
Callable* callable = LookupCall(callable_name, arguments);
const std::string& callable_name, Arguments arguments,
const TypeVector& specialization_types, bool is_tailcall) {
Callable* callable =
LookupCall(callable_name, arguments, specialization_types);
// Operators used in a branching context can also be function calls that never
// return but have a True and False label
......@@ -1828,30 +1846,18 @@ VisitResult ImplementationVisitor::Visit(CallExpression* expr,
bool is_tailcall) {
Arguments arguments;
std::string name = expr->callee.name;
bool has_template_arguments = expr->callee.generic_arguments.size() != 0;
if (has_template_arguments) {
TypeVector specialization_types =
GetTypeVector(expr->callee.generic_arguments);
name = GetGeneratedCallableName(name, specialization_types);
for (auto generic :
declarations()->LookupGeneric(expr->callee.name)->list()) {
CallableNode* callable = generic->declaration()->callable;
if (generic->declaration()->body) {
QueueGenericSpecialization({generic, specialization_types}, callable,
callable->signature.get(),
generic->declaration()->body);
}
}
}
for (Expression* arg : expr->arguments)
arguments.parameters.push_back(Visit(arg));
arguments.labels = LabelsFromIdentifiers(expr->labels);
VisitResult result;
if (!has_template_arguments &&
declarations()->Lookup(expr->callee.name)->IsValue()) {
result = GeneratePointerCall(&expr->callee, arguments, is_tailcall);
bool has_template_arguments = !specialization_types.empty();
for (Expression* arg : expr->arguments)
arguments.parameters.push_back(Visit(arg));
arguments.labels = LabelsFromIdentifiers(expr->labels);
VisitResult result;
if (!has_template_arguments &&
declarations()->Lookup(expr->callee.name)->IsValue()) {
result = GeneratePointerCall(&expr->callee, arguments, is_tailcall);
} else {
result = GenerateCall(name, arguments, is_tailcall);
result = GenerateCall(name, arguments, specialization_types, is_tailcall);
}
if (!result.type()->IsVoidOrNever()) {
GenerateIndent();
......@@ -1924,7 +1930,7 @@ VisitResult ImplementationVisitor::GenerateImplicitConvert(
source.type())) {
std::string name =
GetGeneratedCallableName(kFromConstexprMacroName, {destination_type});
return GenerateCall(name, {{source}, {}}, false);
return GenerateCall(name, {{source}, {}}, {}, false);
} else if (IsAssignableFrom(destination_type, source.type())) {
source.SetType(destination_type);
return source;
......
......@@ -168,7 +168,8 @@ class ImplementationVisitor : public FileVisitor {
ImplementationVisitor* visitor_;
};
Callable* LookupCall(const std::string& name, const Arguments& arguments);
Callable* LookupCall(const std::string& name, const Arguments& arguments,
const TypeVector& specialization_types);
bool GenerateChangedVarFromControlSplit(const Variable* v, bool first = true);
......@@ -203,7 +204,9 @@ class ImplementationVisitor : public FileVisitor {
void GenerateParameterList(const NameVector& list, size_t first = 0);
VisitResult GenerateCall(const std::string& callable_name,
Arguments parameters, bool tail_call = false);
Arguments parameters,
const TypeVector& specialization_types = {},
bool tail_call = false);
VisitResult GeneratePointerCall(Expression* callee,
const Arguments& parameters, bool tail_call);
......
......@@ -235,6 +235,18 @@ TEST(TestForLoop) {
ft.Call();
}
TEST(TestGenericOverload) {
Isolate* isolate(CcTest::InitIsolateOnce());
CodeAssemblerTester asm_tester(isolate, 0);
TestBuiltinsFromDSLAssembler m(asm_tester.state());
{
m.TestGenericOverload();
m.Return(m.UndefinedConstant());
}
FunctionTester ft(asm_tester.GenerateCode(), 0);
ft.Call();
}
} // namespace compiler
} // namespace internal
} // namespace v8
......@@ -386,4 +386,18 @@ module test {
}
check(sum == 7);
}
macro ExampleGenericOverload<A: type>(o : Object) : A {
return o;
}
macro ExampleGenericOverload<A: type>(o : Smi) : A {
return o + 1;
}
macro TestGenericOverload() {
const x_smi : Smi = 5;
const x_object : Object = x_smi;
check(ExampleGenericOverload<Smi>(x_smi) == 6);
check(unsafe_cast<Smi>(ExampleGenericOverload<Object>(x_object)) == 5);
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment