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