Commit 362b30eb authored by Nico Hartmann's avatar Nico Hartmann Committed by V8 LUCI CQ

Reland "Reland "[Torque] Generalize Torque literals to larger size""

This is a reland of 517ed4ad

Original change's description:
> Reland "[Torque] Generalize Torque literals to larger size"
>
> Previously, literals in Torque were stored as double values, which
> made it impossible to precisely represent 64 bit integer values.
> This CL replaces the old literal expression with an integer and
> floating point literal expression that are unbounded in size. We
> allow implicit conversion of these literals to arbitary integer
> and floating point types respectively and insert a corresponding
> bounds check into generated CSA.
>
> Changes in the reland: Simplified IntegerLiteral to single digit.
>
> Bug: v8:7793, chromium:1289282
> Change-Id: I31c762c2f31165c7a1d0b07842b764e5851ce189
> Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3406750
> Reviewed-by: Jakob Kummerow <jkummerow@chromium.org>
> Reviewed-by: Tobias Tebbi <tebbi@chromium.org>
> Commit-Queue: Nico Hartmann <nicohartmann@chromium.org>
> Cr-Commit-Position: refs/heads/main@{#78811}

Bug: v8:7793, chromium:1289282
Change-Id: I7aadc4d2c9494f03eae85e94949c8f4cab7a075c
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3437047Reviewed-by: 's avatarJakob Kummerow <jkummerow@chromium.org>
Reviewed-by: 's avatarTobias Tebbi <tebbi@chromium.org>
Commit-Queue: Nico Hartmann <nicohartmann@chromium.org>
Cr-Commit-Position: refs/heads/main@{#78939}
parent bc2a8f64
...@@ -923,6 +923,8 @@ filegroup( ...@@ -923,6 +923,8 @@ filegroup(
filegroup( filegroup(
name = "torque_base_files", name = "torque_base_files",
srcs = [ srcs = [
"src/numbers/integer-literal-inl.h",
"src/numbers/integer-literal.h",
"src/torque/ast.h", "src/torque/ast.h",
"src/torque/cc-generator.cc", "src/torque/cc-generator.cc",
"src/torque/cc-generator.h", "src/torque/cc-generator.h",
...@@ -2802,6 +2804,8 @@ filegroup( ...@@ -2802,6 +2804,8 @@ filegroup(
"src/interpreter/interpreter-generator.h", "src/interpreter/interpreter-generator.h",
"src/interpreter/interpreter-intrinsics-generator.cc", "src/interpreter/interpreter-intrinsics-generator.cc",
"src/interpreter/interpreter-intrinsics-generator.h", "src/interpreter/interpreter-intrinsics-generator.h",
"src/numbers/integer-literal-inl.h",
"src/numbers/integer-literal.h",
] + select({ ] + select({
"@v8//bazel/config:v8_target_ia32": ["src/builtins/ia32/builtins-ia32.cc"], "@v8//bazel/config:v8_target_ia32": ["src/builtins/ia32/builtins-ia32.cc"],
"@v8//bazel/config:v8_target_x64": ["src/builtins/x64/builtins-x64.cc"], "@v8//bazel/config:v8_target_x64": ["src/builtins/x64/builtins-x64.cc"],
......
...@@ -2380,6 +2380,8 @@ v8_source_set("v8_initializers") { ...@@ -2380,6 +2380,8 @@ v8_source_set("v8_initializers") {
"src/interpreter/interpreter-generator.h", "src/interpreter/interpreter-generator.h",
"src/interpreter/interpreter-intrinsics-generator.cc", "src/interpreter/interpreter-intrinsics-generator.cc",
"src/interpreter/interpreter-intrinsics-generator.h", "src/interpreter/interpreter-intrinsics-generator.h",
"src/numbers/integer-literal-inl.h",
"src/numbers/integer-literal.h",
] ]
if (v8_enable_webassembly) { if (v8_enable_webassembly) {
...@@ -4872,6 +4874,8 @@ v8_source_set("torque_base") { ...@@ -4872,6 +4874,8 @@ v8_source_set("torque_base") {
visibility = [ ":*" ] # Only targets in this file can depend on this. visibility = [ ":*" ] # Only targets in this file can depend on this.
sources = [ sources = [
"src/numbers/integer-literal-inl.h",
"src/numbers/integer-literal.h",
"src/torque/ast.h", "src/torque/ast.h",
"src/torque/cc-generator.cc", "src/torque/cc-generator.cc",
"src/torque/cc-generator.h", "src/torque/cc-generator.h",
......
...@@ -301,6 +301,10 @@ class Processor { ...@@ -301,6 +301,10 @@ class Processor {
// Z := the contents of {accumulator}. // Z := the contents of {accumulator}.
// Assume that this leaves {accumulator} in unusable state. // Assume that this leaves {accumulator} in unusable state.
Status FromString(RWDigits Z, FromStringAccumulator* accumulator); 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) { inline int AddResultLength(int x_length, int y_length) {
...@@ -418,13 +422,13 @@ class FromStringAccumulator { ...@@ -418,13 +422,13 @@ class FromStringAccumulator {
: max_digits_(std::max(max_digits, kStackParts)) {} : max_digits_(std::max(max_digits, kStackParts)) {}
// Step 2: Call this method to read all characters. // Step 2: Call this method to read all characters.
// {Char} should be a character type, such as uint8_t or uint16_t. // {CharIt} should be a forward iterator and
// {end} should be one past the last character (i.e. {start == end} would // std::iterator_traits<CharIt>::value_type shall be a character type, such as
// indicate an empty string). // uint8_t or uint16_t. {end} should be one past the last character (i.e.
// Returns the current position when an invalid character is encountered. // {start == end} would indicate an empty string). Returns the current
template <class Char> // position when an invalid character is encountered.
ALWAYS_INLINE const Char* Parse(const Char* start, const Char* end, template <class CharIt>
digit_t radix); ALWAYS_INLINE CharIt Parse(CharIt start, CharIt end, digit_t radix);
// Step 3: Check if a result is available, and determine its required // Step 3: Check if a result is available, and determine its required
// allocation size (guaranteed to be <= max_digits passed to the constructor). // allocation size (guaranteed to be <= max_digits passed to the constructor).
...@@ -434,14 +438,13 @@ class FromStringAccumulator { ...@@ -434,14 +438,13 @@ class FromStringAccumulator {
} }
// Step 4: Use BigIntProcessor::FromString() to retrieve the result into an // 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: private:
friend class ProcessorImpl; friend class ProcessorImpl;
template <class Char> template <class CharIt>
ALWAYS_INLINE const Char* ParsePowerTwo(const Char* start, const Char* end, ALWAYS_INLINE CharIt ParsePowerTwo(CharIt start, CharIt end, digit_t radix);
digit_t radix);
ALWAYS_INLINE bool AddPart(digit_t multiplier, digit_t part, bool is_last); ALWAYS_INLINE bool AddPart(digit_t multiplier, digit_t part, bool is_last);
ALWAYS_INLINE bool AddPart(digit_t part); ALWAYS_INLINE bool AddPart(digit_t part);
...@@ -491,10 +494,9 @@ static constexpr uint8_t kCharValue[] = { ...@@ -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}. // 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}; static constexpr uint8_t kCharBits[] = {1, 2, 3, 0, 4, 0, 0, 0, 5};
template <class Char> template <class CharIt>
const Char* FromStringAccumulator::ParsePowerTwo(const Char* current, CharIt FromStringAccumulator::ParsePowerTwo(CharIt current, CharIt end,
const Char* end, digit_t radix) {
digit_t radix) {
radix_ = static_cast<uint8_t>(radix); radix_ = static_cast<uint8_t>(radix);
const int char_bits = kCharBits[radix >> 2]; const int char_bits = kCharBits[radix >> 2];
int bits_left; int bits_left;
...@@ -528,11 +530,10 @@ const Char* FromStringAccumulator::ParsePowerTwo(const Char* current, ...@@ -528,11 +530,10 @@ const Char* FromStringAccumulator::ParsePowerTwo(const Char* current,
return current; return current;
} }
template <class Char> template <class CharIt>
const Char* FromStringAccumulator::Parse(const Char* start, const Char* end, CharIt FromStringAccumulator::Parse(CharIt start, CharIt end, digit_t radix) {
digit_t radix) {
BIGINT_H_DCHECK(2 <= radix && radix <= 36); BIGINT_H_DCHECK(2 <= radix && radix <= 36);
const Char* current = start; CharIt current = start;
#if !HAVE_BUILTIN_MUL_OVERFLOW #if !HAVE_BUILTIN_MUL_OVERFLOW
const digit_t kMaxMultiplier = (~digit_t{0}) / radix; const digit_t kMaxMultiplier = (~digit_t{0}) / radix;
#endif #endif
......
...@@ -127,6 +127,7 @@ class ToStringFormatter { ...@@ -127,6 +127,7 @@ class ToStringFormatter {
out_end_(out + chars_available), out_end_(out + chars_available),
out_(out_end_), out_(out_end_),
processor_(processor) { processor_(processor) {
digits_.Normalize();
DCHECK(chars_available >= ToStringResultLength(digits_, radix_, sign_)); DCHECK(chars_available >= ToStringResultLength(digits_, radix_, sign_));
} }
......
...@@ -548,7 +548,7 @@ macro JoinStackPopInline(implicit context: Context)(receiver: JSReceiver): ...@@ -548,7 +548,7 @@ macro JoinStackPopInline(implicit context: Context)(receiver: JSReceiver):
// Builtin call was not nested (receiver is the first entry) and // Builtin call was not nested (receiver is the first entry) and
// did not contain other nested arrays that expanded the stack. // did not contain other nested arrays that expanded the stack.
if (stack.objects[0] == receiver && len == kMinJoinStackSize) { if (stack.objects[0] == receiver && len == kMinJoinStackSize) {
StoreFixedArrayElement(stack, 0, TheHole, SKIP_WRITE_BARRIER); stack.objects[0] = TheHole;
} else } else
deferred { deferred {
JoinStackPop(stack, receiver); JoinStackPop(stack, receiver);
......
...@@ -27,6 +27,8 @@ ...@@ -27,6 +27,8 @@
type void; type void;
type never; type never;
type IntegerLiteral constexpr 'IntegerLiteral';
type Tagged generates 'TNode<MaybeObject>' constexpr 'MaybeObject'; type Tagged generates 'TNode<MaybeObject>' constexpr 'MaybeObject';
type StrongTagged extends Tagged type StrongTagged extends Tagged
generates 'TNode<Object>' constexpr 'Object'; generates 'TNode<Object>' constexpr 'Object';
...@@ -613,7 +615,7 @@ transitioning macro ToIntegerImpl(implicit context: Context)(input: JSAny): ...@@ -613,7 +615,7 @@ transitioning macro ToIntegerImpl(implicit context: Context)(input: JSAny):
if (Float64IsNaN(value)) return SmiConstant(0); if (Float64IsNaN(value)) return SmiConstant(0);
value = math::Float64Trunc(value); value = math::Float64Trunc(value);
// ToInteger normalizes -0 to +0. // ToInteger normalizes -0 to +0.
if (value == 0.0) return SmiConstant(0); if (value == 0) return SmiConstant(0);
const result = ChangeFloat64ToTagged(value); const result = ChangeFloat64ToTagged(value);
dcheck(IsNumberNormalized(result)); dcheck(IsNumberNormalized(result));
return result; return result;
...@@ -989,6 +991,38 @@ extern operator '==' macro ConstexprInt32Equal( ...@@ -989,6 +991,38 @@ extern operator '==' macro ConstexprInt32Equal(
extern operator '!=' macro ConstexprInt32NotEqual( extern operator '!=' macro ConstexprInt32NotEqual(
constexpr int32, constexpr int32): constexpr bool; 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(int32, int32): bool;
extern operator '==' macro Word32Equal(uint32, uint32): bool; extern operator '==' macro Word32Equal(uint32, uint32): bool;
extern operator '!=' macro Word32NotEqual(int32, int32): bool; extern operator '!=' macro Word32NotEqual(int32, int32): bool;
...@@ -1178,19 +1212,29 @@ extern macro IntPtrConstant(constexpr int32): intptr; ...@@ -1178,19 +1212,29 @@ extern macro IntPtrConstant(constexpr int32): intptr;
extern macro Uint16Constant(constexpr uint16): uint16; extern macro Uint16Constant(constexpr uint16): uint16;
extern macro Int32Constant(constexpr int31): int31; extern macro Int32Constant(constexpr int31): int31;
extern macro Int32Constant(constexpr int32): int32; extern macro Int32Constant(constexpr int32): int32;
macro Int32Constant(i: constexpr IntegerLiteral): int32 {
return Int32Constant(ConstexprIntegerLiteralToInt32(i));
}
extern macro Int64Constant(constexpr int64): int64; extern macro Int64Constant(constexpr int64): int64;
extern macro Uint64Constant(constexpr uint64): uint64; extern macro Uint64Constant(constexpr uint64): uint64;
extern macro Float64Constant(constexpr int32): float64; extern macro Float64Constant(constexpr int32): float64;
extern macro Float64Constant(constexpr float64): float64; extern macro Float64Constant(constexpr float64): float64;
extern macro Float64Constant(constexpr IntegerLiteral): float64;
extern macro SmiConstant(constexpr int31): Smi; extern macro SmiConstant(constexpr int31): Smi;
extern macro SmiConstant(constexpr Smi): Smi; extern macro SmiConstant(constexpr Smi): Smi;
extern macro SmiConstant(constexpr MessageTemplate): Smi; extern macro SmiConstant(constexpr MessageTemplate): Smi;
extern macro SmiConstant(constexpr bool): Smi; extern macro SmiConstant(constexpr bool): Smi;
extern macro SmiConstant(constexpr uint32): 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 BoolConstant(constexpr bool): bool;
extern macro StringConstant(constexpr string): String; extern macro StringConstant(constexpr string): String;
extern macro IntPtrConstant(constexpr ContextSlot): ContextSlot; extern macro IntPtrConstant(constexpr ContextSlot): ContextSlot;
extern macro IntPtrConstant(constexpr intptr): intptr; extern macro IntPtrConstant(constexpr intptr): intptr;
macro IntPtrConstant(il: constexpr IntegerLiteral): intptr {
return IntPtrConstant(ConstexprIntegerLiteralToIntptr(il));
}
extern macro PointerConstant(constexpr RawPtr): RawPtr; extern macro PointerConstant(constexpr RawPtr): RawPtr;
extern macro SingleCharacterStringConstant(constexpr string): String; extern macro SingleCharacterStringConstant(constexpr string): String;
extern macro Float64SilenceNaN(float64): float64; extern macro Float64SilenceNaN(float64): float64;
......
...@@ -4,6 +4,59 @@ ...@@ -4,6 +4,59 @@
intrinsic %FromConstexpr<To: type, From: type>(b: From): To; intrinsic %FromConstexpr<To: type, From: type>(b: From): To;
macro FromConstexpr<To: type, From: type>(o: From): To; macro FromConstexpr<To: type, From: type>(o: From): To;
// Conversions for IntegerLiteral
FromConstexpr<intptr, constexpr IntegerLiteral>(i: constexpr IntegerLiteral):
intptr {
return ConstexprIntegerLiteralToIntptr(i);
}
FromConstexpr<uintptr, constexpr IntegerLiteral>(i: constexpr IntegerLiteral):
uintptr {
return ConstexprIntegerLiteralToUintptr(i);
}
FromConstexpr<int32, constexpr IntegerLiteral>(i: constexpr IntegerLiteral):
int32 {
return ConstexprIntegerLiteralToInt32(i);
}
FromConstexpr<uint32, constexpr IntegerLiteral>(i: constexpr IntegerLiteral):
uint32 {
return ConstexprIntegerLiteralToUint32(i);
}
FromConstexpr<int31, constexpr IntegerLiteral>(i: constexpr IntegerLiteral):
int31 {
return ConstexprIntegerLiteralToInt31(i);
}
FromConstexpr<int8, constexpr IntegerLiteral>(i: constexpr IntegerLiteral):
int8 {
return ConstexprIntegerLiteralToInt8(i);
}
FromConstexpr<uint8, constexpr IntegerLiteral>(i: constexpr IntegerLiteral):
uint8 {
return ConstexprIntegerLiteralToUint8(i);
}
FromConstexpr<uint64, constexpr IntegerLiteral>(i: constexpr IntegerLiteral):
uint64 {
return ConstexprIntegerLiteralToUint64(i);
}
FromConstexpr<constexpr int31, constexpr IntegerLiteral>(
i: constexpr IntegerLiteral): constexpr int31 {
return ConstexprIntegerLiteralToInt31(i);
}
FromConstexpr<constexpr int32, constexpr IntegerLiteral>(
i: constexpr IntegerLiteral): constexpr int32 {
return ConstexprIntegerLiteralToInt32(i);
}
FromConstexpr<Number, constexpr IntegerLiteral>(i: constexpr IntegerLiteral):
Number {
return NumberConstant(ConstexprIntegerLiteralToFloat64(i));
}
FromConstexpr<Smi, constexpr IntegerLiteral>(i: constexpr IntegerLiteral): Smi {
return Convert<Smi>(ConstexprIntegerLiteralToInt31(i));
}
FromConstexpr<char8, constexpr IntegerLiteral>(i: constexpr IntegerLiteral):
char8 {
return %RawDownCast<char8>(FromConstexpr<uint8>(i));
}
FromConstexpr<int31, constexpr int31>(i: constexpr int31): int31 { FromConstexpr<int31, constexpr int31>(i: constexpr int31): int31 {
return %FromConstexpr<int31>(i); return %FromConstexpr<int31>(i);
} }
...@@ -325,6 +378,10 @@ Convert<intptr, Number>(n: Number): intptr { ...@@ -325,6 +378,10 @@ Convert<intptr, Number>(n: Number): intptr {
Convert<bint, int32>(v: int32): bint { Convert<bint, int32>(v: int32): bint {
return IntPtrToBInt(Convert<intptr>(v)); return IntPtrToBInt(Convert<intptr>(v));
} }
FromConstexpr<float64, constexpr IntegerLiteral>(v: constexpr IntegerLiteral):
float64 {
return ConstexprIntegerLiteralToFloat64(v);
}
extern macro IntPtrToBInt(intptr): bint; extern macro IntPtrToBInt(intptr): bint;
Convert<bint, intptr>(v: intptr): bint { Convert<bint, intptr>(v: intptr): bint {
return IntPtrToBInt(v); return IntPtrToBInt(v);
......
...@@ -90,7 +90,7 @@ macro NumberToStringSmi(x: int32, radix: int32): String labels Slow { ...@@ -90,7 +90,7 @@ macro NumberToStringSmi(x: int32, radix: int32): String labels Slow {
// Calculate length and pre-allocate the result string. // Calculate length and pre-allocate the result string.
let temp: int32 = n; let temp: int32 = n;
let length: int32 = isNegative ? 1 : 0; let length: int32 = isNegative ? Convert<int32>(1) : Convert<int32>(0);
while (temp > 0) { while (temp > 0) {
temp = temp / radix; temp = temp / radix;
length = length + 1; length = length + 1;
...@@ -277,7 +277,7 @@ transitioning builtin ParseInt(implicit context: Context)( ...@@ -277,7 +277,7 @@ transitioning builtin ParseInt(implicit context: Context)(
// the runtime for the range [0,1[ because the result could be -0. // the runtime for the range [0,1[ because the result could be -0.
const kMaxAbsValue: float64 = 2147483648.0; const kMaxAbsValue: float64 = 2147483648.0;
const absInput: float64 = math::Float64Abs(asFloat64); 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; goto CallRuntime;
} }
case (s: String): { case (s: String): {
...@@ -690,7 +690,7 @@ builtin Negate(implicit context: Context)(value: JSAny): Numeric { ...@@ -690,7 +690,7 @@ builtin Negate(implicit context: Context)(value: JSAny): Numeric {
} label Smi(s: Smi) { } label Smi(s: Smi) {
return SmiMul(s, -1); return SmiMul(s, -1);
} label HeapNumber(h: HeapNumber) { } label HeapNumber(h: HeapNumber) {
return AllocateHeapNumberWithValue(Convert<float64>(h) * -1); return AllocateHeapNumberWithValue(Convert<float64>(h) * -1.0);
} label BigInt(b: BigInt) { } label BigInt(b: BigInt) {
tail runtime::BigIntUnaryOp( tail runtime::BigIntUnaryOp(
context, b, SmiTag<Operation>(Operation::kNegate)); context, b, SmiTag<Operation>(Operation::kNegate));
......
...@@ -55,7 +55,7 @@ transitioning javascript builtin StringPrototypeRepeat( ...@@ -55,7 +55,7 @@ transitioning javascript builtin StringPrototypeRepeat(
// 4. If n < 0, throw a RangeError exception. // 4. If n < 0, throw a RangeError exception.
// 5. If n is +∞, 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. // 6. If n is 0, return the empty String.
if (s.length_uint32 == 0) goto EmptyString; if (s.length_uint32 == 0) goto EmptyString;
......
...@@ -105,6 +105,10 @@ struct Slice<T: type, Reference: type> { ...@@ -105,6 +105,10 @@ struct Slice<T: type, Reference: type> {
return this.TryAtIndex(Convert<intptr>(index)) otherwise unreachable; return this.TryAtIndex(Convert<intptr>(index)) otherwise unreachable;
} }
macro AtIndex(index: constexpr IntegerLiteral): Reference {
return this.AtIndex(FromConstexpr<uintptr>(index));
}
macro AtIndex(index: constexpr int31): Reference { macro AtIndex(index: constexpr int31): Reference {
const i: intptr = Convert<intptr>(index); const i: intptr = Convert<intptr>(index);
return this.TryAtIndex(i) otherwise unreachable; return this.TryAtIndex(i) otherwise unreachable;
......
...@@ -17,6 +17,7 @@ ...@@ -17,6 +17,7 @@
#include "src/heap/heap-inl.h" // For MemoryChunk. TODO(jkummerow): Drop. #include "src/heap/heap-inl.h" // For MemoryChunk. TODO(jkummerow): Drop.
#include "src/heap/memory-chunk.h" #include "src/heap/memory-chunk.h"
#include "src/logging/counters.h" #include "src/logging/counters.h"
#include "src/numbers/integer-literal-inl.h"
#include "src/objects/api-callbacks.h" #include "src/objects/api-callbacks.h"
#include "src/objects/cell.h" #include "src/objects/cell.h"
#include "src/objects/descriptor-array.h" #include "src/objects/descriptor-array.h"
...@@ -14892,6 +14893,19 @@ void CodeStubAssembler::Print(const char* prefix, ...@@ -14892,6 +14893,19 @@ void CodeStubAssembler::Print(const char* prefix,
CallRuntime(Runtime::kDebugPrint, NoContextConstant(), arg); 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> context) { void CodeStubAssembler::PerformStackCheck(TNode<Context> context) {
Label ok(this), stack_check_interrupt(this, Label::kDeferred); Label ok(this), stack_check_interrupt(this, Label::kDeferred);
......
...@@ -13,6 +13,7 @@ ...@@ -13,6 +13,7 @@
#include "src/common/globals.h" #include "src/common/globals.h"
#include "src/common/message-template.h" #include "src/common/message-template.h"
#include "src/compiler/code-assembler.h" #include "src/compiler/code-assembler.h"
#include "src/numbers/integer-literal.h"
#include "src/objects/arguments.h" #include "src/objects/arguments.h"
#include "src/objects/bigint.h" #include "src/objects/bigint.h"
#include "src/objects/cell.h" #include "src/objects/cell.h"
...@@ -3776,6 +3777,45 @@ class V8_EXPORT_PRIVATE CodeStubAssembler ...@@ -3776,6 +3777,45 @@ class V8_EXPORT_PRIVATE CodeStubAssembler
} }
bool ConstexprBoolNot(bool value) { return !value; } bool ConstexprBoolNot(bool value) { return !value; }
int31_t ConstexprIntegerLiteralToInt31(const IntegerLiteral& i) {
return int31_t(i.To<int32_t>());
}
int32_t ConstexprIntegerLiteralToInt32(const IntegerLiteral& i) {
return i.To<int32_t>();
}
uint32_t ConstexprIntegerLiteralToUint32(const IntegerLiteral& i) {
return i.To<uint32_t>();
}
int8_t ConstexprIntegerLiteralToInt8(const IntegerLiteral& i) {
return i.To<int8_t>();
}
uint8_t ConstexprIntegerLiteralToUint8(const IntegerLiteral& i) {
return i.To<uint8_t>();
}
uint64_t ConstexprIntegerLiteralToUint64(const IntegerLiteral& i) {
return i.To<uint64_t>();
}
intptr_t ConstexprIntegerLiteralToIntptr(const IntegerLiteral& i) {
return i.To<intptr_t>();
}
uintptr_t ConstexprIntegerLiteralToUintptr(const IntegerLiteral& i) {
return i.To<uintptr_t>();
}
double ConstexprIntegerLiteralToFloat64(const IntegerLiteral& i) {
int64_t i_value = i.To<int64_t>();
double d_value = static_cast<double>(i_value);
CHECK_EQ(i_value, static_cast<int64_t>(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 ConstexprInt31Equal(int31_t a, int31_t b) { return a == b; }
bool ConstexprInt31NotEqual(int31_t a, int31_t b) { return a != b; } bool ConstexprInt31NotEqual(int31_t a, int31_t b) { return a != b; }
......
// 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_
// 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 <typename T>
explicit IntegerLiteral(T value) : IntegerLiteral(value, true) {}
bool is_negative() const { return negative_; }
uint64_t absolute_value() const { return absolute_value_; }
template <typename T>
bool IsRepresentableAs() const {
static_assert(std::is_integral<T>::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<T>::min(), false)) >= 0 &&
Compare(IntegerLiteral(std::numeric_limits<T>::max(), false)) <= 0;
}
template <typename T>
T To() const {
static_assert(std::is_integral<T>::value, "Integral type required");
DCHECK(IsRepresentableAs<T>());
uint64_t v = absolute_value_;
if (negative_) v = ~v + 1;
return static_cast<T>(v);
}
template <typename T>
base::Optional<T> TryTo() const {
static_assert(std::is_integral<T>::value, "Integral type required");
if (!IsRepresentableAs<T>()) return base::nullopt;
return To<T>();
}
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 <typename T>
explicit IntegerLiteral(T value, bool perform_dcheck) : negative_(false) {
static_assert(std::is_integral<T>::value, "Integral type required");
absolute_value_ = static_cast<uint64_t>(value);
if (value < T(0)) {
negative_ = true;
absolute_value_ = ~absolute_value_ + 1;
}
if (perform_dcheck) DCHECK_EQ(To<T>(), 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_
...@@ -5,12 +5,11 @@ ...@@ -5,12 +5,11 @@
#ifndef V8_OBJECTS_DESCRIPTOR_ARRAY_INL_H_ #ifndef V8_OBJECTS_DESCRIPTOR_ARRAY_INL_H_
#define 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/execution/isolate.h"
#include "src/handles/maybe-handles-inl.h" #include "src/handles/maybe-handles-inl.h"
#include "src/heap/heap-write-barrier.h" #include "src/heap/heap-write-barrier.h"
#include "src/heap/heap.h" #include "src/heap/heap.h"
#include "src/objects/descriptor-array.h"
#include "src/objects/field-type.h" #include "src/objects/field-type.h"
#include "src/objects/heap-object-inl.h" #include "src/objects/heap-object-inl.h"
#include "src/objects/lookup-cache-inl.h" #include "src/objects/lookup-cache-inl.h"
......
...@@ -5,13 +5,12 @@ ...@@ -5,13 +5,12 @@
#ifndef V8_OBJECTS_FIXED_ARRAY_INL_H_ #ifndef V8_OBJECTS_FIXED_ARRAY_INL_H_
#define 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/handles/handles-inl.h"
#include "src/heap/heap-write-barrier-inl.h" #include "src/heap/heap-write-barrier-inl.h"
#include "src/numbers/conversions.h" #include "src/numbers/conversions.h"
#include "src/objects/bigint.h" #include "src/objects/bigint.h"
#include "src/objects/compressed-slots.h" #include "src/objects/compressed-slots.h"
#include "src/objects/fixed-array.h"
#include "src/objects/map.h" #include "src/objects/map.h"
#include "src/objects/maybe-object-inl.h" #include "src/objects/maybe-object-inl.h"
#include "src/objects/objects-inl.h" #include "src/objects/objects-inl.h"
......
...@@ -80,7 +80,7 @@ class TurbofanOtherNumberConstantType extends TurbofanType { ...@@ -80,7 +80,7 @@ class TurbofanOtherNumberConstantType extends TurbofanType {
} }
macro IsMinusZero(x: float64): bool { macro IsMinusZero(x: float64): bool {
return x == 0 && 1 / x < 0; return x == 0 && 1.0 / x < 0;
} }
macro TestTurbofanBitsetType( macro TestTurbofanBitsetType(
...@@ -94,13 +94,13 @@ macro TestTurbofanBitsetType( ...@@ -94,13 +94,13 @@ macro TestTurbofanBitsetType(
if (IsInteger(value)) { if (IsInteger(value)) {
if (IsMinusZero(valueF)) { if (IsMinusZero(valueF)) {
return bitsetLow.minus_zero; return bitsetLow.minus_zero;
} else if (valueF < Convert<float64>(-0x80000000)) { } else if (valueF < -0x80000000) {
return bitsetLow.other_number; return bitsetLow.other_number;
} else if (valueF < -0x40000000) { } else if (valueF < -0x40000000) {
return bitsetLow.other_signed32; return bitsetLow.other_signed32;
} else if (valueF < 0) { } else if (valueF < 0) {
return bitsetLow.negative31; return bitsetLow.negative31;
} else if (valueF < Convert<float64>(0x40000000)) { } else if (valueF < 0x40000000) {
return bitsetLow.unsigned30; return bitsetLow.unsigned30;
} else if (valueF < 0x80000000) { } else if (valueF < 0x80000000) {
return bitsetLow.other_unsigned31; return bitsetLow.other_unsigned31;
......
...@@ -14,6 +14,7 @@ ...@@ -14,6 +14,7 @@
#include <vector> #include <vector>
#include "src/base/optional.h" #include "src/base/optional.h"
#include "src/numbers/integer-literal.h"
#include "src/torque/constants.h" #include "src/torque/constants.h"
#include "src/torque/source-positions.h" #include "src/torque/source-positions.h"
#include "src/torque/utils.h" #include "src/torque/utils.h"
...@@ -33,7 +34,8 @@ namespace torque { ...@@ -33,7 +34,8 @@ namespace torque {
V(ConditionalExpression) \ V(ConditionalExpression) \
V(IdentifierExpression) \ V(IdentifierExpression) \
V(StringLiteralExpression) \ V(StringLiteralExpression) \
V(NumberLiteralExpression) \ V(IntegerLiteralExpression) \
V(FloatingPointLiteralExpression) \
V(FieldAccessExpression) \ V(FieldAccessExpression) \
V(ElementAccessExpression) \ V(ElementAccessExpression) \
V(DereferenceExpression) \ V(DereferenceExpression) \
...@@ -459,16 +461,28 @@ struct StringLiteralExpression : Expression { ...@@ -459,16 +461,28 @@ struct StringLiteralExpression : Expression {
std::string literal; std::string literal;
}; };
struct NumberLiteralExpression : Expression { struct IntegerLiteralExpression : Expression {
DEFINE_AST_NODE_LEAF_BOILERPLATE(NumberLiteralExpression) DEFINE_AST_NODE_LEAF_BOILERPLATE(IntegerLiteralExpression)
NumberLiteralExpression(SourcePosition pos, double number) IntegerLiteralExpression(SourcePosition pos, IntegerLiteral value)
: Expression(kKind, pos), number(number) {} : Expression(kKind, pos), value(std::move(value)) {}
void VisitAllSubExpressions(VisitCallback callback) override { void VisitAllSubExpressions(VisitCallback callback) override {
callback(this); 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 { struct ElementAccessExpression : LocationExpression {
......
...@@ -67,6 +67,8 @@ static const char* const FLOAT64_OR_HOLE_TYPE_STRING = "float64_or_hole"; ...@@ -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_INT31_TYPE_STRING = "constexpr int31";
static const char* const CONST_INT32_TYPE_STRING = "constexpr int32"; static const char* const CONST_INT32_TYPE_STRING = "constexpr int32";
static const char* const CONST_FLOAT64_TYPE_STRING = "constexpr float64"; 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 TORQUE_INTERNAL_NAMESPACE_STRING = "torque_internal";
static const char* const MUTABLE_REFERENCE_TYPE_STRING = "MutableReference"; static const char* const MUTABLE_REFERENCE_TYPE_STRING = "MutableReference";
static const char* const CONST_REFERENCE_TYPE_STRING = "ConstReference"; static const char* const CONST_REFERENCE_TYPE_STRING = "ConstReference";
......
...@@ -127,6 +127,7 @@ LexerResult Lexer::RunLexer(const std::string& input) { ...@@ -127,6 +127,7 @@ LexerResult Lexer::RunLexer(const std::string& input) {
while (pos != end) { while (pos != end) {
token_start = pos; token_start = pos;
Symbol* symbol = MatchToken(&pos, end); Symbol* symbol = MatchToken(&pos, end);
DCHECK_IMPLIES(symbol != nullptr, pos != token_start);
InputPosition token_end = pos; InputPosition token_end = pos;
line_column_tracker.Advance(token_start, token_end); line_column_tracker.Advance(token_start, token_end);
if (!symbol) { if (!symbol) {
......
...@@ -44,6 +44,8 @@ enum class ParseResultHolderBase::TypeId { ...@@ -44,6 +44,8 @@ enum class ParseResultHolderBase::TypeId {
kStdString, kStdString,
kBool, kBool,
kInt32, kInt32,
kDouble,
kIntegerLiteral,
kStdVectorOfString, kStdVectorOfString,
kExpressionPtr, kExpressionPtr,
kIdentifierPtr, kIdentifierPtr,
......
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
#include "src/base/optional.h" #include "src/base/optional.h"
#include "src/common/globals.h" #include "src/common/globals.h"
#include "src/numbers/integer-literal-inl.h"
#include "src/torque/cc-generator.h" #include "src/torque/cc-generator.h"
#include "src/torque/cfg.h" #include "src/torque/cfg.h"
#include "src/torque/constants.h" #include "src/torque/constants.h"
...@@ -182,6 +183,7 @@ void ImplementationVisitor::BeginDebugMacrosFile() { ...@@ -182,6 +183,7 @@ void ImplementationVisitor::BeginDebugMacrosFile() {
header << "#ifndef " << kHeaderDefine << "\n"; header << "#ifndef " << kHeaderDefine << "\n";
header << "#define " << kHeaderDefine << "\n\n"; header << "#define " << kHeaderDefine << "\n\n";
header << "#include \"tools/debug_helper/debug-helper-internal.h\"\n"; header << "#include \"tools/debug_helper/debug-helper-internal.h\"\n";
header << "#include \"src/numbers/integer-literal.h\"\n";
header << "\n"; header << "\n";
header << "namespace v8 {\n" header << "namespace v8 {\n"
...@@ -943,22 +945,20 @@ VisitResult ImplementationVisitor::Visit(AssignmentExpression* expr) { ...@@ -943,22 +945,20 @@ VisitResult ImplementationVisitor::Visit(AssignmentExpression* expr) {
return scope.Yield(assignment_value); return scope.Yield(assignment_value);
} }
VisitResult ImplementationVisitor::Visit(NumberLiteralExpression* expr) { VisitResult ImplementationVisitor::Visit(FloatingPointLiteralExpression* expr) {
const Type* result_type = TypeOracle::GetConstFloat64Type(); const Type* result_type = TypeOracle::GetConstFloat64Type();
if (expr->number >= std::numeric_limits<int32_t>::min() &&
expr->number <= std::numeric_limits<int32_t>::max()) {
int32_t i = static_cast<int32_t>(expr->number);
if (i == expr->number) {
if ((i >> 30) == (i >> 31)) {
result_type = TypeOracle::GetConstInt31Type();
} else {
result_type = TypeOracle::GetConstInt32Type();
}
}
}
std::stringstream str; std::stringstream str;
str << std::setprecision(std::numeric_limits<double>::digits10 + 1) str << std::setprecision(std::numeric_limits<double>::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.is_negative() ? "true, 0x" : "false, 0x") << std::hex
<< expr->value.absolute_value() << std::dec << "ull)";
return VisitResult{result_type, str.str()}; return VisitResult{result_type, str.str()};
} }
...@@ -2848,7 +2848,9 @@ VisitResult ImplementationVisitor::GenerateCall( ...@@ -2848,7 +2848,9 @@ VisitResult ImplementationVisitor::GenerateCall(
// If we're currently generating a C++ macro and it's calling another macro, // 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 // then we need to make sure that we also generate C++ code for the called
// macro within the same -inl.inc file. // 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)) { if (auto* torque_macro = TorqueMacro::DynamicCast(macro)) {
auto* streams = CurrentFileStreams::Get(); auto* streams = CurrentFileStreams::Get();
SourceId file = streams ? streams->file : SourceId::Invalid(); SourceId file = streams ? streams->file : SourceId::Invalid();
...@@ -2862,14 +2864,32 @@ VisitResult ImplementationVisitor::GenerateCall( ...@@ -2862,14 +2864,32 @@ VisitResult ImplementationVisitor::GenerateCall(
std::stringstream result; std::stringstream result;
result << "("; result << "(";
bool first = true; bool first = true;
if (auto* extern_macro = ExternMacro::DynamicCast(macro)) { switch (output_type_) {
result << extern_macro->external_assembler_name() << "(state_)." case OutputType::kCSA: {
<< extern_macro->ExternalName() << "("; if (auto* extern_macro = ExternMacro::DynamicCast(macro)) {
} else { result << extern_macro->external_assembler_name() << "(state_)."
result << macro->ExternalName() << "(state_"; << extern_macro->ExternalName() << "(";
first = false; } 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()); DCHECK(!arg.IsOnStack());
if (!first) { if (!first) {
result << ", "; result << ", ";
......
...@@ -555,7 +555,8 @@ class ImplementationVisitor { ...@@ -555,7 +555,8 @@ class ImplementationVisitor {
VisitResult Visit(IncrementDecrementExpression* expr); VisitResult Visit(IncrementDecrementExpression* expr);
VisitResult Visit(AssignmentExpression* expr); VisitResult Visit(AssignmentExpression* expr);
VisitResult Visit(StringLiteralExpression* expr); VisitResult Visit(StringLiteralExpression* expr);
VisitResult Visit(NumberLiteralExpression* expr); VisitResult Visit(FloatingPointLiteralExpression* expr);
VisitResult Visit(IntegerLiteralExpression* expr);
VisitResult Visit(AssumeTypeImpossibleExpression* expr); VisitResult Visit(AssumeTypeImpossibleExpression* expr);
VisitResult Visit(TryLabelExpression* expr); VisitResult Visit(TryLabelExpression* expr);
VisitResult Visit(StatementExpression* expr); VisitResult Visit(StatementExpression* expr);
......
...@@ -10,6 +10,8 @@ ...@@ -10,6 +10,8 @@
#include <cstdint> #include <cstdint>
#include "src/numbers/integer-literal.h"
namespace v8 { namespace v8 {
namespace internal { namespace internal {
...@@ -35,6 +37,15 @@ inline uintptr_t Unsigned(intptr_t s) { return static_cast<uintptr_t>(s); } ...@@ -35,6 +37,15 @@ inline uintptr_t Unsigned(intptr_t s) { return static_cast<uintptr_t>(s); }
#endif #endif
inline bool Word32Equal(uint32_t a, uint32_t b) { return a == b; } 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 bool Word32NotEqual(uint32_t a, uint32_t b) { return a != b; }
inline int32_t ConstexprIntegerLiteralToInt32(const IntegerLiteral& i) {
return i.To<int32_t>();
}
inline int31_t ConstexprIntegerLiteralToInt31(const IntegerLiteral& i) {
return int31_t(ConstexprIntegerLiteralToInt32(i));
}
inline intptr_t ConstexprIntegerLiteralToIntptr(const IntegerLiteral& i) {
return i.To<intptr_t>();
}
} // namespace CodeStubAssembler } // namespace CodeStubAssembler
} // namespace TorqueRuntimeMacroShims } // namespace TorqueRuntimeMacroShims
......
...@@ -93,6 +93,12 @@ template <> ...@@ -93,6 +93,12 @@ template <>
V8_EXPORT_PRIVATE const ParseResultTypeId ParseResultHolder<int32_t>::id = V8_EXPORT_PRIVATE const ParseResultTypeId ParseResultHolder<int32_t>::id =
ParseResultTypeId::kInt32; ParseResultTypeId::kInt32;
template <> template <>
V8_EXPORT_PRIVATE const ParseResultTypeId ParseResultHolder<double>::id =
ParseResultTypeId::kDouble;
template <>
V8_EXPORT_PRIVATE const ParseResultTypeId
ParseResultHolder<IntegerLiteral>::id = ParseResultTypeId::kIntegerLiteral;
template <>
V8_EXPORT_PRIVATE const ParseResultTypeId V8_EXPORT_PRIVATE const ParseResultTypeId
ParseResultHolder<std::vector<std::string>>::id = ParseResultHolder<std::vector<std::string>>::id =
ParseResultTypeId::kStdVectorOfString; ParseResultTypeId::kStdVectorOfString;
...@@ -866,8 +872,8 @@ bool ProcessIfAnnotation(ParseResultIterator* child_results) { ...@@ -866,8 +872,8 @@ bool ProcessIfAnnotation(ParseResultIterator* child_results) {
return true; return true;
} }
base::Optional<ParseResult> MakeInt32(ParseResultIterator* child_results) { base::Optional<ParseResult> YieldInt32(ParseResultIterator* child_results) {
std::string value = child_results->NextAs<std::string>(); std::string value = child_results->matched_input().ToString();
size_t num_chars_converted = 0; size_t num_chars_converted = 0;
int result = 0; int result = 0;
try { try {
...@@ -884,6 +890,43 @@ base::Optional<ParseResult> MakeInt32(ParseResultIterator* child_results) { ...@@ -884,6 +890,43 @@ base::Optional<ParseResult> MakeInt32(ParseResultIterator* child_results) {
return ParseResult{result}; return ParseResult{result};
} }
base::Optional<ParseResult> 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<ParseResult> 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<ParseResult> MakeStringAnnotationParameter( base::Optional<ParseResult> MakeStringAnnotationParameter(
ParseResultIterator* child_results) { ParseResultIterator* child_results) {
std::string value = child_results->NextAs<std::string>(); std::string value = child_results->NextAs<std::string>();
...@@ -1904,29 +1947,17 @@ base::Optional<ParseResult> MakeAssignmentExpression( ...@@ -1904,29 +1947,17 @@ base::Optional<ParseResult> MakeAssignmentExpression(
return ParseResult{result}; return ParseResult{result};
} }
base::Optional<ParseResult> MakeNumberLiteralExpression( base::Optional<ParseResult> MakeFloatingPointLiteralExpression(
ParseResultIterator* child_results) { ParseResultIterator* child_results) {
auto number = child_results->NextAs<std::string>(); auto value = child_results->NextAs<double>();
// TODO(turbofan): Support 64bit literals. Expression* result = MakeNode<FloatingPointLiteralExpression>(value);
// Meanwhile, we type it as constexpr float64 when out of int32 range. return ParseResult{result};
double value = 0; }
try {
#if defined(V8_OS_SOLARIS) base::Optional<ParseResult> MakeIntegerLiteralExpression(
// stod() on Solaris does not currently support hex strings. Use strtol() ParseResultIterator* child_results) {
// specifically for hex literals until stod() support is available. auto value = child_results->NextAs<IntegerLiteral>();
if (number.find("0x") == std::string::npos && Expression* result = MakeNode<IntegerLiteralExpression>(std::move(value));
number.find("0X") == std::string::npos) {
value = std::stod(number);
} else {
value = static_cast<double>(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<NumberLiteralExpression>(value);
return ParseResult{result}; return ParseResult{result};
} }
...@@ -2086,8 +2117,19 @@ base::Optional<ParseResult> MakeClassField(ParseResultIterator* child_results) { ...@@ -2086,8 +2117,19 @@ base::Optional<ParseResult> MakeClassField(ParseResultIterator* child_results) {
// Internally, an optional field is just an indexed field where the count // Internally, an optional field is just an indexed field where the count
// is zero or one. // is zero or one.
index = MakeNode<ConditionalExpression>( index = MakeNode<ConditionalExpression>(
*index, MakeNode<NumberLiteralExpression>(1), *index,
MakeNode<NumberLiteralExpression>(0)); MakeCall(
MakeNode<Identifier>("FromConstexpr"),
{MakeNode<BasicTypeExpression>(std::vector<std::string>{},
MakeNode<Identifier>("intptr"),
std::vector<TypeExpression*>{})},
{MakeNode<IntegerLiteralExpression>(IntegerLiteral(1))}, {}),
MakeCall(
MakeNode<Identifier>("FromConstexpr"),
{MakeNode<BasicTypeExpression>(std::vector<std::string>{},
MakeNode<Identifier>("intptr"),
std::vector<TypeExpression*>{})},
{MakeNode<IntegerLiteralExpression>(IntegerLiteral(0))}, {}));
} }
index_info = ClassFieldIndexInfo{*index, optional}; index_info = ClassFieldIndexInfo{*index, optional};
} }
...@@ -2206,12 +2248,24 @@ struct TorqueGrammar : Grammar { ...@@ -2206,12 +2248,24 @@ struct TorqueGrammar : Grammar {
return false; return false;
} }
static bool MatchDecimalLiteral(InputPosition* pos) { static bool MatchIntegerLiteral(InputPosition* pos) {
InputPosition current = *pos;
bool found_digit = false;
MatchString("-", &current);
while (MatchChar(std::isdigit, &current)) found_digit = true;
if (found_digit) {
*pos = current;
return true;
}
return false;
}
static bool MatchFloatingPointLiteral(InputPosition* pos) {
InputPosition current = *pos; InputPosition current = *pos;
bool found_digit = false; bool found_digit = false;
MatchString("-", &current); MatchString("-", &current);
while (MatchChar(std::isdigit, &current)) found_digit = true; while (MatchChar(std::isdigit, &current)) found_digit = true;
MatchString(".", &current); if (!MatchString(".", &current)) return false;
while (MatchChar(std::isdigit, &current)) found_digit = true; while (MatchChar(std::isdigit, &current)) found_digit = true;
if (!found_digit) return false; if (!found_digit) return false;
*pos = current; *pos = current;
...@@ -2285,13 +2339,18 @@ struct TorqueGrammar : Grammar { ...@@ -2285,13 +2339,18 @@ struct TorqueGrammar : Grammar {
// Result: std::string // Result: std::string
Symbol externalString = {Rule({&stringLiteral}, StringLiteralUnquoteAction)}; Symbol externalString = {Rule({&stringLiteral}, StringLiteralUnquoteAction)};
// Result: std::string // Result: IntegerLiteral
Symbol decimalLiteral = { Symbol integerLiteral = {
Rule({Pattern(MatchDecimalLiteral)}, YieldMatchedInput), Rule({Pattern(MatchIntegerLiteral)}, YieldIntegerLiteral),
Rule({Pattern(MatchHexLiteral)}, YieldMatchedInput)}; Rule({Pattern(MatchHexLiteral)}, YieldIntegerLiteral)};
// Result: double
Symbol floatingPointLiteral = {
Rule({Pattern(MatchFloatingPointLiteral)}, YieldDouble)};
// Result: int32_t // Result: int32_t
Symbol int32Literal = {Rule({&decimalLiteral}, MakeInt32)}; Symbol int32Literal = {Rule({Pattern(MatchIntegerLiteral)}, YieldInt32),
Rule({Pattern(MatchHexLiteral)}, YieldInt32)};
// Result: AnnotationParameter // Result: AnnotationParameter
Symbol annotationParameter = { Symbol annotationParameter = {
...@@ -2510,7 +2569,8 @@ struct TorqueGrammar : Grammar { ...@@ -2510,7 +2569,8 @@ struct TorqueGrammar : Grammar {
MakeReferenceFieldAccessExpression), MakeReferenceFieldAccessExpression),
Rule({&primaryExpression, Token("["), expression, Token("]")}, Rule({&primaryExpression, Token("["), expression, Token("]")},
MakeElementAccessExpression), MakeElementAccessExpression),
Rule({&decimalLiteral}, MakeNumberLiteralExpression), Rule({&integerLiteral}, MakeIntegerLiteralExpression),
Rule({&floatingPointLiteral}, MakeFloatingPointLiteralExpression),
Rule({&stringLiteral}, MakeStringLiteralExpression), Rule({&stringLiteral}, MakeStringLiteralExpression),
Rule({&simpleType, &initializerList}, MakeStructExpression), Rule({&simpleType, &initializerList}, MakeStructExpression),
Rule({&newExpression}), Rule({&newExpression}),
......
...@@ -315,6 +315,10 @@ class TypeOracle : public ContextualClass<TypeOracle> { ...@@ -315,6 +315,10 @@ class TypeOracle : public ContextualClass<TypeOracle> {
return Get().GetBuiltinType(CONST_FLOAT64_TYPE_STRING); return Get().GetBuiltinType(CONST_FLOAT64_TYPE_STRING);
} }
static const Type* GetIntegerLiteralType() {
return Get().GetBuiltinType(INTEGER_LITERAL_TYPE_STRING);
}
static const Type* GetNeverType() { static const Type* GetNeverType() {
return Get().GetBuiltinType(NEVER_TYPE_STRING); return Get().GetBuiltinType(NEVER_TYPE_STRING);
} }
......
...@@ -459,12 +459,12 @@ void TypeVisitor::VisitClassFieldsAndMethods( ...@@ -459,12 +459,12 @@ void TypeVisitor::VisitClassFieldsAndMethods(
field_size * ResidueClass::Unknown()); field_size * ResidueClass::Unknown());
if (auto literal = if (auto literal =
NumberLiteralExpression::DynamicCast(field.index->expr)) { IntegerLiteralExpression::DynamicCast(field.index->expr)) {
size_t value = static_cast<size_t>(literal->number); if (auto value = literal->value.TryTo<size_t>()) {
if (value != literal->number) { field_size *= *value;
Error("non-integral array length").Position(field.pos); } else {
Error("Not a valid field index").Position(field.pos);
} }
field_size *= value;
} else { } else {
field_size *= ResidueClass::Unknown(); field_size *= ResidueClass::Unknown();
} }
......
...@@ -850,7 +850,7 @@ void ClassType::GenerateSliceAccessor(size_t field_index) { ...@@ -850,7 +850,7 @@ void ClassType::GenerateSliceAccessor(size_t field_index) {
if (field.offset.has_value()) { if (field.offset.has_value()) {
offset_expression = offset_expression =
MakeNode<NumberLiteralExpression>(static_cast<double>(*field.offset)); MakeNode<IntegerLiteralExpression>(IntegerLiteral(*field.offset));
} else { } else {
const Field* previous = GetFieldPreceding(field_index); const Field* previous = GetFieldPreceding(field_index);
DCHECK_NOT_NULL(previous); DCHECK_NOT_NULL(previous);
...@@ -879,8 +879,8 @@ void ClassType::GenerateSliceAccessor(size_t field_index) { ...@@ -879,8 +879,8 @@ void ClassType::GenerateSliceAccessor(size_t field_index) {
std::tie(previous_element_size, std::ignore) = std::tie(previous_element_size, std::ignore) =
*SizeOf(previous->name_and_type.type); *SizeOf(previous->name_and_type.type);
Expression* previous_element_size_expression = Expression* previous_element_size_expression =
MakeNode<NumberLiteralExpression>( MakeNode<IntegerLiteralExpression>(
static_cast<double>(previous_element_size)); IntegerLiteral(previous_element_size));
// previous.length // previous.length
Expression* previous_length_expression = MakeFieldAccessExpression( Expression* previous_length_expression = MakeFieldAccessExpression(
......
...@@ -196,8 +196,8 @@ macro TestFunctionPointers(implicit context: Context)(): Boolean { ...@@ -196,8 +196,8 @@ macro TestFunctionPointers(implicit context: Context)(): Boolean {
@export @export
macro TestVariableRedeclaration(implicit context: Context)(): Boolean { macro TestVariableRedeclaration(implicit context: Context)(): Boolean {
let _var1: int31 = FromConstexpr<bool>(42 == 0) ? 0 : 1; let _var1: int31 = FromConstexpr<bool>(42 == 0) ? FromConstexpr<int31>(0) : 1;
let _var2: int31 = FromConstexpr<bool>(42 == 0) ? 1 : 0; let _var2: int31 = FromConstexpr<bool>(42 == 0) ? FromConstexpr<int31>(1) : 0;
return True; return True;
} }
......
...@@ -20,6 +20,8 @@ constexpr const char* kTestTorquePrelude = R"( ...@@ -20,6 +20,8 @@ constexpr const char* kTestTorquePrelude = R"(
type void; type void;
type never; type never;
type IntegerLiteral constexpr 'IntegerLiteral';
namespace torque_internal { namespace torque_internal {
struct Reference<T: type> { struct Reference<T: type> {
const object: HeapObject; const object: HeapObject;
...@@ -112,6 +114,8 @@ extern macro TaggedToHeapObject(Object): HeapObject ...@@ -112,6 +114,8 @@ extern macro TaggedToHeapObject(Object): HeapObject
extern macro Float64SilenceNaN(float64): float64; extern macro Float64SilenceNaN(float64): float64;
extern macro IntPtrConstant(constexpr int31): intptr; extern macro IntPtrConstant(constexpr int31): intptr;
extern macro ConstexprIntegerLiteralToInt32(constexpr IntegerLiteral): constexpr int32;
extern macro SmiFromInt32(int32): Smi;
macro FromConstexpr<To: type, From: type>(o: From): To; macro FromConstexpr<To: type, From: type>(o: From): To;
FromConstexpr<Smi, constexpr Smi>(s: constexpr Smi): Smi { FromConstexpr<Smi, constexpr Smi>(s: constexpr Smi): Smi {
...@@ -133,6 +137,15 @@ FromConstexpr<bool, constexpr bool>(b: constexpr bool): bool { ...@@ -133,6 +137,15 @@ FromConstexpr<bool, constexpr bool>(b: constexpr bool): bool {
FromConstexpr<int32, constexpr int31>(i: constexpr int31): int32 { FromConstexpr<int32, constexpr int31>(i: constexpr int31): int32 {
return %FromConstexpr<int32>(i); return %FromConstexpr<int32>(i);
} }
FromConstexpr<int32, constexpr int32>(i: constexpr int32): int32 {
return %FromConstexpr<int32>(i);
}
FromConstexpr<int32, constexpr IntegerLiteral>(i: constexpr IntegerLiteral): int32 {
return FromConstexpr<int32>(ConstexprIntegerLiteralToInt32(i));
}
FromConstexpr<Smi, constexpr IntegerLiteral>(i: constexpr IntegerLiteral): Smi {
return SmiFromInt32(FromConstexpr<int32>(i));
}
macro Cast<A : type extends Object>(implicit context: Context)(o: Object): A macro Cast<A : type extends Object>(implicit context: Context)(o: Object): A
labels CastError { labels CastError {
......
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
#ifndef V8_TORQUE_DEBUG_MACRO_SHIMS_H_ #ifndef V8_TORQUE_DEBUG_MACRO_SHIMS_H_
#define 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 "src/objects/smi.h"
#include "tools/debug_helper/debug-helper-internal.h" #include "tools/debug_helper/debug-helper-internal.h"
...@@ -81,6 +82,9 @@ inline Value<int32_t> SmiUntag(d::MemoryAccessor accessor, uintptr_t s_t) { ...@@ -81,6 +82,9 @@ inline Value<int32_t> SmiUntag(d::MemoryAccessor accessor, uintptr_t s_t) {
Smi s(s_t); Smi s(s_t);
return {d::MemoryAccessResult::kOk, s.value()}; return {d::MemoryAccessResult::kOk, s.value()};
} }
inline Value<uintptr_t> SmiFromInt32(d::MemoryAccessor accessor, int32_t i) {
return {d::MemoryAccessResult::kOk, Smi::FromInt(i).ptr()};
}
inline Value<bool> UintPtrLessThan(d::MemoryAccessor accessor, uintptr_t a, inline Value<bool> UintPtrLessThan(d::MemoryAccessor accessor, uintptr_t a,
uintptr_t b) { uintptr_t b) {
return {d::MemoryAccessResult::kOk, a < b}; return {d::MemoryAccessResult::kOk, a < b};
...@@ -101,6 +105,19 @@ inline Value<bool> Word32NotEqual(d::MemoryAccessor accessor, uint32_t a, ...@@ -101,6 +105,19 @@ inline Value<bool> Word32NotEqual(d::MemoryAccessor accessor, uint32_t a,
uint32_t b) { uint32_t b) {
return {d::MemoryAccessResult::kOk, a != b}; return {d::MemoryAccessResult::kOk, a != b};
} }
// This is used in a nested call where we cannot pass Value<int32_t>.
inline int31_t ConstexprIntegerLiteralToInt31(d::MemoryAccessor accessor,
const IntegerLiteral& i) {
return i.To<int32_t>();
}
inline int32_t ConstexprIntegerLiteralToInt32(d::MemoryAccessor accessor,
const IntegerLiteral& i) {
return i.To<int32_t>();
}
inline intptr_t ConstexprIntegerLiteralToIntptr(d::MemoryAccessor accessor,
const IntegerLiteral& i) {
return i.To<intptr_t>();
}
} // namespace CodeStubAssembler } // namespace CodeStubAssembler
} // namespace TorqueDebugMacroShims } // namespace TorqueDebugMacroShims
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment