[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:
Tobias Tebbi 2018-07-03 14:02:05 +02:00 committed by Commit Bot
parent f7bad08397
commit 81186ff41d
12 changed files with 174 additions and 105 deletions

View File

@ -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);

View File

@ -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;

View File

@ -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:

View File

@ -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);
}
}

View File

@ -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;
}

View File

@ -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_;

View File

@ -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);

View File

@ -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

View File

@ -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,

View File

@ -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;

View File

@ -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);

View File

@ -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>;