diff --git a/BUILD.bazel b/BUILD.bazel index f45ec37ba2..9cd6d3ca60 100644 --- a/BUILD.bazel +++ b/BUILD.bazel @@ -923,6 +923,8 @@ filegroup( filegroup( name = "torque_base_files", srcs = [ + "src/numbers/integer-literal-inl.h", + "src/numbers/integer-literal.h", "src/torque/ast.h", "src/torque/cc-generator.cc", "src/torque/cc-generator.h", @@ -2801,6 +2803,8 @@ filegroup( "src/interpreter/interpreter-generator.h", "src/interpreter/interpreter-intrinsics-generator.cc", "src/interpreter/interpreter-intrinsics-generator.h", + "src/numbers/integer-literal-inl.h", + "src/numbers/integer-literal.h", ] + select({ "@v8//bazel/config:v8_target_ia32": ["src/builtins/ia32/builtins-ia32.cc"], "@v8//bazel/config:v8_target_x64": ["src/builtins/x64/builtins-x64.cc"], diff --git a/BUILD.gn b/BUILD.gn index ce150e6a00..32ffa7acf0 100644 --- a/BUILD.gn +++ b/BUILD.gn @@ -2363,6 +2363,8 @@ v8_source_set("v8_initializers") { "src/interpreter/interpreter-generator.h", "src/interpreter/interpreter-intrinsics-generator.cc", "src/interpreter/interpreter-intrinsics-generator.h", + "src/numbers/integer-literal-inl.h", + "src/numbers/integer-literal.h", ] if (v8_enable_webassembly) { @@ -4854,6 +4856,8 @@ v8_source_set("torque_base") { visibility = [ ":*" ] # Only targets in this file can depend on this. sources = [ + "src/numbers/integer-literal-inl.h", + "src/numbers/integer-literal.h", "src/torque/ast.h", "src/torque/cc-generator.cc", "src/torque/cc-generator.h", diff --git a/src/bigint/bigint.h b/src/bigint/bigint.h index 300229c97d..f366952762 100644 --- a/src/bigint/bigint.h +++ b/src/bigint/bigint.h @@ -301,6 +301,10 @@ class Processor { // Z := the contents of {accumulator}. // Assume that this leaves {accumulator} in unusable state. Status FromString(RWDigits Z, FromStringAccumulator* accumulator); + + protected: + // Use {Destroy} or {Destroyer} instead of the destructor directly. + ~Processor() = default; }; inline int AddResultLength(int x_length, int y_length) { @@ -418,13 +422,13 @@ class FromStringAccumulator { : max_digits_(std::max(max_digits, kStackParts)) {} // Step 2: Call this method to read all characters. - // {Char} should be a character type, such as uint8_t or uint16_t. - // {end} should be one past the last character (i.e. {start == end} would - // indicate an empty string). - // Returns the current position when an invalid character is encountered. - template - ALWAYS_INLINE const Char* Parse(const Char* start, const Char* end, - digit_t radix); + // {CharIt} should be a forward iterator and + // std::iterator_traits::value_type shall be a character type, such as + // uint8_t or uint16_t. {end} should be one past the last character (i.e. + // {start == end} would indicate an empty string). Returns the current + // position when an invalid character is encountered. + template + ALWAYS_INLINE CharIt Parse(CharIt start, CharIt end, digit_t radix); // Step 3: Check if a result is available, and determine its required // allocation size (guaranteed to be <= max_digits passed to the constructor). @@ -434,14 +438,13 @@ class FromStringAccumulator { } // Step 4: Use BigIntProcessor::FromString() to retrieve the result into an - // {RWDigits} struct allocated for the size returned by step 2. + // {RWDigits} struct allocated for the size returned by step 3. private: friend class ProcessorImpl; - template - ALWAYS_INLINE const Char* ParsePowerTwo(const Char* start, const Char* end, - digit_t radix); + template + ALWAYS_INLINE CharIt ParsePowerTwo(CharIt start, CharIt end, digit_t radix); ALWAYS_INLINE bool AddPart(digit_t multiplier, digit_t part, bool is_last); ALWAYS_INLINE bool AddPart(digit_t part); @@ -491,10 +494,9 @@ static constexpr uint8_t kCharValue[] = { // A space- and time-efficient way to map {2,4,8,16,32} to {1,2,3,4,5}. static constexpr uint8_t kCharBits[] = {1, 2, 3, 0, 4, 0, 0, 0, 5}; -template -const Char* FromStringAccumulator::ParsePowerTwo(const Char* current, - const Char* end, - digit_t radix) { +template +CharIt FromStringAccumulator::ParsePowerTwo(CharIt current, CharIt end, + digit_t radix) { radix_ = static_cast(radix); const int char_bits = kCharBits[radix >> 2]; int bits_left; @@ -528,11 +530,10 @@ const Char* FromStringAccumulator::ParsePowerTwo(const Char* current, return current; } -template -const Char* FromStringAccumulator::Parse(const Char* start, const Char* end, - digit_t radix) { +template +CharIt FromStringAccumulator::Parse(CharIt start, CharIt end, digit_t radix) { BIGINT_H_DCHECK(2 <= radix && radix <= 36); - const Char* current = start; + CharIt current = start; #if !HAVE_BUILTIN_MUL_OVERFLOW const digit_t kMaxMultiplier = (~digit_t{0}) / radix; #endif diff --git a/src/bigint/tostring.cc b/src/bigint/tostring.cc index 0447ce0c22..3f1a277c3d 100644 --- a/src/bigint/tostring.cc +++ b/src/bigint/tostring.cc @@ -127,6 +127,7 @@ class ToStringFormatter { out_end_(out + chars_available), out_(out_end_), processor_(processor) { + digits_.Normalize(); DCHECK(chars_available >= ToStringResultLength(digits_, radix_, sign_)); } diff --git a/src/builtins/array-join.tq b/src/builtins/array-join.tq index b87827442f..c88a0c2800 100644 --- a/src/builtins/array-join.tq +++ b/src/builtins/array-join.tq @@ -548,7 +548,7 @@ macro JoinStackPopInline(implicit context: Context)(receiver: JSReceiver): // Builtin call was not nested (receiver is the first entry) and // did not contain other nested arrays that expanded the stack. if (stack.objects[0] == receiver && len == kMinJoinStackSize) { - StoreFixedArrayElement(stack, 0, TheHole, SKIP_WRITE_BARRIER); + stack.objects[0] = TheHole; } else deferred { JoinStackPop(stack, receiver); diff --git a/src/builtins/base.tq b/src/builtins/base.tq index 00d21c1470..bdeac88b67 100644 --- a/src/builtins/base.tq +++ b/src/builtins/base.tq @@ -27,6 +27,8 @@ type void; type never; +type IntegerLiteral constexpr 'IntegerLiteral'; + type Tagged generates 'TNode' constexpr 'MaybeObject'; type StrongTagged extends Tagged generates 'TNode' constexpr 'Object'; @@ -613,7 +615,7 @@ transitioning macro ToIntegerImpl(implicit context: Context)(input: JSAny): if (Float64IsNaN(value)) return SmiConstant(0); value = math::Float64Trunc(value); // ToInteger normalizes -0 to +0. - if (value == 0.0) return SmiConstant(0); + if (value == 0) return SmiConstant(0); const result = ChangeFloat64ToTagged(value); dcheck(IsNumberNormalized(result)); return result; @@ -989,6 +991,38 @@ extern operator '==' macro ConstexprInt32Equal( extern operator '!=' macro ConstexprInt32NotEqual( constexpr int32, constexpr int32): constexpr bool; +// IntegerLiteral overloads +extern macro ConstexprIntegerLiteralToInt31(constexpr IntegerLiteral): + constexpr int31; +extern macro ConstexprIntegerLiteralToInt32(constexpr IntegerLiteral): + constexpr int32; +extern macro ConstexprIntegerLiteralToUint32(constexpr IntegerLiteral): + constexpr uint32; +extern macro ConstexprIntegerLiteralToUint64(constexpr IntegerLiteral): + constexpr uint64; +extern macro ConstexprIntegerLiteralToIntptr(constexpr IntegerLiteral): + constexpr intptr; +extern macro ConstexprIntegerLiteralToUintptr(constexpr IntegerLiteral): + constexpr uintptr; +extern macro ConstexprIntegerLiteralToInt8(constexpr IntegerLiteral): + constexpr int8; +extern macro ConstexprIntegerLiteralToUint8(constexpr IntegerLiteral): + constexpr uint8; +extern macro ConstexprIntegerLiteralToFloat64(constexpr IntegerLiteral): + constexpr float64; + +extern operator '==' macro ConstexprIntegerLiteralEqual( + constexpr IntegerLiteral, constexpr IntegerLiteral): constexpr bool; +extern operator '+' macro ConstexprIntegerLiteralAdd( + constexpr IntegerLiteral, + constexpr IntegerLiteral): constexpr IntegerLiteral; +extern operator '<<' macro ConstexprIntegerLiteralLeftShift( + constexpr IntegerLiteral, + constexpr IntegerLiteral): constexpr IntegerLiteral; +extern operator '|' macro ConstexprIntegerLiteralBitwiseOr( + constexpr IntegerLiteral, + constexpr IntegerLiteral): constexpr IntegerLiteral; + extern operator '==' macro Word32Equal(int32, int32): bool; extern operator '==' macro Word32Equal(uint32, uint32): bool; extern operator '!=' macro Word32NotEqual(int32, int32): bool; @@ -1178,19 +1212,29 @@ extern macro IntPtrConstant(constexpr int32): intptr; extern macro Uint16Constant(constexpr uint16): uint16; extern macro Int32Constant(constexpr int31): int31; extern macro Int32Constant(constexpr int32): int32; +macro Int32Constant(i: constexpr IntegerLiteral): int32 { + return Int32Constant(ConstexprIntegerLiteralToInt32(i)); +} extern macro Int64Constant(constexpr int64): int64; extern macro Uint64Constant(constexpr uint64): uint64; extern macro Float64Constant(constexpr int32): float64; extern macro Float64Constant(constexpr float64): float64; +extern macro Float64Constant(constexpr IntegerLiteral): float64; extern macro SmiConstant(constexpr int31): Smi; extern macro SmiConstant(constexpr Smi): Smi; extern macro SmiConstant(constexpr MessageTemplate): Smi; extern macro SmiConstant(constexpr bool): Smi; extern macro SmiConstant(constexpr uint32): Smi; +macro SmiConstant(il: constexpr IntegerLiteral): Smi { + return SmiConstant(ConstexprIntegerLiteralToInt31(il)); +} extern macro BoolConstant(constexpr bool): bool; extern macro StringConstant(constexpr string): String; extern macro IntPtrConstant(constexpr ContextSlot): ContextSlot; extern macro IntPtrConstant(constexpr intptr): intptr; +macro IntPtrConstant(il: constexpr IntegerLiteral): intptr { + return IntPtrConstant(ConstexprIntegerLiteralToIntptr(il)); +} extern macro PointerConstant(constexpr RawPtr): RawPtr; extern macro SingleCharacterStringConstant(constexpr string): String; extern macro Float64SilenceNaN(float64): float64; diff --git a/src/builtins/convert.tq b/src/builtins/convert.tq index 64c81ca572..23995e50e3 100644 --- a/src/builtins/convert.tq +++ b/src/builtins/convert.tq @@ -4,6 +4,59 @@ intrinsic %FromConstexpr(b: From): To; macro FromConstexpr(o: From): To; +// Conversions for IntegerLiteral +FromConstexpr(i: constexpr IntegerLiteral): + intptr { + return ConstexprIntegerLiteralToIntptr(i); +} +FromConstexpr(i: constexpr IntegerLiteral): + uintptr { + return ConstexprIntegerLiteralToUintptr(i); +} +FromConstexpr(i: constexpr IntegerLiteral): + int32 { + return ConstexprIntegerLiteralToInt32(i); +} +FromConstexpr(i: constexpr IntegerLiteral): + uint32 { + return ConstexprIntegerLiteralToUint32(i); +} +FromConstexpr(i: constexpr IntegerLiteral): + int31 { + return ConstexprIntegerLiteralToInt31(i); +} +FromConstexpr(i: constexpr IntegerLiteral): + int8 { + return ConstexprIntegerLiteralToInt8(i); +} +FromConstexpr(i: constexpr IntegerLiteral): + uint8 { + return ConstexprIntegerLiteralToUint8(i); +} +FromConstexpr(i: constexpr IntegerLiteral): + uint64 { + return ConstexprIntegerLiteralToUint64(i); +} +FromConstexpr( + i: constexpr IntegerLiteral): constexpr int31 { + return ConstexprIntegerLiteralToInt31(i); +} +FromConstexpr( + i: constexpr IntegerLiteral): constexpr int32 { + return ConstexprIntegerLiteralToInt32(i); +} +FromConstexpr(i: constexpr IntegerLiteral): + Number { + return NumberConstant(ConstexprIntegerLiteralToFloat64(i)); +} +FromConstexpr(i: constexpr IntegerLiteral): Smi { + return Convert(ConstexprIntegerLiteralToInt31(i)); +} +FromConstexpr(i: constexpr IntegerLiteral): + char8 { + return %RawDownCast(FromConstexpr(i)); +} + FromConstexpr(i: constexpr int31): int31 { return %FromConstexpr(i); } @@ -325,6 +378,10 @@ Convert(n: Number): intptr { Convert(v: int32): bint { return IntPtrToBInt(Convert(v)); } +FromConstexpr(v: constexpr IntegerLiteral): + float64 { + return ConstexprIntegerLiteralToFloat64(v); +} extern macro IntPtrToBInt(intptr): bint; Convert(v: intptr): bint { return IntPtrToBInt(v); diff --git a/src/builtins/number.tq b/src/builtins/number.tq index 4136b9a693..c68a32c678 100644 --- a/src/builtins/number.tq +++ b/src/builtins/number.tq @@ -90,7 +90,7 @@ macro NumberToStringSmi(x: int32, radix: int32): String labels Slow { // Calculate length and pre-allocate the result string. let temp: int32 = n; - let length: int32 = isNegative ? 1 : 0; + let length: int32 = isNegative ? Convert(1) : Convert(0); while (temp > 0) { temp = temp / radix; length = length + 1; @@ -277,7 +277,7 @@ transitioning builtin ParseInt(implicit context: Context)( // the runtime for the range [0,1[ because the result could be -0. const kMaxAbsValue: float64 = 2147483648.0; const absInput: float64 = math::Float64Abs(asFloat64); - if (absInput < kMaxAbsValue && absInput >= 1) goto Int32(asInt32); + if (absInput < kMaxAbsValue && absInput >= 1.0) goto Int32(asInt32); goto CallRuntime; } case (s: String): { @@ -690,7 +690,7 @@ builtin Negate(implicit context: Context)(value: JSAny): Numeric { } label Smi(s: Smi) { return SmiMul(s, -1); } label HeapNumber(h: HeapNumber) { - return AllocateHeapNumberWithValue(Convert(h) * -1); + return AllocateHeapNumberWithValue(Convert(h) * -1.0); } label BigInt(b: BigInt) { tail runtime::BigIntUnaryOp( context, b, SmiTag(Operation::kNegate)); diff --git a/src/builtins/string-repeat.tq b/src/builtins/string-repeat.tq index b5ced876b7..0c2d68861e 100644 --- a/src/builtins/string-repeat.tq +++ b/src/builtins/string-repeat.tq @@ -55,7 +55,7 @@ transitioning javascript builtin StringPrototypeRepeat( // 4. If n < 0, throw a RangeError exception. // 5. If n is +∞, throw a RangeError exception. - if (n == V8_INFINITY || n < 0.0) goto InvalidCount; + if (n == V8_INFINITY || n < 0) goto InvalidCount; // 6. If n is 0, return the empty String. if (s.length_uint32 == 0) goto EmptyString; diff --git a/src/builtins/torque-internal.tq b/src/builtins/torque-internal.tq index 8765a7b8ac..ad21e24ace 100644 --- a/src/builtins/torque-internal.tq +++ b/src/builtins/torque-internal.tq @@ -105,6 +105,10 @@ struct Slice { return this.TryAtIndex(Convert(index)) otherwise unreachable; } + macro AtIndex(index: constexpr IntegerLiteral): Reference { + return this.AtIndex(FromConstexpr(index)); + } + macro AtIndex(index: constexpr int31): Reference { const i: intptr = Convert(index); return this.TryAtIndex(i) otherwise unreachable; diff --git a/src/codegen/code-stub-assembler.cc b/src/codegen/code-stub-assembler.cc index 360ecc3a1e..a229713001 100644 --- a/src/codegen/code-stub-assembler.cc +++ b/src/codegen/code-stub-assembler.cc @@ -17,6 +17,7 @@ #include "src/heap/heap-inl.h" // For MemoryChunk. TODO(jkummerow): Drop. #include "src/heap/memory-chunk.h" #include "src/logging/counters.h" +#include "src/numbers/integer-literal-inl.h" #include "src/objects/api-callbacks.h" #include "src/objects/cell.h" #include "src/objects/descriptor-array.h" @@ -14863,6 +14864,19 @@ void CodeStubAssembler::Print(const char* prefix, CallRuntime(Runtime::kDebugPrint, NoContextConstant(), arg); } +IntegerLiteral CodeStubAssembler::ConstexprIntegerLiteralAdd( + const IntegerLiteral& lhs, const IntegerLiteral& rhs) { + return lhs + rhs; +} +IntegerLiteral CodeStubAssembler::ConstexprIntegerLiteralLeftShift( + const IntegerLiteral& lhs, const IntegerLiteral& rhs) { + return lhs << rhs; +} +IntegerLiteral CodeStubAssembler::ConstexprIntegerLiteralBitwiseOr( + const IntegerLiteral& lhs, const IntegerLiteral& rhs) { + return lhs | rhs; +} + void CodeStubAssembler::PerformStackCheck(TNode context) { Label ok(this), stack_check_interrupt(this, Label::kDeferred); diff --git a/src/codegen/code-stub-assembler.h b/src/codegen/code-stub-assembler.h index 883deb2fa1..a5688aed04 100644 --- a/src/codegen/code-stub-assembler.h +++ b/src/codegen/code-stub-assembler.h @@ -13,6 +13,7 @@ #include "src/common/globals.h" #include "src/common/message-template.h" #include "src/compiler/code-assembler.h" +#include "src/numbers/integer-literal.h" #include "src/objects/arguments.h" #include "src/objects/bigint.h" #include "src/objects/cell.h" @@ -3771,6 +3772,45 @@ class V8_EXPORT_PRIVATE CodeStubAssembler } bool ConstexprBoolNot(bool value) { return !value; } + int31_t ConstexprIntegerLiteralToInt31(const IntegerLiteral& i) { + return int31_t(i.To()); + } + int32_t ConstexprIntegerLiteralToInt32(const IntegerLiteral& i) { + return i.To(); + } + uint32_t ConstexprIntegerLiteralToUint32(const IntegerLiteral& i) { + return i.To(); + } + int8_t ConstexprIntegerLiteralToInt8(const IntegerLiteral& i) { + return i.To(); + } + uint8_t ConstexprIntegerLiteralToUint8(const IntegerLiteral& i) { + return i.To(); + } + uint64_t ConstexprIntegerLiteralToUint64(const IntegerLiteral& i) { + return i.To(); + } + intptr_t ConstexprIntegerLiteralToIntptr(const IntegerLiteral& i) { + return i.To(); + } + uintptr_t ConstexprIntegerLiteralToUintptr(const IntegerLiteral& i) { + return i.To(); + } + double ConstexprIntegerLiteralToFloat64(const IntegerLiteral& i) { + int64_t i_value = i.To(); + double d_value = static_cast(i_value); + CHECK_EQ(i_value, static_cast(d_value)); + return d_value; + } + bool ConstexprIntegerLiteralEqual(IntegerLiteral lhs, IntegerLiteral rhs) { + return lhs == rhs; + } + IntegerLiteral ConstexprIntegerLiteralAdd(const IntegerLiteral& lhs, + const IntegerLiteral& rhs); + IntegerLiteral ConstexprIntegerLiteralLeftShift(const IntegerLiteral& lhs, + const IntegerLiteral& rhs); + IntegerLiteral ConstexprIntegerLiteralBitwiseOr(const IntegerLiteral& lhs, + const IntegerLiteral& rhs); bool ConstexprInt31Equal(int31_t a, int31_t b) { return a == b; } bool ConstexprInt31NotEqual(int31_t a, int31_t b) { return a != b; } diff --git a/src/numbers/integer-literal-inl.h b/src/numbers/integer-literal-inl.h new file mode 100644 index 0000000000..561f9880de --- /dev/null +++ b/src/numbers/integer-literal-inl.h @@ -0,0 +1,43 @@ +// Copyright 2022 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef V8_NUMBERS_INTEGER_LITERAL_INL_H_ +#define V8_NUMBERS_INTEGER_LITERAL_INL_H_ + +#include "src/numbers/integer-literal.h" + +namespace v8 { +namespace internal { + +inline std::string IntegerLiteral::ToString() const { + if (negative_) return std::string("-") + std::to_string(absolute_value_); + return std::to_string(absolute_value_); +} + +inline IntegerLiteral operator<<(const IntegerLiteral& x, + const IntegerLiteral& y) { + DCHECK(!y.is_negative()); + DCHECK_LT(y.absolute_value(), sizeof(uint64_t) * kBitsPerByte); + return IntegerLiteral(x.is_negative(), x.absolute_value() + << y.absolute_value()); +} + +inline IntegerLiteral operator+(const IntegerLiteral& x, + const IntegerLiteral& y) { + if (x.is_negative() == y.is_negative()) { + DCHECK_GE(x.absolute_value() + y.absolute_value(), x.absolute_value()); + return IntegerLiteral(x.is_negative(), + x.absolute_value() + y.absolute_value()); + } + if (x.absolute_value() >= y.absolute_value()) { + return IntegerLiteral(x.is_negative(), + x.absolute_value() - y.absolute_value()); + } + return IntegerLiteral(!x.is_negative(), + y.absolute_value() - x.absolute_value()); +} + +} // namespace internal +} // namespace v8 +#endif // V8_NUMBERS_INTEGER_LITERAL_INL_H_ diff --git a/src/numbers/integer-literal.h b/src/numbers/integer-literal.h new file mode 100644 index 0000000000..5ac3ae76ee --- /dev/null +++ b/src/numbers/integer-literal.h @@ -0,0 +1,106 @@ +// Copyright 2022 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef V8_NUMBERS_INTEGER_LITERAL_H_ +#define V8_NUMBERS_INTEGER_LITERAL_H_ + +#include "src/base/optional.h" +#include "src/common/globals.h" + +namespace v8 { +namespace internal { + +class IntegerLiteral { + public: + IntegerLiteral(bool negative, uint64_t absolute_value) + : negative_(negative), absolute_value_(absolute_value) { + if (absolute_value == 0) negative_ = false; + } + + template + explicit IntegerLiteral(T value) : IntegerLiteral(value, true) {} + + bool is_negative() const { return negative_; } + uint64_t absolute_value() const { return absolute_value_; } + + template + bool IsRepresentableAs() const { + static_assert(std::is_integral::value, "Integral type required"); + static_assert(sizeof(T) <= sizeof(uint64_t), + "Types with more than 64 bits are not supported"); + return Compare(IntegerLiteral(std::numeric_limits::min(), false)) >= 0 && + Compare(IntegerLiteral(std::numeric_limits::max(), false)) <= 0; + } + + template + T To() const { + static_assert(std::is_integral::value, "Integral type required"); + DCHECK(IsRepresentableAs()); + uint64_t v = absolute_value_; + if (negative_) v = ~v + 1; + return static_cast(v); + } + + template + base::Optional TryTo() const { + static_assert(std::is_integral::value, "Integral type required"); + if (!IsRepresentableAs()) return base::nullopt; + return To(); + } + + int Compare(const IntegerLiteral& other) const { + if (absolute_value_ == other.absolute_value_) { + if (absolute_value_ == 0 || negative_ == other.negative_) return 0; + return negative_ ? -1 : 1; + } else if (absolute_value_ < other.absolute_value_) { + return other.negative_ ? 1 : -1; + } else { + return negative_ ? -1 : 1; + } + } + + std::string ToString() const; + + private: + template + explicit IntegerLiteral(T value, bool perform_dcheck) : negative_(false) { + static_assert(std::is_integral::value, "Integral type required"); + absolute_value_ = static_cast(value); + if (value < T(0)) { + negative_ = true; + absolute_value_ = ~absolute_value_ + 1; + } + if (perform_dcheck) DCHECK_EQ(To(), value); + } + + bool negative_; + uint64_t absolute_value_; +}; + +inline bool operator==(const IntegerLiteral& x, const IntegerLiteral& y) { + return x.Compare(y) == 0; +} + +inline bool operator!=(const IntegerLiteral& x, const IntegerLiteral& y) { + return x.Compare(y) != 0; +} + +inline std::ostream& operator<<(std::ostream& stream, + const IntegerLiteral& literal) { + return stream << literal.ToString(); +} + +inline IntegerLiteral operator|(const IntegerLiteral& x, + const IntegerLiteral& y) { + DCHECK(!x.is_negative()); + DCHECK(!y.is_negative()); + return IntegerLiteral(false, x.absolute_value() | y.absolute_value()); +} + +IntegerLiteral operator<<(const IntegerLiteral& x, const IntegerLiteral& y); +IntegerLiteral operator+(const IntegerLiteral& x, const IntegerLiteral& y); + +} // namespace internal +} // namespace v8 +#endif // V8_NUMBERS_INTEGER_LITERAL_H_ diff --git a/src/objects/descriptor-array-inl.h b/src/objects/descriptor-array-inl.h index 387ae8d276..3756fafa33 100644 --- a/src/objects/descriptor-array-inl.h +++ b/src/objects/descriptor-array-inl.h @@ -5,12 +5,11 @@ #ifndef V8_OBJECTS_DESCRIPTOR_ARRAY_INL_H_ #define V8_OBJECTS_DESCRIPTOR_ARRAY_INL_H_ -#include "src/objects/descriptor-array.h" - #include "src/execution/isolate.h" #include "src/handles/maybe-handles-inl.h" #include "src/heap/heap-write-barrier.h" #include "src/heap/heap.h" +#include "src/objects/descriptor-array.h" #include "src/objects/field-type.h" #include "src/objects/heap-object-inl.h" #include "src/objects/lookup-cache-inl.h" diff --git a/src/objects/fixed-array-inl.h b/src/objects/fixed-array-inl.h index b9e348f7fd..5dea891511 100644 --- a/src/objects/fixed-array-inl.h +++ b/src/objects/fixed-array-inl.h @@ -5,13 +5,12 @@ #ifndef V8_OBJECTS_FIXED_ARRAY_INL_H_ #define V8_OBJECTS_FIXED_ARRAY_INL_H_ -#include "src/objects/fixed-array.h" - #include "src/handles/handles-inl.h" #include "src/heap/heap-write-barrier-inl.h" #include "src/numbers/conversions.h" #include "src/objects/bigint.h" #include "src/objects/compressed-slots.h" +#include "src/objects/fixed-array.h" #include "src/objects/map.h" #include "src/objects/maybe-object-inl.h" #include "src/objects/objects-inl.h" diff --git a/src/objects/turbofan-types.tq b/src/objects/turbofan-types.tq index f1cab8c491..147927f61c 100644 --- a/src/objects/turbofan-types.tq +++ b/src/objects/turbofan-types.tq @@ -80,7 +80,7 @@ class TurbofanOtherNumberConstantType extends TurbofanType { } macro IsMinusZero(x: float64): bool { - return x == 0 && 1 / x < 0; + return x == 0 && 1.0 / x < 0; } macro TestTurbofanBitsetType( @@ -94,13 +94,13 @@ macro TestTurbofanBitsetType( if (IsInteger(value)) { if (IsMinusZero(valueF)) { return bitsetLow.minus_zero; - } else if (valueF < Convert(-0x80000000)) { + } else if (valueF < -0x80000000) { return bitsetLow.other_number; } else if (valueF < -0x40000000) { return bitsetLow.other_signed32; } else if (valueF < 0) { return bitsetLow.negative31; - } else if (valueF < Convert(0x40000000)) { + } else if (valueF < 0x40000000) { return bitsetLow.unsigned30; } else if (valueF < 0x80000000) { return bitsetLow.other_unsigned31; diff --git a/src/torque/ast.h b/src/torque/ast.h index a4ccefb304..d80993e38f 100644 --- a/src/torque/ast.h +++ b/src/torque/ast.h @@ -14,6 +14,7 @@ #include #include "src/base/optional.h" +#include "src/numbers/integer-literal.h" #include "src/torque/constants.h" #include "src/torque/source-positions.h" #include "src/torque/utils.h" @@ -33,7 +34,8 @@ namespace torque { V(ConditionalExpression) \ V(IdentifierExpression) \ V(StringLiteralExpression) \ - V(NumberLiteralExpression) \ + V(IntegerLiteralExpression) \ + V(FloatingPointLiteralExpression) \ V(FieldAccessExpression) \ V(ElementAccessExpression) \ V(DereferenceExpression) \ @@ -459,16 +461,28 @@ struct StringLiteralExpression : Expression { std::string literal; }; -struct NumberLiteralExpression : Expression { - DEFINE_AST_NODE_LEAF_BOILERPLATE(NumberLiteralExpression) - NumberLiteralExpression(SourcePosition pos, double number) - : Expression(kKind, pos), number(number) {} +struct IntegerLiteralExpression : Expression { + DEFINE_AST_NODE_LEAF_BOILERPLATE(IntegerLiteralExpression) + IntegerLiteralExpression(SourcePosition pos, IntegerLiteral value) + : Expression(kKind, pos), value(std::move(value)) {} void VisitAllSubExpressions(VisitCallback callback) override { callback(this); } - double number; + IntegerLiteral value; +}; + +struct FloatingPointLiteralExpression : Expression { + DEFINE_AST_NODE_LEAF_BOILERPLATE(FloatingPointLiteralExpression) + FloatingPointLiteralExpression(SourcePosition pos, double value) + : Expression(kKind, pos), value(value) {} + + void VisitAllSubExpressions(VisitCallback callback) override { + callback(this); + } + + double value; }; struct ElementAccessExpression : LocationExpression { diff --git a/src/torque/constants.h b/src/torque/constants.h index 63cddf6e0a..325c6dea8f 100644 --- a/src/torque/constants.h +++ b/src/torque/constants.h @@ -67,6 +67,8 @@ static const char* const FLOAT64_OR_HOLE_TYPE_STRING = "float64_or_hole"; static const char* const CONST_INT31_TYPE_STRING = "constexpr int31"; static const char* const CONST_INT32_TYPE_STRING = "constexpr int32"; static const char* const CONST_FLOAT64_TYPE_STRING = "constexpr float64"; +static const char* const INTEGER_LITERAL_TYPE_STRING = + "constexpr IntegerLiteral"; static const char* const TORQUE_INTERNAL_NAMESPACE_STRING = "torque_internal"; static const char* const MUTABLE_REFERENCE_TYPE_STRING = "MutableReference"; static const char* const CONST_REFERENCE_TYPE_STRING = "ConstReference"; diff --git a/src/torque/earley-parser.cc b/src/torque/earley-parser.cc index f99424b1a6..adb7e77153 100644 --- a/src/torque/earley-parser.cc +++ b/src/torque/earley-parser.cc @@ -127,6 +127,7 @@ LexerResult Lexer::RunLexer(const std::string& input) { while (pos != end) { token_start = pos; Symbol* symbol = MatchToken(&pos, end); + DCHECK_IMPLIES(symbol != nullptr, pos != token_start); InputPosition token_end = pos; line_column_tracker.Advance(token_start, token_end); if (!symbol) { diff --git a/src/torque/earley-parser.h b/src/torque/earley-parser.h index bca3cf5fb1..6be44a619b 100644 --- a/src/torque/earley-parser.h +++ b/src/torque/earley-parser.h @@ -44,6 +44,8 @@ enum class ParseResultHolderBase::TypeId { kStdString, kBool, kInt32, + kDouble, + kIntegerLiteral, kStdVectorOfString, kExpressionPtr, kIdentifierPtr, diff --git a/src/torque/implementation-visitor.cc b/src/torque/implementation-visitor.cc index e515c0ae54..604681bc8e 100644 --- a/src/torque/implementation-visitor.cc +++ b/src/torque/implementation-visitor.cc @@ -10,6 +10,7 @@ #include "src/base/optional.h" #include "src/common/globals.h" +#include "src/numbers/integer-literal-inl.h" #include "src/torque/cc-generator.h" #include "src/torque/cfg.h" #include "src/torque/constants.h" @@ -182,6 +183,7 @@ void ImplementationVisitor::BeginDebugMacrosFile() { header << "#ifndef " << kHeaderDefine << "\n"; header << "#define " << kHeaderDefine << "\n\n"; header << "#include \"tools/debug_helper/debug-helper-internal.h\"\n"; + header << "#include \"src/numbers/integer-literal.h\"\n"; header << "\n"; header << "namespace v8 {\n" @@ -943,22 +945,18 @@ VisitResult ImplementationVisitor::Visit(AssignmentExpression* expr) { return scope.Yield(assignment_value); } -VisitResult ImplementationVisitor::Visit(NumberLiteralExpression* expr) { +VisitResult ImplementationVisitor::Visit(FloatingPointLiteralExpression* expr) { const Type* result_type = TypeOracle::GetConstFloat64Type(); - if (expr->number >= std::numeric_limits::min() && - expr->number <= std::numeric_limits::max()) { - int32_t i = static_cast(expr->number); - if (i == expr->number) { - if ((i >> 30) == (i >> 31)) { - result_type = TypeOracle::GetConstInt31Type(); - } else { - result_type = TypeOracle::GetConstInt32Type(); - } - } - } std::stringstream str; str << std::setprecision(std::numeric_limits::digits10 + 1) - << expr->number; + << expr->value; + return VisitResult{result_type, str.str()}; +} + +VisitResult ImplementationVisitor::Visit(IntegerLiteralExpression* expr) { + const Type* result_type = TypeOracle::GetIntegerLiteralType(); + std::stringstream str; + str << "IntegerLiteral(" << expr->value << ")"; return VisitResult{result_type, str.str()}; } @@ -2848,7 +2846,9 @@ VisitResult ImplementationVisitor::GenerateCall( // If we're currently generating a C++ macro and it's calling another macro, // then we need to make sure that we also generate C++ code for the called // macro within the same -inl.inc file. - if (output_type_ == OutputType::kCC && !inline_macro) { + if ((output_type_ == OutputType::kCC || + output_type_ == OutputType::kCCDebug) && + !inline_macro) { if (auto* torque_macro = TorqueMacro::DynamicCast(macro)) { auto* streams = CurrentFileStreams::Get(); SourceId file = streams ? streams->file : SourceId::Invalid(); @@ -2862,14 +2862,32 @@ VisitResult ImplementationVisitor::GenerateCall( std::stringstream result; result << "("; bool first = true; - if (auto* extern_macro = ExternMacro::DynamicCast(macro)) { - result << extern_macro->external_assembler_name() << "(state_)." - << extern_macro->ExternalName() << "("; - } else { - result << macro->ExternalName() << "(state_"; - first = false; + switch (output_type_) { + case OutputType::kCSA: { + if (auto* extern_macro = ExternMacro::DynamicCast(macro)) { + result << extern_macro->external_assembler_name() << "(state_)." + << extern_macro->ExternalName() << "("; + } else { + result << macro->ExternalName() << "(state_"; + first = false; + } + break; + } + case OutputType::kCC: { + auto* extern_macro = ExternMacro::DynamicCast(macro); + CHECK_NOT_NULL(extern_macro); + result << extern_macro->CCName() << "("; + break; + } + case OutputType::kCCDebug: { + auto* extern_macro = ExternMacro::DynamicCast(macro); + CHECK_NOT_NULL(extern_macro); + result << extern_macro->CCDebugName() << "(accessor"; + first = false; + break; + } } - for (VisitResult arg : arguments.parameters) { + for (VisitResult arg : converted_arguments) { DCHECK(!arg.IsOnStack()); if (!first) { result << ", "; diff --git a/src/torque/implementation-visitor.h b/src/torque/implementation-visitor.h index 8ebb72cc2e..36c9ca452e 100644 --- a/src/torque/implementation-visitor.h +++ b/src/torque/implementation-visitor.h @@ -555,7 +555,8 @@ class ImplementationVisitor { VisitResult Visit(IncrementDecrementExpression* expr); VisitResult Visit(AssignmentExpression* expr); VisitResult Visit(StringLiteralExpression* expr); - VisitResult Visit(NumberLiteralExpression* expr); + VisitResult Visit(FloatingPointLiteralExpression* expr); + VisitResult Visit(IntegerLiteralExpression* expr); VisitResult Visit(AssumeTypeImpossibleExpression* expr); VisitResult Visit(TryLabelExpression* expr); VisitResult Visit(StatementExpression* expr); diff --git a/src/torque/runtime-macro-shims.h b/src/torque/runtime-macro-shims.h index 951aa47a62..b1cf681923 100644 --- a/src/torque/runtime-macro-shims.h +++ b/src/torque/runtime-macro-shims.h @@ -10,6 +10,8 @@ #include +#include "src/numbers/integer-literal.h" + namespace v8 { namespace internal { @@ -34,6 +36,15 @@ inline uintptr_t Unsigned(intptr_t s) { return static_cast(s); } #endif inline bool Word32Equal(uint32_t a, uint32_t b) { return a == b; } inline bool Word32NotEqual(uint32_t a, uint32_t b) { return a != b; } +inline int32_t ConstexprIntegerLiteralToInt32(const IntegerLiteral& i) { + return i.To(); +} +inline int31_t ConstexprIntegerLiteralToInt31(const IntegerLiteral& i) { + return int31_t(ConstexprIntegerLiteralToInt32(i)); +} +inline intptr_t ConstexprIntegerLiteralToIntptr(const IntegerLiteral& i) { + return i.To(); +} } // namespace CodeStubAssembler } // namespace TorqueRuntimeMacroShims diff --git a/src/torque/torque-parser.cc b/src/torque/torque-parser.cc index a2dfa43e6a..4df9e36102 100644 --- a/src/torque/torque-parser.cc +++ b/src/torque/torque-parser.cc @@ -92,6 +92,12 @@ template <> V8_EXPORT_PRIVATE const ParseResultTypeId ParseResultHolder::id = ParseResultTypeId::kInt32; template <> +V8_EXPORT_PRIVATE const ParseResultTypeId ParseResultHolder::id = + ParseResultTypeId::kDouble; +template <> +V8_EXPORT_PRIVATE const ParseResultTypeId + ParseResultHolder::id = ParseResultTypeId::kIntegerLiteral; +template <> V8_EXPORT_PRIVATE const ParseResultTypeId ParseResultHolder>::id = ParseResultTypeId::kStdVectorOfString; @@ -865,8 +871,8 @@ bool ProcessIfAnnotation(ParseResultIterator* child_results) { return true; } -base::Optional MakeInt32(ParseResultIterator* child_results) { - std::string value = child_results->NextAs(); +base::Optional YieldInt32(ParseResultIterator* child_results) { + std::string value = child_results->matched_input().ToString(); size_t num_chars_converted = 0; int result = 0; try { @@ -883,6 +889,43 @@ base::Optional MakeInt32(ParseResultIterator* child_results) { return ParseResult{result}; } +base::Optional YieldDouble(ParseResultIterator* child_results) { + std::string value = child_results->matched_input().ToString(); + size_t num_chars_converted = 0; + double result = 0; + try { + result = std::stod(value, &num_chars_converted); + } catch (const std::out_of_range&) { + Error("double literal out-of-range"); + return ParseResult{result}; + } + // Tokenizer shouldn't have included extra trailing characters. + DCHECK_EQ(num_chars_converted, value.size()); + return ParseResult{result}; +} + +base::Optional YieldIntegerLiteral( + ParseResultIterator* child_results) { + std::string value = child_results->matched_input().ToString(); + // Consume a leading minus. + bool negative = false; + if (value.size() > 0 && value[0] == '-') { + negative = true; + value = value.substr(1); + } + uint64_t absolute_value; + try { + size_t parsed = 0; + absolute_value = std::stoull(value, &parsed, 0); + DCHECK_EQ(parsed, value.size()); + } catch (const std::invalid_argument&) { + Error("integer literal could not be parsed").Throw(); + } catch (const std::out_of_range&) { + Error("integer literal value out of range").Throw(); + } + return ParseResult(IntegerLiteral(negative, absolute_value)); +} + base::Optional MakeStringAnnotationParameter( ParseResultIterator* child_results) { std::string value = child_results->NextAs(); @@ -1903,29 +1946,17 @@ base::Optional MakeAssignmentExpression( return ParseResult{result}; } -base::Optional MakeNumberLiteralExpression( +base::Optional MakeFloatingPointLiteralExpression( ParseResultIterator* child_results) { - auto number = child_results->NextAs(); - // TODO(turbofan): Support 64bit literals. - // Meanwhile, we type it as constexpr float64 when out of int32 range. - double value = 0; - try { -#if defined(V8_OS_SOLARIS) - // stod() on Solaris does not currently support hex strings. Use strtol() - // specifically for hex literals until stod() support is available. - if (number.find("0x") == std::string::npos && - number.find("0X") == std::string::npos) { - value = std::stod(number); - } else { - value = static_cast(strtol(number.c_str(), nullptr, 0)); - } -#else - value = std::stod(number); -#endif // !defined(V8_OS_SOLARIS) - } catch (const std::out_of_range&) { - Error("double literal out-of-range").Throw(); - } - Expression* result = MakeNode(value); + auto value = child_results->NextAs(); + Expression* result = MakeNode(value); + return ParseResult{result}; +} + +base::Optional MakeIntegerLiteralExpression( + ParseResultIterator* child_results) { + auto value = child_results->NextAs(); + Expression* result = MakeNode(std::move(value)); return ParseResult{result}; } @@ -2085,8 +2116,19 @@ base::Optional MakeClassField(ParseResultIterator* child_results) { // Internally, an optional field is just an indexed field where the count // is zero or one. index = MakeNode( - *index, MakeNode(1), - MakeNode(0)); + *index, + MakeCall( + MakeNode("FromConstexpr"), + {MakeNode(std::vector{}, + MakeNode("intptr"), + std::vector{})}, + {MakeNode(IntegerLiteral(1))}, {}), + MakeCall( + MakeNode("FromConstexpr"), + {MakeNode(std::vector{}, + MakeNode("intptr"), + std::vector{})}, + {MakeNode(IntegerLiteral(0))}, {})); } index_info = ClassFieldIndexInfo{*index, optional}; } @@ -2205,12 +2247,24 @@ struct TorqueGrammar : Grammar { return false; } - static bool MatchDecimalLiteral(InputPosition* pos) { + static bool MatchIntegerLiteral(InputPosition* pos) { InputPosition current = *pos; bool found_digit = false; MatchString("-", ¤t); while (MatchChar(std::isdigit, ¤t)) found_digit = true; - MatchString(".", ¤t); + if (found_digit) { + *pos = current; + return true; + } + return false; + } + + static bool MatchFloatingPointLiteral(InputPosition* pos) { + InputPosition current = *pos; + bool found_digit = false; + MatchString("-", ¤t); + while (MatchChar(std::isdigit, ¤t)) found_digit = true; + if (!MatchString(".", ¤t)) return false; while (MatchChar(std::isdigit, ¤t)) found_digit = true; if (!found_digit) return false; *pos = current; @@ -2284,13 +2338,18 @@ struct TorqueGrammar : Grammar { // Result: std::string Symbol externalString = {Rule({&stringLiteral}, StringLiteralUnquoteAction)}; - // Result: std::string - Symbol decimalLiteral = { - Rule({Pattern(MatchDecimalLiteral)}, YieldMatchedInput), - Rule({Pattern(MatchHexLiteral)}, YieldMatchedInput)}; + // Result: IntegerLiteral + Symbol integerLiteral = { + Rule({Pattern(MatchIntegerLiteral)}, YieldIntegerLiteral), + Rule({Pattern(MatchHexLiteral)}, YieldIntegerLiteral)}; + + // Result: double + Symbol floatingPointLiteral = { + Rule({Pattern(MatchFloatingPointLiteral)}, YieldDouble)}; // Result: int32_t - Symbol int32Literal = {Rule({&decimalLiteral}, MakeInt32)}; + Symbol int32Literal = {Rule({Pattern(MatchIntegerLiteral)}, YieldInt32), + Rule({Pattern(MatchHexLiteral)}, YieldInt32)}; // Result: AnnotationParameter Symbol annotationParameter = { @@ -2509,7 +2568,8 @@ struct TorqueGrammar : Grammar { MakeReferenceFieldAccessExpression), Rule({&primaryExpression, Token("["), expression, Token("]")}, MakeElementAccessExpression), - Rule({&decimalLiteral}, MakeNumberLiteralExpression), + Rule({&integerLiteral}, MakeIntegerLiteralExpression), + Rule({&floatingPointLiteral}, MakeFloatingPointLiteralExpression), Rule({&stringLiteral}, MakeStringLiteralExpression), Rule({&simpleType, &initializerList}, MakeStructExpression), Rule({&newExpression}), diff --git a/src/torque/type-oracle.h b/src/torque/type-oracle.h index e184bc0f72..7bcbd6a77b 100644 --- a/src/torque/type-oracle.h +++ b/src/torque/type-oracle.h @@ -315,6 +315,10 @@ class TypeOracle : public ContextualClass { return Get().GetBuiltinType(CONST_FLOAT64_TYPE_STRING); } + static const Type* GetIntegerLiteralType() { + return Get().GetBuiltinType(INTEGER_LITERAL_TYPE_STRING); + } + static const Type* GetNeverType() { return Get().GetBuiltinType(NEVER_TYPE_STRING); } diff --git a/src/torque/type-visitor.cc b/src/torque/type-visitor.cc index aaae9e559c..7ca916f4ff 100644 --- a/src/torque/type-visitor.cc +++ b/src/torque/type-visitor.cc @@ -459,12 +459,12 @@ void TypeVisitor::VisitClassFieldsAndMethods( field_size * ResidueClass::Unknown()); if (auto literal = - NumberLiteralExpression::DynamicCast(field.index->expr)) { - size_t value = static_cast(literal->number); - if (value != literal->number) { - Error("non-integral array length").Position(field.pos); + IntegerLiteralExpression::DynamicCast(field.index->expr)) { + if (auto value = literal->value.TryTo()) { + field_size *= *value; + } else { + Error("Not a valid field index").Position(field.pos); } - field_size *= value; } else { field_size *= ResidueClass::Unknown(); } diff --git a/src/torque/types.cc b/src/torque/types.cc index c69986e407..9fa92d8723 100644 --- a/src/torque/types.cc +++ b/src/torque/types.cc @@ -850,7 +850,7 @@ void ClassType::GenerateSliceAccessor(size_t field_index) { if (field.offset.has_value()) { offset_expression = - MakeNode(static_cast(*field.offset)); + MakeNode(IntegerLiteral(*field.offset)); } else { const Field* previous = GetFieldPreceding(field_index); DCHECK_NOT_NULL(previous); @@ -879,8 +879,8 @@ void ClassType::GenerateSliceAccessor(size_t field_index) { std::tie(previous_element_size, std::ignore) = *SizeOf(previous->name_and_type.type); Expression* previous_element_size_expression = - MakeNode( - static_cast(previous_element_size)); + MakeNode( + IntegerLiteral(previous_element_size)); // previous.length Expression* previous_length_expression = MakeFieldAccessExpression( diff --git a/test/torque/test-torque.tq b/test/torque/test-torque.tq index 0b3be07e3b..661042399c 100644 --- a/test/torque/test-torque.tq +++ b/test/torque/test-torque.tq @@ -196,8 +196,8 @@ macro TestFunctionPointers(implicit context: Context)(): Boolean { @export macro TestVariableRedeclaration(implicit context: Context)(): Boolean { - let _var1: int31 = FromConstexpr(42 == 0) ? 0 : 1; - let _var2: int31 = FromConstexpr(42 == 0) ? 1 : 0; + let _var1: int31 = FromConstexpr(42 == 0) ? FromConstexpr(0) : 1; + let _var2: int31 = FromConstexpr(42 == 0) ? FromConstexpr(1) : 0; return True; } diff --git a/test/unittests/torque/torque-unittest.cc b/test/unittests/torque/torque-unittest.cc index f6a3eef8e1..5299766823 100644 --- a/test/unittests/torque/torque-unittest.cc +++ b/test/unittests/torque/torque-unittest.cc @@ -20,6 +20,8 @@ constexpr const char* kTestTorquePrelude = R"( type void; type never; +type IntegerLiteral constexpr 'IntegerLiteral'; + namespace torque_internal { struct Reference { const object: HeapObject; @@ -112,6 +114,8 @@ extern macro TaggedToHeapObject(Object): HeapObject extern macro Float64SilenceNaN(float64): float64; extern macro IntPtrConstant(constexpr int31): intptr; +extern macro ConstexprIntegerLiteralToInt32(constexpr IntegerLiteral): constexpr int32; +extern macro SmiFromInt32(int32): Smi; macro FromConstexpr(o: From): To; FromConstexpr(s: constexpr Smi): Smi { @@ -133,6 +137,15 @@ FromConstexpr(b: constexpr bool): bool { FromConstexpr(i: constexpr int31): int32 { return %FromConstexpr(i); } +FromConstexpr(i: constexpr int32): int32 { + return %FromConstexpr(i); +} +FromConstexpr(i: constexpr IntegerLiteral): int32 { + return FromConstexpr(ConstexprIntegerLiteralToInt32(i)); +} +FromConstexpr(i: constexpr IntegerLiteral): Smi { + return SmiFromInt32(FromConstexpr(i)); +} macro Cast(implicit context: Context)(o: Object): A labels CastError { diff --git a/tools/debug_helper/debug-macro-shims.h b/tools/debug_helper/debug-macro-shims.h index e434fb1bf3..343a6433fc 100644 --- a/tools/debug_helper/debug-macro-shims.h +++ b/tools/debug_helper/debug-macro-shims.h @@ -8,6 +8,7 @@ #ifndef V8_TORQUE_DEBUG_MACRO_SHIMS_H_ #define V8_TORQUE_DEBUG_MACRO_SHIMS_H_ +#include "src/numbers/integer-literal.h" #include "src/objects/smi.h" #include "tools/debug_helper/debug-helper-internal.h" @@ -77,6 +78,9 @@ inline Value SmiUntag(d::MemoryAccessor accessor, uintptr_t s_t) { Smi s(s_t); return {d::MemoryAccessResult::kOk, s.value()}; } +inline Value SmiFromInt32(d::MemoryAccessor accessor, int32_t i) { + return {d::MemoryAccessResult::kOk, Smi::FromInt(i).ptr()}; +} inline Value UintPtrLessThan(d::MemoryAccessor accessor, uintptr_t a, uintptr_t b) { return {d::MemoryAccessResult::kOk, a < b}; @@ -97,6 +101,19 @@ inline Value Word32NotEqual(d::MemoryAccessor accessor, uint32_t a, uint32_t b) { return {d::MemoryAccessResult::kOk, a != b}; } +// This is used in a nested call where we cannot pass Value. +inline int31_t ConstexprIntegerLiteralToInt31(d::MemoryAccessor accessor, + const IntegerLiteral& i) { + return i.To(); +} +inline int32_t ConstexprIntegerLiteralToInt32(d::MemoryAccessor accessor, + const IntegerLiteral& i) { + return i.To(); +} +inline intptr_t ConstexprIntegerLiteralToIntptr(d::MemoryAccessor accessor, + const IntegerLiteral& i) { + return i.To(); +} } // namespace CodeStubAssembler } // namespace TorqueDebugMacroShims