Commit 81186ff4 authored by Tobias Tebbi's avatar Tobias Tebbi Committed by Commit Bot

[torque] fix variables, returns and conditionals with constexpr

Variables/return values with constexpr type cannot have multiple
assignments. We check this now.
For conditionals, it is important to always infer a non-constexpr type.
This CL adds the ability to map any type (including union types) to be
mapped to their non-constexpr variant. Conditionals infer their type as
the non-constexpr version of a combination of the two branch types.

In addition, this improves subtyping for constexpr types:
If A extends B, then constexpr A extends constexpr B.
This makes it necessary to clean up "constexpr String", which has nothing
to do with tagged values.

Bug: v8:7793
Change-Id: Ia4d3cd5dc98f45b0ec89adf05c5c6111a0e51cc6
Reviewed-on: https://chromium-review.googlesource.com/1122864
Commit-Queue: Tobias Tebbi <tebbi@chromium.org>
Reviewed-by: 's avatarDaniel Clifford <danno@chromium.org>
Cr-Commit-Position: refs/heads/master@{#54167}
parent f7bad083
...@@ -18,6 +18,7 @@ type uintptr generates 'TNode<UintPtrT>' constexpr 'uintptr_t'; ...@@ -18,6 +18,7 @@ type uintptr generates 'TNode<UintPtrT>' constexpr 'uintptr_t';
type float32 generates 'TNode<Float32T>' constexpr 'float'; type float32 generates 'TNode<Float32T>' constexpr 'float';
type float64 generates 'TNode<Float64T>' constexpr 'double'; type float64 generates 'TNode<Float64T>' constexpr 'double';
type bool generates 'TNode<BoolT>' constexpr 'bool'; type bool generates 'TNode<BoolT>' constexpr 'bool';
type string constexpr 'const char*';
type int31 extends int32 generates 'TNode<Int32T>' constexpr 'int31_t'; type int31 extends int32 generates 'TNode<Int32T>' constexpr 'int31_t';
type RawPtr generates 'TNode<RawPtrT>' constexpr 'void*'; type RawPtr generates 'TNode<RawPtrT>' constexpr 'void*';
...@@ -25,8 +26,7 @@ type AbstractCode extends HeapObject generates 'TNode<AbstractCode>'; ...@@ -25,8 +26,7 @@ type AbstractCode extends HeapObject generates 'TNode<AbstractCode>';
type Code extends AbstractCode generates 'TNode<Code>'; type Code extends AbstractCode generates 'TNode<Code>';
type JSReceiver extends HeapObject generates 'TNode<JSReceiver>'; type JSReceiver extends HeapObject generates 'TNode<JSReceiver>';
type Context extends HeapObject generates 'TNode<Context>'; type Context extends HeapObject generates 'TNode<Context>';
type String extends HeapObject generates type String extends HeapObject generates 'TNode<String>';
'TNode<String>' constexpr 'const char*';
type Oddball extends HeapObject generates 'TNode<Oddball>'; type Oddball extends HeapObject generates 'TNode<Oddball>';
type HeapNumber extends HeapObject generates 'TNode<HeapNumber>'; type HeapNumber extends HeapObject generates 'TNode<HeapNumber>';
type Number = Smi|HeapNumber; type Number = Smi|HeapNumber;
...@@ -69,16 +69,16 @@ type HasPropertyLookupMode constexpr 'HasPropertyLookupMode'; ...@@ -69,16 +69,16 @@ type HasPropertyLookupMode constexpr 'HasPropertyLookupMode';
const NO_ELEMENTS: constexpr ElementsKind generates 'NO_ELEMENTS'; const NO_ELEMENTS: constexpr ElementsKind generates 'NO_ELEMENTS';
const PACKED_SMI_ELEMENTS: constexpr ElementsKind generates const PACKED_SMI_ELEMENTS: constexpr ElementsKind generates
'PACKED_SMI_ELEMENTS'; 'PACKED_SMI_ELEMENTS';
const HOLEY_SMI_ELEMENTS: constexpr ElementsKind generates 'HOLEY_SMI_ELEMENTS'; const HOLEY_SMI_ELEMENTS: constexpr ElementsKind generates 'HOLEY_SMI_ELEMENTS';
const PACKED_ELEMENTS: constexpr ElementsKind generates 'PACKED_ELEMENTS'; const PACKED_ELEMENTS: constexpr ElementsKind generates 'PACKED_ELEMENTS';
const HOLEY_ELEMENTS: constexpr ElementsKind generates 'HOLEY_ELEMENTS'; const HOLEY_ELEMENTS: constexpr ElementsKind generates 'HOLEY_ELEMENTS';
const PACKED_DOUBLE_ELEMENTS: constexpr ElementsKind generates const PACKED_DOUBLE_ELEMENTS: constexpr ElementsKind generates
'PACKED_DOUBLE_ELEMENTS'; 'PACKED_DOUBLE_ELEMENTS';
const HOLEY_DOUBLE_ELEMENTS: constexpr ElementsKind generates const HOLEY_DOUBLE_ELEMENTS: constexpr ElementsKind generates
'HOLEY_DOUBLE_ELEMENTS'; 'HOLEY_DOUBLE_ELEMENTS';
const DICTIONARY_ELEMENTS: constexpr ElementsKind generates const DICTIONARY_ELEMENTS: constexpr ElementsKind generates
'DICTIONARY_ELEMENTS'; 'DICTIONARY_ELEMENTS';
const UINT8_ELEMENTS: constexpr ElementsKind generates 'UINT8_ELEMENTS'; const UINT8_ELEMENTS: constexpr ElementsKind generates 'UINT8_ELEMENTS';
const INT8_ELEMENTS: constexpr ElementsKind generates 'INT8_ELEMENTS'; const INT8_ELEMENTS: constexpr ElementsKind generates 'INT8_ELEMENTS';
...@@ -89,7 +89,7 @@ const INT32_ELEMENTS: constexpr ElementsKind generates 'INT32_ELEMENTS'; ...@@ -89,7 +89,7 @@ const INT32_ELEMENTS: constexpr ElementsKind generates 'INT32_ELEMENTS';
const FLOAT32_ELEMENTS: constexpr ElementsKind generates 'FLOAT32_ELEMENTS'; const FLOAT32_ELEMENTS: constexpr ElementsKind generates 'FLOAT32_ELEMENTS';
const FLOAT64_ELEMENTS: constexpr ElementsKind generates 'FLOAT64_ELEMENTS'; const FLOAT64_ELEMENTS: constexpr ElementsKind generates 'FLOAT64_ELEMENTS';
const UINT8_CLAMPED_ELEMENTS: constexpr ElementsKind generates const UINT8_CLAMPED_ELEMENTS: constexpr ElementsKind generates
'UINT8_CLAMPED_ELEMENTS'; 'UINT8_CLAMPED_ELEMENTS';
const BIGUINT64_ELEMENTS: constexpr ElementsKind generates 'BIGUINT64_ELEMENTS'; const BIGUINT64_ELEMENTS: constexpr ElementsKind generates 'BIGUINT64_ELEMENTS';
const BIGINT64_ELEMENTS: constexpr ElementsKind generates 'BIGINT64_ELEMENTS'; const BIGINT64_ELEMENTS: constexpr ElementsKind generates 'BIGINT64_ELEMENTS';
...@@ -152,8 +152,8 @@ const INTPTR_PARAMETERS: constexpr ParameterMode generates 'INTPTR_PARAMETERS'; ...@@ -152,8 +152,8 @@ const INTPTR_PARAMETERS: constexpr ParameterMode generates 'INTPTR_PARAMETERS';
extern macro Is64(): constexpr bool; extern macro Is64(): constexpr bool;
extern macro Print(constexpr String); extern macro Print(constexpr string);
extern macro Print(constexpr String, Object); extern macro Print(constexpr string, Object);
extern macro Print(Object); extern macro Print(Object);
extern macro DebugBreak(); extern macro DebugBreak();
extern macro ToInteger_Inline(Context, Object): Number; extern macro ToInteger_Inline(Context, Object): Number;
...@@ -348,19 +348,19 @@ extern macro SmiToInt32(Smi): int32; ...@@ -348,19 +348,19 @@ extern macro SmiToInt32(Smi): int32;
extern macro LoadHeapNumberValue(HeapNumber): float64; extern macro LoadHeapNumberValue(HeapNumber): float64;
extern macro ChangeFloat32ToFloat64(float32): float64; extern macro ChangeFloat32ToFloat64(float32): float64;
extern macro ChangeNumberToFloat64(Number): float64; extern macro ChangeNumberToFloat64(Number): float64;
extern macro ChangeInt32ToIntPtr(int32): intptr; // Sign-extends. extern macro ChangeInt32ToIntPtr(int32): intptr; // Sign-extends.
extern macro ChangeUint32ToWord(uint32): uintptr; // Doesn't sign-extend. extern macro ChangeUint32ToWord(uint32): uintptr; // Doesn't sign-extend.
extern macro NumberConstant(constexpr float64): Number; extern macro NumberConstant(constexpr float64): Number;
extern macro NumberConstant(constexpr int32): Number; extern macro NumberConstant(constexpr int32): Number;
extern macro IntPtrConstant(constexpr int31): intptr; extern macro IntPtrConstant(constexpr int31): intptr;
extern macro IntPtrConstant(constexpr int32): intptr; extern macro IntPtrConstant(constexpr int32): intptr;
extern macro Int32Constant(constexpr int31): int32; extern macro Int32Constant(constexpr int31): int31;
extern macro Int32Constant(constexpr int32): int32; extern macro Int32Constant(constexpr int32): int32;
extern macro Float64Constant(constexpr int31): float64; extern macro Float64Constant(constexpr int31): float64;
extern macro SmiConstant(constexpr int31): Smi; extern macro SmiConstant(constexpr int31): Smi;
extern macro BoolConstant(constexpr bool): bool; extern macro BoolConstant(constexpr bool): bool;
extern macro StringConstant(constexpr String): String; extern macro StringConstant(constexpr string): String;
extern macro LanguageModeConstant(constexpr LanguageMode): LanguageMode; extern macro LanguageModeConstant(constexpr LanguageMode): LanguageMode;
extern macro Int32Constant(constexpr ElementsKind): ElementsKind; extern macro Int32Constant(constexpr ElementsKind): ElementsKind;
...@@ -368,6 +368,9 @@ macro from_constexpr<A : type>(o: constexpr int31): A; ...@@ -368,6 +368,9 @@ macro from_constexpr<A : type>(o: constexpr int31): A;
from_constexpr<intptr>(i: constexpr int31): intptr { from_constexpr<intptr>(i: constexpr int31): intptr {
return IntPtrConstant(i); return IntPtrConstant(i);
} }
from_constexpr<int31>(i: constexpr int31): int31 {
return Int32Constant(i);
}
from_constexpr<int32>(i: constexpr int31): int32 { from_constexpr<int32>(i: constexpr int31): int32 {
return Int32Constant(i); return Int32Constant(i);
} }
...@@ -412,14 +415,17 @@ macro from_constexpr<A : type>(e: constexpr ElementsKind): A; ...@@ -412,14 +415,17 @@ macro from_constexpr<A : type>(e: constexpr ElementsKind): A;
from_constexpr<ElementsKind>(e: constexpr ElementsKind): ElementsKind { from_constexpr<ElementsKind>(e: constexpr ElementsKind): ElementsKind {
return Int32Constant(e); return Int32Constant(e);
} }
macro from_constexpr<A : type>(s: constexpr String): A; macro from_constexpr<A : type>(s: constexpr string): A;
from_constexpr<String>(s: constexpr String): String { from_constexpr<String>(s: constexpr string): String {
return StringConstant(s); return StringConstant(s);
} }
from_constexpr<Object>(s: constexpr String): Object { from_constexpr<Object>(s: constexpr string): Object {
return StringConstant(s); return StringConstant(s);
} }
macro convert<A : type>(i: constexpr int31): A {
return i;
}
macro convert<A : type>(i: int32): A; macro convert<A : type>(i: int32): A;
convert<Number>(i: int32): Number { convert<Number>(i: int32): Number {
return ChangeInt32ToTagged(i); return ChangeInt32ToTagged(i);
......
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
module typed_array { module typed_array {
extern runtime TypedArraySortFast(Context, Object): JSTypedArray; extern runtime TypedArraySortFast(Context, Object): JSTypedArray;
extern macro ValidateTypedArray( extern macro ValidateTypedArray(
Context, Object, constexpr String): JSTypedArray; Context, Object, constexpr string): JSTypedArray;
extern macro LoadFixedTypedArrayElementAsTagged( extern macro LoadFixedTypedArrayElementAsTagged(
RawPtr, Smi, constexpr ElementsKind, constexpr ParameterMode): Object; RawPtr, Smi, constexpr ElementsKind, constexpr ParameterMode): Object;
......
...@@ -121,6 +121,9 @@ class Variable : public Value { ...@@ -121,6 +121,9 @@ class Variable : public Value {
bool IsConst() const override { return false; } bool IsConst() const override { return false; }
std::string GetValueForDeclaration() const override { return value_; } std::string GetValueForDeclaration() const override { return value_; }
std::string GetValueForRead() const override { std::string GetValueForRead() const override {
if (!IsDefined()) {
ReportError("Reading uninitialized variable.");
}
if (type()->IsConstexpr()) { if (type()->IsConstexpr()) {
return std::string("*") + value_; return std::string("*") + value_;
} else { } else {
...@@ -130,7 +133,12 @@ class Variable : public Value { ...@@ -130,7 +133,12 @@ class Variable : public Value {
std::string GetValueForWrite() const override { std::string GetValueForWrite() const override {
return std::string("*") + value_; return std::string("*") + value_;
} }
void Define() { defined_ = true; } void Define() {
if (defined_ && type()->IsConstexpr()) {
ReportError("Cannot re-define a constexpr variable.");
}
defined_ = true;
}
bool IsDefined() const { return defined_; } bool IsDefined() const { return defined_; }
private: private:
......
...@@ -478,17 +478,17 @@ void DeclarationVisitor::Visit(CallExpression* expr) { ...@@ -478,17 +478,17 @@ void DeclarationVisitor::Visit(CallExpression* expr) {
} }
void DeclarationVisitor::Visit(TypeDeclaration* decl) { void DeclarationVisitor::Visit(TypeDeclaration* decl) {
std::string extends = decl->extends ? *decl->extends : std::string("");
std::string* extends_ptr = decl->extends ? &extends : nullptr;
std::string generates = decl->generates ? *decl->generates : std::string(""); std::string generates = decl->generates ? *decl->generates : std::string("");
declarations()->DeclareAbstractType(decl->name, generates, extends_ptr); const AbstractType* type = declarations()->DeclareAbstractType(
decl->name, generates, {}, decl->extends);
if (decl->constexpr_generates) { if (decl->constexpr_generates) {
std::string constexpr_name = std::string constexpr_name = CONSTEXPR_TYPE_PREFIX + decl->name;
std::string(CONSTEXPR_TYPE_PREFIX) + decl->name; base::Optional<std::string> constexpr_extends;
if (decl->extends)
constexpr_extends = CONSTEXPR_TYPE_PREFIX + *decl->extends;
declarations()->DeclareAbstractType( declarations()->DeclareAbstractType(
constexpr_name, *decl->constexpr_generates, &(decl->name)); constexpr_name, *decl->constexpr_generates, type, constexpr_extends);
} }
} }
......
...@@ -4,6 +4,7 @@ ...@@ -4,6 +4,7 @@
#include "src/torque/declarations.h" #include "src/torque/declarations.h"
#include "src/torque/declarable.h" #include "src/torque/declarable.h"
#include "src/torque/type-oracle.h"
namespace v8 { namespace v8 {
namespace internal { namespace internal {
...@@ -73,48 +74,22 @@ const Type* Declarations::LookupGlobalType(const std::string& name) { ...@@ -73,48 +74,22 @@ const Type* Declarations::LookupGlobalType(const std::string& name) {
return TypeAlias::cast(raw)->type(); return TypeAlias::cast(raw)->type();
} }
const AbstractType* Declarations::GetAbstractType(const Type* parent,
std::string name,
std::string generated) {
AbstractType* result =
new AbstractType(parent, std::move(name), std::move(generated));
nominal_types_.push_back(std::unique_ptr<AbstractType>(result));
return result;
}
const FunctionPointerType* Declarations::GetFunctionPointerType(
TypeVector argument_types, const Type* return_type) {
const Type* code_type = LookupGlobalType(CODE_TYPE_STRING);
return function_pointer_types_.Add(
FunctionPointerType(code_type, argument_types, return_type));
}
const Type* Declarations::GetUnionType(const Type* a, const Type* b) {
if (a->IsSubtypeOf(b)) return b;
if (b->IsSubtypeOf(a)) return a;
UnionType result = UnionType::FromType(a);
result.Extend(b);
if (base::Optional<const Type*> single = result.GetSingleMember()) {
return *single;
}
return union_types_.Add(std::move(result));
}
const Type* Declarations::GetType(TypeExpression* type_expression) { const Type* Declarations::GetType(TypeExpression* type_expression) {
if (auto* basic = BasicTypeExpression::DynamicCast(type_expression)) { if (auto* basic = BasicTypeExpression::DynamicCast(type_expression)) {
std::string name = std::string name =
(basic->is_constexpr ? CONSTEXPR_TYPE_PREFIX : "") + basic->name; (basic->is_constexpr ? CONSTEXPR_TYPE_PREFIX : "") + basic->name;
return LookupType(name); return LookupType(name);
} else if (auto* union_type = UnionTypeExpression::cast(type_expression)) { } else if (auto* union_type = UnionTypeExpression::cast(type_expression)) {
return GetUnionType(GetType(union_type->a), GetType(union_type->b)); return TypeOracle::GetUnionType(GetType(union_type->a),
GetType(union_type->b));
} else { } else {
auto* function_type_exp = FunctionTypeExpression::cast(type_expression); auto* function_type_exp = FunctionTypeExpression::cast(type_expression);
TypeVector argument_types; TypeVector argument_types;
for (TypeExpression* type_exp : function_type_exp->parameters.types) { for (TypeExpression* type_exp : function_type_exp->parameters.types) {
argument_types.push_back(GetType(type_exp)); argument_types.push_back(GetType(type_exp));
} }
return GetFunctionPointerType(argument_types, return TypeOracle::GetFunctionPointerType(
GetType(function_type_exp->return_type)); argument_types, GetType(function_type_exp->return_type));
} }
} }
...@@ -206,10 +181,11 @@ GenericList* Declarations::LookupGeneric(const std::string& name) { ...@@ -206,10 +181,11 @@ GenericList* Declarations::LookupGeneric(const std::string& name) {
const AbstractType* Declarations::DeclareAbstractType( const AbstractType* Declarations::DeclareAbstractType(
const std::string& name, const std::string& generated, const std::string& name, const std::string& generated,
const std::string* parent) { base::Optional<const AbstractType*> non_constexpr_version,
const base::Optional<std::string>& parent) {
CheckAlreadyDeclared(name, "type"); CheckAlreadyDeclared(name, "type");
const Type* parent_type = nullptr; const Type* parent_type = nullptr;
if (parent != nullptr) { if (parent) {
Declarable* maybe_parent_type = Lookup(*parent); Declarable* maybe_parent_type = Lookup(*parent);
if (maybe_parent_type == nullptr) { if (maybe_parent_type == nullptr) {
std::stringstream s; std::stringstream s;
...@@ -224,7 +200,8 @@ const AbstractType* Declarations::DeclareAbstractType( ...@@ -224,7 +200,8 @@ const AbstractType* Declarations::DeclareAbstractType(
} }
parent_type = TypeAlias::cast(maybe_parent_type)->type(); parent_type = TypeAlias::cast(maybe_parent_type)->type();
} }
const AbstractType* type = GetAbstractType(parent_type, name, generated); const AbstractType* type = TypeOracle::GetAbstractType(
parent_type, name, generated, non_constexpr_version);
DeclareType(name, type); DeclareType(name, type);
return type; return type;
} }
......
...@@ -16,6 +16,8 @@ namespace internal { ...@@ -16,6 +16,8 @@ namespace internal {
namespace torque { namespace torque {
static constexpr const char* const kFromConstexprMacroName = "from_constexpr"; static constexpr const char* const kFromConstexprMacroName = "from_constexpr";
static constexpr const char* kTrueLabelName = "_True";
static constexpr const char* kFalseLabelName = "_False";
class Declarations { class Declarations {
public: public:
...@@ -49,13 +51,6 @@ class Declarations { ...@@ -49,13 +51,6 @@ class Declarations {
const Type* LookupGlobalType(const std::string& name); const Type* LookupGlobalType(const std::string& name);
const Type* GetType(TypeExpression* type_expression); const Type* GetType(TypeExpression* type_expression);
const AbstractType* GetAbstractType(const Type* parent, std::string name,
std::string generated);
const FunctionPointerType* GetFunctionPointerType(TypeVector argument_types,
const Type* return_type);
const Type* GetUnionType(const Type* a, const Type* b);
Builtin* FindSomeInternalBuiltinWithType(const FunctionPointerType* type); Builtin* FindSomeInternalBuiltinWithType(const FunctionPointerType* type);
Value* LookupValue(const std::string& name); Value* LookupValue(const std::string& name);
...@@ -73,9 +68,10 @@ class Declarations { ...@@ -73,9 +68,10 @@ class Declarations {
GenericList* LookupGeneric(const std::string& name); GenericList* LookupGeneric(const std::string& name);
const AbstractType* DeclareAbstractType(const std::string& name, const AbstractType* DeclareAbstractType(
const std::string& generated, const std::string& name, const std::string& generated,
const std::string* parent = nullptr); base::Optional<const AbstractType*> non_constexpr_version,
const base::Optional<std::string>& parent = {});
void DeclareType(const std::string& name, const Type* type); void DeclareType(const std::string& name, const Type* type);
...@@ -151,9 +147,6 @@ class Declarations { ...@@ -151,9 +147,6 @@ class Declarations {
const SpecializationKey* current_generic_specialization_; const SpecializationKey* current_generic_specialization_;
Statement* next_body_; Statement* next_body_;
std::vector<std::unique_ptr<Declarable>> declarables_; std::vector<std::unique_ptr<Declarable>> declarables_;
Deduplicator<FunctionPointerType> function_pointer_types_;
Deduplicator<UnionType> union_types_;
std::vector<std::unique_ptr<Type>> nominal_types_;
std::map<const Module*, Scope*> module_scopes_; std::map<const Module*, Scope*> module_scopes_;
std::map<std::pair<const AstNode*, TypeVector>, Scope*> scopes_; std::map<std::pair<const AstNode*, TypeVector>, Scope*> scopes_;
std::map<Generic*, ScopeChain::Snapshot> generic_declaration_scopes_; std::map<Generic*, ScopeChain::Snapshot> generic_declaration_scopes_;
......
...@@ -187,15 +187,16 @@ void ImplementationVisitor::Visit(TorqueMacroDeclaration* decl, ...@@ -187,15 +187,16 @@ void ImplementationVisitor::Visit(TorqueMacroDeclaration* decl,
if (!return_type->IsConstexpr()) { if (!return_type->IsConstexpr()) {
GenerateIndent(); GenerateIndent();
source_out() << "Node* return_default = &*SmiConstant(0);" << std::endl; source_out() << "Node* return_default = &*SmiConstant(0);" << std::endl;
VisitResult init = {
return_type,
(std::string("UncheckedCast<") +
return_type->GetGeneratedTNodeTypeName() + ">(return_default)")};
result_var =
GenerateVariableDeclaration(decl, kReturnValueVariable, {}, init);
} else {
result_var =
GenerateVariableDeclaration(decl, kReturnValueVariable, {}, {});
} }
VisitResult init = {return_type,
return_type->IsConstexpr()
? (return_type->GetGeneratedTypeName() + "()")
: (std::string("UncheckedCast<") +
return_type->GetGeneratedTNodeTypeName() +
">(return_default)")};
result_var =
GenerateVariableDeclaration(decl, kReturnValueVariable, {}, init);
} }
Label* macro_end = declarations()->DeclareLabel("macro_end"); Label* macro_end = declarations()->DeclareLabel("macro_end");
GenerateLabelDefinition(macro_end, decl); GenerateLabelDefinition(macro_end, decl);
...@@ -335,8 +336,7 @@ VisitResult ImplementationVisitor::Visit(ConditionalExpression* expr) { ...@@ -335,8 +336,7 @@ VisitResult ImplementationVisitor::Visit(ConditionalExpression* expr) {
const Type* common_type = GetCommonType(left.type(), right.type()); const Type* common_type = GetCommonType(left.type(), right.type());
std::string result_var = NewTempVariable(); std::string result_var = NewTempVariable();
const Variable* result = Variable* result = GenerateVariableDeclaration(expr, result_var, common_type);
GenerateVariableDeclaration(expr, result_var, common_type);
{ {
ScopedIndent indent(this); ScopedIndent indent(this);
...@@ -357,14 +357,14 @@ VisitResult ImplementationVisitor::Visit(ConditionalExpression* expr) { ...@@ -357,14 +357,14 @@ VisitResult ImplementationVisitor::Visit(ConditionalExpression* expr) {
} }
GenerateLabelBind(true_label); GenerateLabelBind(true_label);
GenerateIndent(); GenerateIndent();
source_out() << result->GetValueForWrite() << " = " << f1 << "();" VisitResult left_result = {right.type(), f1 + "()"};
<< std::endl; GenerateAssignToVariable(result, left_result);
GenerateLabelGoto(done_label); GenerateLabelGoto(done_label);
GenerateLabelBind(false_label); GenerateLabelBind(false_label);
GenerateIndent(); GenerateIndent();
source_out() << result->GetValueForWrite() << " = " << f2 << "();" VisitResult right_result = {right.type(), f2 + "()"};
<< std::endl; GenerateAssignToVariable(result, right_result);
GenerateLabelGoto(done_label); GenerateLabelGoto(done_label);
GenerateLabelBind(done_label); GenerateLabelBind(done_label);
...@@ -504,7 +504,7 @@ VisitResult ImplementationVisitor::GetBuiltinCode(Builtin* builtin) { ...@@ -504,7 +504,7 @@ VisitResult ImplementationVisitor::GetBuiltinCode(Builtin* builtin) {
"creating function pointers is only allowed for internal builtins with " "creating function pointers is only allowed for internal builtins with "
"stub linkage"); "stub linkage");
} }
const Type* type = declarations()->GetFunctionPointerType( const Type* type = TypeOracle::GetFunctionPointerType(
builtin->signature().parameter_types.types, builtin->signature().parameter_types.types,
builtin->signature().return_type); builtin->signature().return_type);
std::string code = std::string code =
...@@ -1174,8 +1174,7 @@ Callable* ImplementationVisitor::LookupCall(const std::string& name, ...@@ -1174,8 +1174,7 @@ Callable* ImplementationVisitor::LookupCall(const std::string& name,
is_better_candidate); is_better_candidate);
for (Macro* candidate : candidates) { for (Macro* candidate : candidates) {
if (candidate != best && !is_better_candidate(best, candidate)) { if (candidate != best && !is_better_candidate(best, candidate)) {
FailMacroLookup("ambiguous macro", name, arguments, FailMacroLookup("ambiguous macro", name, arguments, candidates);
macros_with_same_name);
} }
} }
result = best; result = best;
...@@ -1221,16 +1220,15 @@ void ImplementationVisitor::GenerateChangedVarsFromControlSplit(AstNode* node) { ...@@ -1221,16 +1220,15 @@ void ImplementationVisitor::GenerateChangedVarsFromControlSplit(AstNode* node) {
const Type* ImplementationVisitor::GetCommonType(const Type* left, const Type* ImplementationVisitor::GetCommonType(const Type* left,
const Type* right) { const Type* right) {
const Type* common_type = TypeOracle::GetVoidType(); const Type* common_type;
if (IsAssignableFrom(left, right)) { if (IsAssignableFrom(left, right)) {
common_type = left; common_type = left;
} else if (IsAssignableFrom(right, left)) { } else if (IsAssignableFrom(right, left)) {
common_type = right; common_type = right;
} else { } else {
std::stringstream s; common_type = TypeOracle::GetUnionType(left, right);
s << "illegal combination of types " << *left << " and " << *right;
ReportError(s.str());
} }
common_type = common_type->NonConstexprVersion();
return common_type; return common_type;
} }
...@@ -1280,7 +1278,7 @@ void ImplementationVisitor::GenerateAssignToVariable(Variable* var, ...@@ -1280,7 +1278,7 @@ void ImplementationVisitor::GenerateAssignToVariable(Variable* var,
VisitResult casted_value = GenerateImplicitConvert(var->type(), value); VisitResult casted_value = GenerateImplicitConvert(var->type(), value);
GenerateIndent(); GenerateIndent();
source_out() << var->GetValueForWrite() << " = " << casted_value.variable() source_out() << var->GetValueForWrite() << " = " << casted_value.variable()
<< ";" << std::endl; << ";\n";
var->Define(); var->Define();
} }
...@@ -1709,7 +1707,8 @@ VisitResult ImplementationVisitor::GenerateImplicitConvert( ...@@ -1709,7 +1707,8 @@ VisitResult ImplementationVisitor::GenerateImplicitConvert(
return source; return source;
} }
if (TypeOracle::IsImplicitlyConverableFrom(destination_type, source.type())) { if (TypeOracle::IsImplicitlyConvertableFrom(destination_type,
source.type())) {
std::string name = std::string name =
GetGeneratedCallableName(kFromConstexprMacroName, {destination_type}); GetGeneratedCallableName(kFromConstexprMacroName, {destination_type});
return GenerateCall(name, {{source}, {}}, false); return GenerateCall(name, {{source}, {}}, false);
......
...@@ -20,6 +20,37 @@ class TypeOracle : public ContextualClass<TypeOracle> { ...@@ -20,6 +20,37 @@ class TypeOracle : public ContextualClass<TypeOracle> {
explicit TypeOracle(Declarations* declarations) explicit TypeOracle(Declarations* declarations)
: declarations_(declarations) {} : declarations_(declarations) {}
static const AbstractType* GetAbstractType(
const Type* parent, std::string name, std::string generated,
base::Optional<const AbstractType*> non_constexpr_version) {
AbstractType* result = new AbstractType(
parent, std::move(name), std::move(generated), non_constexpr_version);
Get().nominal_types_.push_back(std::unique_ptr<AbstractType>(result));
return result;
}
static const FunctionPointerType* GetFunctionPointerType(
TypeVector argument_types, const Type* return_type) {
const Type* code_type = Get().GetBuiltinType(CODE_TYPE_STRING);
return Get().function_pointer_types_.Add(
FunctionPointerType(code_type, argument_types, return_type));
}
static const Type* GetUnionType(UnionType type) {
if (base::Optional<const Type*> single = type.GetSingleMember()) {
return *single;
}
return Get().union_types_.Add(std::move(type));
}
static const Type* GetUnionType(const Type* a, const Type* b) {
if (a->IsSubtypeOf(b)) return b;
if (b->IsSubtypeOf(a)) return a;
UnionType result = UnionType::FromType(a);
result.Extend(b);
return GetUnionType(std::move(result));
}
static const Type* GetArgumentsType() { static const Type* GetArgumentsType() {
return Get().GetBuiltinType(ARGUMENTS_TYPE_STRING); return Get().GetBuiltinType(ARGUMENTS_TYPE_STRING);
} }
...@@ -56,7 +87,7 @@ class TypeOracle : public ContextualClass<TypeOracle> { ...@@ -56,7 +87,7 @@ class TypeOracle : public ContextualClass<TypeOracle> {
return Get().GetBuiltinType(CONST_INT31_TYPE_STRING); return Get().GetBuiltinType(CONST_INT31_TYPE_STRING);
} }
static bool IsImplicitlyConverableFrom(const Type* to, const Type* from) { static bool IsImplicitlyConvertableFrom(const Type* to, const Type* from) {
std::string name = GetGeneratedCallableName(kFromConstexprMacroName, {to}); std::string name = GetGeneratedCallableName(kFromConstexprMacroName, {to});
return Get().declarations_->TryLookupMacro(name, {from}) != nullptr; return Get().declarations_->TryLookupMacro(name, {from}) != nullptr;
} }
...@@ -67,6 +98,9 @@ class TypeOracle : public ContextualClass<TypeOracle> { ...@@ -67,6 +98,9 @@ class TypeOracle : public ContextualClass<TypeOracle> {
} }
Declarations* declarations_; Declarations* declarations_;
Deduplicator<FunctionPointerType> function_pointer_types_;
Deduplicator<UnionType> union_types_;
std::vector<std::unique_ptr<Type>> nominal_types_;
}; };
} // namespace torque } // namespace torque
......
...@@ -141,6 +141,19 @@ std::string UnionType::GetGeneratedTNodeTypeName() const { ...@@ -141,6 +141,19 @@ std::string UnionType::GetGeneratedTNodeTypeName() const {
return parent()->GetGeneratedTNodeTypeName(); return parent()->GetGeneratedTNodeTypeName();
} }
const Type* UnionType::NonConstexprVersion() const {
if (IsConstexpr()) {
auto it = types_.begin();
UnionType result((*it)->NonConstexprVersion());
++it;
for (; it != types_.end(); ++it) {
result.Extend((*it)->NonConstexprVersion());
}
return TypeOracle::GetUnionType(std::move(result));
}
return this;
}
void PrintSignature(std::ostream& os, const Signature& sig, bool with_names) { void PrintSignature(std::ostream& os, const Signature& sig, bool with_names) {
os << "("; os << "(";
for (size_t i = 0; i < sig.parameter_types.types.size(); ++i) { for (size_t i = 0; i < sig.parameter_types.types.size(); ++i) {
...@@ -207,8 +220,8 @@ bool Signature::HasSameTypesAs(const Signature& other) const { ...@@ -207,8 +220,8 @@ bool Signature::HasSameTypesAs(const Signature& other) const {
bool IsAssignableFrom(const Type* to, const Type* from) { bool IsAssignableFrom(const Type* to, const Type* from) {
if (to == from) return true; if (to == from) return true;
if (from->IsSubtypeOf(to) && !from->IsConstexpr()) return true; if (from->IsSubtypeOf(to)) return true;
return TypeOracle::IsImplicitlyConverableFrom(to, from); return TypeOracle::IsImplicitlyConvertableFrom(to, from);
} }
bool IsCompatibleSignature(const Signature& sig, const TypeVector& types, bool IsCompatibleSignature(const Signature& sig, const TypeVector& types,
......
...@@ -25,7 +25,7 @@ static const char* const VOID_TYPE_STRING = "void"; ...@@ -25,7 +25,7 @@ static const char* const VOID_TYPE_STRING = "void";
static const char* const ARGUMENTS_TYPE_STRING = "constexpr Arguments"; static const char* const ARGUMENTS_TYPE_STRING = "constexpr Arguments";
static const char* const CONTEXT_TYPE_STRING = "Context"; static const char* const CONTEXT_TYPE_STRING = "Context";
static const char* const OBJECT_TYPE_STRING = "Object"; static const char* const OBJECT_TYPE_STRING = "Object";
static const char* const CONST_STRING_TYPE_STRING = "constexpr String"; static const char* const CONST_STRING_TYPE_STRING = "constexpr string";
static const char* const CODE_TYPE_STRING = "Code"; static const char* const CODE_TYPE_STRING = "Code";
static const char* const INTPTR_TYPE_STRING = "intptr"; static const char* const INTPTR_TYPE_STRING = "intptr";
static const char* const CONST_INT31_TYPE_STRING = "constexpr int31"; static const char* const CONST_INT31_TYPE_STRING = "constexpr int31";
...@@ -88,6 +88,7 @@ class Type : public TypeBase { ...@@ -88,6 +88,7 @@ class Type : public TypeBase {
virtual std::string GetGeneratedTypeName() const = 0; virtual std::string GetGeneratedTypeName() const = 0;
virtual std::string GetGeneratedTNodeTypeName() const = 0; virtual std::string GetGeneratedTNodeTypeName() const = 0;
virtual bool IsConstexpr() const = 0; virtual bool IsConstexpr() const = 0;
virtual const Type* NonConstexprVersion() const = 0;
static const Type* CommonSupertype(const Type* a, const Type* b); static const Type* CommonSupertype(const Type* a, const Type* b);
void AddAlias(std::string alias) const { aliases_.insert(std::move(alias)); } void AddAlias(std::string alias) const { aliases_.insert(std::move(alias)); }
...@@ -121,17 +122,27 @@ class AbstractType final : public Type { ...@@ -121,17 +122,27 @@ class AbstractType final : public Type {
return name().substr(0, strlen(CONSTEXPR_TYPE_PREFIX)) == return name().substr(0, strlen(CONSTEXPR_TYPE_PREFIX)) ==
CONSTEXPR_TYPE_PREFIX; CONSTEXPR_TYPE_PREFIX;
} }
const Type* NonConstexprVersion() const override {
if (IsConstexpr()) return *non_constexpr_version_;
return this;
}
private: private:
friend class Declarations; friend class TypeOracle;
AbstractType(const Type* parent, const std::string& name, AbstractType(const Type* parent, const std::string& name,
const std::string& generated_type) const std::string& generated_type,
base::Optional<const AbstractType*> non_constexpr_version)
: Type(Kind::kAbstractType, parent), : Type(Kind::kAbstractType, parent),
name_(name), name_(name),
generated_type_(generated_type) {} generated_type_(generated_type),
non_constexpr_version_(non_constexpr_version) {
DCHECK_EQ(non_constexpr_version_.has_value(), IsConstexpr());
if (parent) DCHECK(parent->IsConstexpr() == IsConstexpr());
}
const std::string name_; const std::string name_;
const std::string generated_type_; const std::string generated_type_;
base::Optional<const AbstractType*> non_constexpr_version_;
}; };
// For now, function pointers are restricted to Code objects of Torque-defined // For now, function pointers are restricted to Code objects of Torque-defined
...@@ -147,7 +158,11 @@ class FunctionPointerType final : public Type { ...@@ -147,7 +158,11 @@ class FunctionPointerType final : public Type {
std::string GetGeneratedTNodeTypeName() const override { std::string GetGeneratedTNodeTypeName() const override {
return parent()->GetGeneratedTNodeTypeName(); return parent()->GetGeneratedTNodeTypeName();
} }
bool IsConstexpr() const override { return parent()->IsConstexpr(); } bool IsConstexpr() const override {
DCHECK(!parent()->IsConstexpr());
return false;
}
const Type* NonConstexprVersion() const override { return this; }
const TypeVector& parameter_types() const { return parameter_types_; } const TypeVector& parameter_types() const { return parameter_types_; }
const Type* return_type() const { return return_type_; } const Type* return_type() const { return return_type_; }
...@@ -165,7 +180,7 @@ class FunctionPointerType final : public Type { ...@@ -165,7 +180,7 @@ class FunctionPointerType final : public Type {
} }
private: private:
friend class Declarations; friend class TypeOracle;
FunctionPointerType(const Type* parent, TypeVector parameter_types, FunctionPointerType(const Type* parent, TypeVector parameter_types,
const Type* return_type) const Type* return_type)
: Type(Kind::kFunctionPointerType, parent), : Type(Kind::kFunctionPointerType, parent),
...@@ -197,6 +212,7 @@ class UnionType final : public Type { ...@@ -197,6 +212,7 @@ class UnionType final : public Type {
DCHECK_EQ(false, parent()->IsConstexpr()); DCHECK_EQ(false, parent()->IsConstexpr());
return false; return false;
} }
const Type* NonConstexprVersion() const override;
friend size_t hash_value(const UnionType& p) { friend size_t hash_value(const UnionType& p) {
size_t result = 0; size_t result = 0;
......
...@@ -139,10 +139,28 @@ TEST(TestFunctionPointers) { ...@@ -139,10 +139,28 @@ TEST(TestFunctionPointers) {
m.UncheckedCast<Context>(m.Parameter(kNumParams + 2)); m.UncheckedCast<Context>(m.Parameter(kNumParams + 2));
m.Return(m.TestFunctionPointers(context)); m.Return(m.TestFunctionPointers(context));
} }
FunctionTester ft(asm_tester.GenerateCode(), 0); FunctionTester ft(asm_tester.GenerateCode(), kNumParams);
ft.CheckCall(ft.true_value()); ft.CheckCall(ft.true_value());
} }
TEST(TestTernaryOperator) {
Isolate* isolate(CcTest::InitIsolateOnce());
const int kNumParams = 1;
CodeAssemblerTester asm_tester(isolate, kNumParams);
TestBuiltinsFromDSLAssembler m(asm_tester.state());
{
TNode<Smi> arg = m.UncheckedCast<Smi>(m.Parameter(0));
m.Return(m.TestTernaryOperator(arg));
}
FunctionTester ft(asm_tester.GenerateCode(), kNumParams);
Handle<Object> result1 =
ft.Call(Handle<Smi>(Smi::FromInt(-5), isolate)).ToHandleChecked();
CHECK_EQ(-15, Handle<Smi>::cast(result1)->value());
Handle<Object> result2 =
ft.Call(Handle<Smi>(Smi::FromInt(3), isolate)).ToHandleChecked();
CHECK_EQ(103, Handle<Smi>::cast(result2)->value());
}
TEST(TestFunctionPointerToGeneric) { TEST(TestFunctionPointerToGeneric) {
Isolate* isolate(CcTest::InitIsolateOnce()); Isolate* isolate(CcTest::InitIsolateOnce());
CodeAssemblerTester asm_tester(isolate, 0); CodeAssemblerTester asm_tester(isolate, 0);
......
...@@ -174,11 +174,16 @@ module test { ...@@ -174,11 +174,16 @@ module test {
} }
macro TestVariableRedeclaration(context : Context) : Boolean { macro TestVariableRedeclaration(context : Context) : Boolean {
let var1 : Number = from_constexpr<bool>(42 == 0) ? 0 : 1; let var1 : int31 = from_constexpr<bool>(42 == 0) ? 0 : 1;
let var2 : Number = from_constexpr<bool>(42 == 0) ? 1 : 0; let var2 : int31 = from_constexpr<bool>(42 == 0) ? 1 : 0;
return True; return True;
} }
macro TestTernaryOperator(x : Smi) : Smi {
let b : bool = x < 0 ? true : false;
return b ? x - 10 : x + 100;
}
macro TestFunctionPointerToGeneric(c: Context) { macro TestFunctionPointerToGeneric(c: Context) {
let fptr1: builtin(Context, Smi) => Object = GenericBuiltinTest<Smi>; let fptr1: builtin(Context, Smi) => Object = GenericBuiltinTest<Smi>;
let fptr2: builtin(Context, Object) => Object = GenericBuiltinTest<Object>; let fptr2: builtin(Context, Object) => Object = GenericBuiltinTest<Object>;
......
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