[torque] Turn implicit converts/unsafe_casts into generics
In the process: - Add strict ordering of Types so that name mangling is consistent and build time. Previously, the UnionType stored the union's types in a std::set<const Type*>, which did not have a consistent ordering of the types in the set. - Add a int31 type to enable consistency and correctness of handling of 'constexpr int31' values on the C++ side. - By removing the "implicit" keyword for operators, there is now one less difference between operators and calls, another incremental step in unifying operators and calls. - Enable external (i.e. C++-defined) generic specializations - Add CSA support for checking double ElementsKinds, including tests. - Clean up some constexpr/non-constexpr handling of ElementsKinds. Bug: v8:7793 Change-Id: I27699aba70b98ebf5466e5b62b045d7b1dad62c8 Reviewed-on: https://chromium-review.googlesource.com/1091155 Commit-Queue: Daniel Clifford <danno@chromium.org> Reviewed-by: Tobias Tebbi <tebbi@chromium.org> Cr-Commit-Position: refs/heads/master@{#53664}
This commit is contained in:
parent
25fbd95079
commit
bbbfd81cfc
@ -529,6 +529,10 @@ module array {
|
||||
}
|
||||
|
||||
type CompareBuiltinFn = builtin(Context, Object, Object, Object) => Number;
|
||||
extern macro UnsafeCastObjectToCompareBuiltinFn(Object): CompareBuiltinFn;
|
||||
unsafe_cast<CompareBuiltinFn>(o: Object): CompareBuiltinFn {
|
||||
return UnsafeCastObjectToCompareBuiltinFn(o);
|
||||
}
|
||||
|
||||
builtin SortCompareDefault(
|
||||
context: Context, comparefn: Object, x: Object, y: Object): Number {
|
||||
@ -928,14 +932,11 @@ module array {
|
||||
sort_state[kElementsIdx()] = a.elements;
|
||||
sort_state[kRandomStateIdx()] = nofNonUndefined;
|
||||
|
||||
// TODO(szuend): Extract into IsDoubleElementsKind when bool types are
|
||||
// fixed in Torque.
|
||||
if (elementsKind == convert<ElementsKind>(PACKED_DOUBLE_ELEMENTS) ||
|
||||
elementsKind == convert<ElementsKind>(HOLEY_DOUBLE_ELEMENTS)) {
|
||||
if (IsDoubleElementsKind(elementsKind)) {
|
||||
ArrayQuickSort<FastDoubleElements>(
|
||||
context, sort_state, 0, nofNonUndefined);
|
||||
} else {
|
||||
if (elementsKind == convert<ElementsKind>(PACKED_SMI_ELEMENTS)) {
|
||||
if (elementsKind == PACKED_SMI_ELEMENTS) {
|
||||
ArrayQuickSort<FastPackedSmiElements>(
|
||||
context, sort_state, 0, nofNonUndefined);
|
||||
} else {
|
||||
|
@ -18,7 +18,7 @@ type float32 generates 'TNode<Float32T>' constexpr 'float';
|
||||
type float64 generates 'TNode<Float64T>' constexpr 'double';
|
||||
type bool generates 'TNode<BoolT>' constexpr 'bool';
|
||||
|
||||
type int31 extends int32 generates 'TNode<Int32T>' constexpr 'int32_t';
|
||||
type int31 extends int32 generates 'TNode<Int32T>' constexpr 'int31_t';
|
||||
type RawPtr generates 'TNode<RawPtrT>' constexpr 'void*';
|
||||
type AbstractCode extends HeapObject generates 'TNode<AbstractCode>';
|
||||
type Code extends AbstractCode generates 'TNode<Code>';
|
||||
@ -188,7 +188,9 @@ extern operator '>=' macro SmiGreaterThanOrEqual(Smi, Smi): bool;
|
||||
|
||||
extern operator '==' macro ElementsKindEqual(
|
||||
constexpr ElementsKind, constexpr ElementsKind): constexpr bool;
|
||||
extern operator '==' macro ElementsKindEqual(ElementsKind, ElementsKind): bool;
|
||||
extern macro IsFastElementsKind(constexpr ElementsKind): constexpr bool;
|
||||
extern macro IsDoubleElementsKind(constexpr ElementsKind): constexpr bool;
|
||||
|
||||
extern macro SmiAbove(Smi, Smi): bool;
|
||||
|
||||
@ -260,13 +262,13 @@ extern macro TaggedToHeapObject(Object): HeapObject labels CastError;
|
||||
extern macro TaggedToSmi(Object): Smi labels CastError;
|
||||
extern macro TaggedToJSArray(Object): JSArray labels CastError;
|
||||
extern macro TaggedToCallable(Object): Callable labels CastError;
|
||||
extern macro ConvertFixedArrayBaseToFixedArray(
|
||||
FixedArrayBase): FixedArray labels CastError;
|
||||
extern macro ConvertFixedArrayBaseToFixedDoubleArray(
|
||||
FixedArrayBase): FixedDoubleArray labels CastError;
|
||||
extern macro ConvertFixedArrayBaseToFixedArray(FixedArrayBase):
|
||||
FixedArray labels CastError;
|
||||
extern macro ConvertFixedArrayBaseToFixedDoubleArray(FixedArrayBase):
|
||||
FixedDoubleArray labels CastError;
|
||||
extern macro TaggedToNumber(Object): Number labels CastError;
|
||||
|
||||
macro cast<A : type>(o: Object): A labels CastError;
|
||||
macro cast<A: type>(o: Object): A labels CastError;
|
||||
cast<Number>(o: Object): Number labels CastError {
|
||||
return TaggedToNumber(o) otherwise CastError;
|
||||
}
|
||||
@ -285,7 +287,7 @@ cast<Callable>(o: Object): Callable labels CastError {
|
||||
cast<JSArray>(o: Object): JSArray labels CastError {
|
||||
return TaggedToJSArray(o) otherwise CastError;
|
||||
}
|
||||
macro cast<A : type>(o: FixedArrayBase): A labels CastError;
|
||||
macro cast<A: type>(o: FixedArrayBase): A labels CastError;
|
||||
cast<FixedArray>(o: FixedArrayBase): FixedArray labels CastError {
|
||||
return ConvertFixedArrayBaseToFixedArray(o) otherwise CastError;
|
||||
}
|
||||
@ -294,36 +296,153 @@ cast<FixedDoubleArray>(o: FixedArrayBase): FixedDoubleArray labels CastError {
|
||||
}
|
||||
|
||||
extern macro AllocateHeapNumberWithValue(float64): HeapNumber;
|
||||
extern macro ChangeInt32ToTagged(int32): Number;
|
||||
extern macro ChangeUint32ToTagged(uint32): Number;
|
||||
extern macro Unsigned(int32): uint32;
|
||||
extern macro TruncateIntPtrToInt32(intptr): int32;
|
||||
extern macro SmiTag(intptr): Smi;
|
||||
extern macro SmiFromInt32(int32): Smi;
|
||||
extern macro SmiUntag(Smi): intptr;
|
||||
extern macro SmiToInt32(Smi): int32;
|
||||
extern macro LoadHeapNumberValue(HeapNumber): float64;
|
||||
extern macro ChangeFloat32ToFloat64(float32): float64;
|
||||
extern macro ChangeNumberToFloat64(Number): float64;
|
||||
|
||||
extern implicit operator
|
||||
'convert<>' macro NumberConstant(constexpr float64): Number;
|
||||
extern implicit operator
|
||||
'convert<>' macro IntPtrConstant(constexpr int31): intptr;
|
||||
extern implicit operator
|
||||
'convert<>' macro Int32Constant(constexpr int31): int32;
|
||||
extern implicit operator
|
||||
'convert<>' macro Int32Constant(constexpr int32): int32;
|
||||
extern implicit operator 'convert<>' macro SmiConstant(constexpr int31): Smi;
|
||||
extern implicit operator
|
||||
'convert<>' macro NumberConstant(constexpr int31): Number;
|
||||
extern implicit operator 'convert<>' macro BoolConstant(constexpr bool): bool;
|
||||
extern implicit operator 'convert<>' macro LanguageModeConstant(
|
||||
constexpr LanguageMode): LanguageMode;
|
||||
extern operator
|
||||
'convert<>' macro Int32Constant(constexpr ElementsKind): ElementsKind;
|
||||
extern implicit operator 'convert<>' macro SmiFromInt32(ElementsKind): Smi;
|
||||
extern macro NumberConstant(constexpr float64): Number;
|
||||
extern macro NumberConstant(constexpr int32): Number;
|
||||
extern macro IntPtrConstant(constexpr int31): intptr;
|
||||
extern macro IntPtrConstant(constexpr int32): intptr;
|
||||
extern macro Int32Constant(constexpr int31): int32;
|
||||
extern macro Int32Constant(constexpr int32): int32;
|
||||
extern macro SmiConstant(constexpr int31): Smi;
|
||||
extern macro BoolConstant(constexpr bool): bool;
|
||||
extern macro LanguageModeConstant(constexpr LanguageMode): LanguageMode;
|
||||
extern macro Int32Constant(constexpr ElementsKind): ElementsKind;
|
||||
|
||||
extern operator 'convert<>' macro ChangeInt32ToTagged(int32): Number;
|
||||
extern operator 'convert<>' macro ChangeUint32ToTagged(uint32): Number;
|
||||
extern operator 'convert<>' macro UncheckedCastInt32ToUint32(int32): uint32;
|
||||
extern operator 'convert<>' macro TruncateWordToWord32(intptr): int32;
|
||||
extern operator 'convert<>' macro SmiTag(intptr): Smi;
|
||||
extern operator 'convert<>' macro SmiFromInt32(int32): Smi;
|
||||
extern operator 'convert<>' macro SmiUntag(Smi): intptr;
|
||||
extern operator 'convert<>' macro SmiToInt32(Smi): int32;
|
||||
extern operator 'convert<>' macro LoadHeapNumberValue(HeapNumber): float64;
|
||||
extern operator 'convert<>' macro ChangeFloat32ToFloat64(float32): float64;
|
||||
extern operator 'convert<>' macro ChangeNumberToFloat64(Number): float64;
|
||||
macro from_constexpr<A: type>(o: constexpr int31): A;
|
||||
from_constexpr<intptr>(i: constexpr int31): intptr {
|
||||
return IntPtrConstant(i);
|
||||
}
|
||||
from_constexpr<int32>(i: constexpr int31): int32 {
|
||||
return Int32Constant(i);
|
||||
}
|
||||
from_constexpr<Smi>(i: constexpr int31): Smi {
|
||||
return SmiConstant(i);
|
||||
}
|
||||
from_constexpr<Number>(i: constexpr int31): Number {
|
||||
return SmiConstant(i);
|
||||
}
|
||||
macro from_constexpr<A: type>(o: constexpr int32): A;
|
||||
from_constexpr<intptr>(i: constexpr int32): intptr {
|
||||
return IntPtrConstant(i);
|
||||
}
|
||||
from_constexpr<int32>(i: constexpr int32): int32 {
|
||||
return Int32Constant(2);
|
||||
}
|
||||
from_constexpr<Number>(i: constexpr int32): Number {
|
||||
return NumberConstant(i);
|
||||
}
|
||||
macro from_constexpr<A: type>(o: constexpr float64): A;
|
||||
from_constexpr<Number>(f: constexpr float64): Number {
|
||||
return NumberConstant(f);
|
||||
}
|
||||
macro from_constexpr<A: type>(b: constexpr bool): A;
|
||||
from_constexpr<bool>(b: constexpr bool): bool {
|
||||
return BoolConstant(b);
|
||||
}
|
||||
macro from_constexpr<A: type>(l: constexpr LanguageMode): A;
|
||||
from_constexpr<LanguageMode>(b: constexpr LanguageMode): LanguageMode {
|
||||
return LanguageModeConstant(b);
|
||||
}
|
||||
macro from_constexpr<A: type>(e: constexpr ElementsKind): A;
|
||||
from_constexpr<ElementsKind>(e: constexpr ElementsKind): ElementsKind {
|
||||
return Int32Constant(e);
|
||||
}
|
||||
|
||||
macro convert<A: type>(i: int32): A;
|
||||
convert<Number>(i: int32): Number {
|
||||
return ChangeInt32ToTagged(i);
|
||||
}
|
||||
convert<uint32>(i: int32): uint32 {
|
||||
return Unsigned(i);
|
||||
}
|
||||
convert<Smi>(i: int32): Smi {
|
||||
return SmiFromInt32(i);
|
||||
}
|
||||
macro convert<A: type>(ui: uint32): A;
|
||||
convert<Number>(ui: uint32): Number {
|
||||
return ChangeUint32ToTagged(ui);
|
||||
}
|
||||
macro convert<A: type>(i: intptr): A;
|
||||
convert<int32>(i: intptr): int32 {
|
||||
return TruncateIntPtrToInt32(i);
|
||||
}
|
||||
convert<Smi>(i: intptr): Smi {
|
||||
return SmiTag(i);
|
||||
}
|
||||
macro convert<A: type>(s: Smi): A;
|
||||
convert<intptr>(s: Smi): intptr {
|
||||
return SmiUntag(s);
|
||||
}
|
||||
convert<int32>(s: Smi): int32 {
|
||||
return SmiToInt32(s);
|
||||
}
|
||||
macro convert<A: type>(h: HeapNumber): A;
|
||||
convert<float64>(h: HeapNumber): float64 {
|
||||
return LoadHeapNumberValue(h);
|
||||
}
|
||||
macro convert<A: type>(n: Number): A;
|
||||
convert<float64>(n: Number): float64 {
|
||||
return ChangeNumberToFloat64(n);
|
||||
}
|
||||
macro convert<A: type>(f: float32): A;
|
||||
convert<float64>(f: float32): float64 {
|
||||
return ChangeFloat32ToFloat64(f);
|
||||
}
|
||||
|
||||
extern macro UnsafeCastNumberToHeapNumber(Number): HeapNumber;
|
||||
extern macro UnsafeCastObjectToFixedArray(Object): FixedArray;
|
||||
extern macro UnsafeCastObjectToFixedDoubleArray(Object): FixedDoubleArray;
|
||||
extern macro UnsafeCastObjectToHeapNumber(Object): HeapNumber;
|
||||
extern macro UnsafeCastObjectToCallable(Object): Callable;
|
||||
extern macro UnsafeCastObjectToSmi(Object): Smi;
|
||||
extern macro UnsafeCastObjectToNumber(Object): Number;
|
||||
extern macro UnsafeCastObjectToHeapObject(Object): HeapObject;
|
||||
extern macro UnsafeCastObjectToJSArray(Object): JSArray;
|
||||
extern macro UnsafeCastObjectToFixedTypedArrayBase(Object): FixedTypedArrayBase;
|
||||
|
||||
macro unsafe_cast<A: type>(n: Number): A;
|
||||
unsafe_cast<HeapNumber>(n: Number): HeapNumber {
|
||||
return UnsafeCastNumberToHeapNumber(n);
|
||||
}
|
||||
macro unsafe_cast<A: type>(o: Object): A;
|
||||
unsafe_cast<FixedArray>(o: Object): FixedArray {
|
||||
return UnsafeCastObjectToFixedArray(o);
|
||||
}
|
||||
unsafe_cast<FixedDoubleArray>(o: Object): FixedDoubleArray {
|
||||
return UnsafeCastObjectToFixedDoubleArray(o);
|
||||
}
|
||||
unsafe_cast<HeapNumber>(o: Object): HeapNumber {
|
||||
return UnsafeCastObjectToHeapNumber(o);
|
||||
}
|
||||
unsafe_cast<Callable>(o: Object): Callable {
|
||||
return UnsafeCastObjectToCallable(o);
|
||||
}
|
||||
unsafe_cast<Smi>(o: Object): Smi {
|
||||
return UnsafeCastObjectToSmi(o);
|
||||
}
|
||||
unsafe_cast<Number>(o: Object): Number {
|
||||
return UnsafeCastObjectToNumber(o);
|
||||
}
|
||||
unsafe_cast<HeapObject>(o: Object): HeapObject {
|
||||
return UnsafeCastObjectToHeapObject(o);
|
||||
}
|
||||
unsafe_cast<JSArray>(o: Object): JSArray {
|
||||
return UnsafeCastObjectToJSArray(o);
|
||||
}
|
||||
unsafe_cast<FixedTypedArrayBase>(o: Object): FixedTypedArrayBase {
|
||||
return UnsafeCastObjectToFixedTypedArrayBase(o);
|
||||
}
|
||||
|
||||
extern macro BranchIfFastJSArray(Object, Context): never labels Taken, NotTaken;
|
||||
extern macro BranchIfNotFastJSArray(Object, Context): never labels Taken,
|
||||
@ -356,7 +475,7 @@ extern operator '.length' macro LoadFixedArrayBaseLength(FixedArrayBase): Smi;
|
||||
extern operator '[]' macro LoadFixedArrayElement(FixedArray, intptr): Object;
|
||||
extern operator '[]' macro LoadFixedArrayElement(FixedArray, Smi): Object;
|
||||
extern operator
|
||||
'[]' macro LoadFixedArrayElementInt(FixedArray, constexpr int31): Object;
|
||||
'[]' macro LoadFixedArrayElementInt(FixedArray, constexpr int31): Object;
|
||||
extern operator
|
||||
'[]=' macro StoreFixedArrayElement(FixedArray, intptr, Object): void;
|
||||
extern operator
|
||||
@ -376,6 +495,7 @@ macro StoreFixedDoubleArrayElementWithSmiIndex(
|
||||
}
|
||||
|
||||
extern macro IsFastElementsKind(ElementsKind): bool;
|
||||
extern macro IsDoubleElementsKind(ElementsKind): bool;
|
||||
extern macro IsFastSmiOrTaggedElementsKind(ElementsKind): bool;
|
||||
extern macro IsFastSmiElementsKind(ElementsKind): bool;
|
||||
extern macro IsHoleyFastElementsKind(ElementsKind): bool;
|
||||
|
@ -33,10 +33,6 @@ class DataViewBuiltinsAssembler : public BaseBuiltinsFromDSLAssembler {
|
||||
return UncheckedCast<Int32T>(
|
||||
Load(MachineType::Int8(), data_pointer, offset));
|
||||
}
|
||||
|
||||
TNode<Uint32T> UncheckedCastInt32ToUint32(TNode<Int32T> value) {
|
||||
return Unsigned(value);
|
||||
}
|
||||
};
|
||||
|
||||
int32_t DataViewElementSize(ElementsKind elements_kind) {
|
||||
|
@ -193,7 +193,7 @@ module data_view {
|
||||
extern runtime DataViewGetBigUint64(Context, Object, Object, Object): Number;
|
||||
|
||||
extern macro ToSmiIndex(Object, Context): Smi labels RangeError;
|
||||
extern macro DataViewElementSize(constexpr ElementsKind): constexpr int32;
|
||||
extern macro DataViewElementSize(constexpr ElementsKind): constexpr int31;
|
||||
|
||||
macro DataViewGet(context: Context,
|
||||
receiver: Object,
|
||||
@ -223,7 +223,7 @@ module data_view {
|
||||
|
||||
let viewOffset: Smi = data_view.byte_offset;
|
||||
let viewSize: Smi = data_view.byte_length;
|
||||
let elementSize: Smi = convert<Smi>(DataViewElementSize(kind));
|
||||
let elementSize: Smi = DataViewElementSize(kind);
|
||||
|
||||
if (getIndex + elementSize > viewSize ||
|
||||
getIndex + elementSize < getIndex) {
|
||||
|
@ -290,42 +290,41 @@ module typed_array {
|
||||
let elements_kind: ElementsKind = array.elements_kind;
|
||||
|
||||
if (IsElementsKindGreaterThan(elements_kind, UINT32_ELEMENTS)) {
|
||||
if (elements_kind == convert<ElementsKind>(INT32_ELEMENTS)) {
|
||||
if (elements_kind == INT32_ELEMENTS) {
|
||||
loadfn = LoadFixedElement<FixedInt32Array>;
|
||||
storefn = StoreFixedElement<FixedInt32Array>;
|
||||
} else if (elements_kind == convert<ElementsKind>(FLOAT32_ELEMENTS)) {
|
||||
} else if (elements_kind == FLOAT32_ELEMENTS) {
|
||||
loadfn = LoadFixedElement<FixedFloat32Array>;
|
||||
storefn = StoreFixedElement<FixedFloat32Array>;
|
||||
} else if (elements_kind == convert<ElementsKind>(FLOAT64_ELEMENTS)) {
|
||||
} else if (elements_kind == FLOAT64_ELEMENTS) {
|
||||
loadfn = LoadFixedElement<FixedFloat64Array>;
|
||||
storefn = StoreFixedElement<FixedFloat64Array>;
|
||||
} else if (
|
||||
elements_kind == convert<ElementsKind>(UINT8_CLAMPED_ELEMENTS)) {
|
||||
} else if (elements_kind == UINT8_CLAMPED_ELEMENTS) {
|
||||
loadfn = LoadFixedElement<FixedUint8ClampedArray>;
|
||||
storefn = StoreFixedElement<FixedUint8ClampedArray>;
|
||||
} else if (elements_kind == convert<ElementsKind>(BIGUINT64_ELEMENTS)) {
|
||||
} else if (elements_kind == BIGUINT64_ELEMENTS) {
|
||||
loadfn = LoadFixedElement<FixedBigUint64Array>;
|
||||
storefn = StoreFixedElement<FixedBigUint64Array>;
|
||||
} else if (elements_kind == convert<ElementsKind>(BIGINT64_ELEMENTS)) {
|
||||
} else if (elements_kind == BIGINT64_ELEMENTS) {
|
||||
loadfn = LoadFixedElement<FixedBigInt64Array>;
|
||||
storefn = StoreFixedElement<FixedBigInt64Array>;
|
||||
} else {
|
||||
unreachable;
|
||||
}
|
||||
} else {
|
||||
if (elements_kind == convert<ElementsKind>(UINT8_ELEMENTS)) {
|
||||
if (elements_kind == UINT8_ELEMENTS) {
|
||||
loadfn = LoadFixedElement<FixedUint8Array>;
|
||||
storefn = StoreFixedElement<FixedUint8Array>;
|
||||
} else if (elements_kind == convert<ElementsKind>(INT8_ELEMENTS)) {
|
||||
} else if (elements_kind == INT8_ELEMENTS) {
|
||||
loadfn = LoadFixedElement<FixedInt8Array>;
|
||||
storefn = StoreFixedElement<FixedInt8Array>;
|
||||
} else if (elements_kind == convert<ElementsKind>(UINT16_ELEMENTS)) {
|
||||
} else if (elements_kind == UINT16_ELEMENTS) {
|
||||
loadfn = LoadFixedElement<FixedUint16Array>;
|
||||
storefn = StoreFixedElement<FixedUint16Array>;
|
||||
} else if (elements_kind == convert<ElementsKind>(INT16_ELEMENTS)) {
|
||||
} else if (elements_kind == INT16_ELEMENTS) {
|
||||
loadfn = LoadFixedElement<FixedInt16Array>;
|
||||
storefn = StoreFixedElement<FixedInt16Array>;
|
||||
} else if (elements_kind == convert<ElementsKind>(UINT32_ELEMENTS)) {
|
||||
} else if (elements_kind == UINT32_ELEMENTS) {
|
||||
loadfn = LoadFixedElement<FixedUint32Array>;
|
||||
storefn = StoreFixedElement<FixedUint32Array>;
|
||||
} else {
|
||||
|
@ -11593,6 +11593,15 @@ Node* CodeStubAssembler::IsFastElementsKind(Node* elements_kind) {
|
||||
Int32Constant(LAST_FAST_ELEMENTS_KIND));
|
||||
}
|
||||
|
||||
TNode<BoolT> CodeStubAssembler::IsDoubleElementsKind(
|
||||
TNode<Int32T> elements_kind) {
|
||||
STATIC_ASSERT(FIRST_ELEMENTS_KIND == FIRST_FAST_ELEMENTS_KIND);
|
||||
STATIC_ASSERT((PACKED_DOUBLE_ELEMENTS & 1) == 0);
|
||||
STATIC_ASSERT(PACKED_DOUBLE_ELEMENTS + 1 == HOLEY_DOUBLE_ELEMENTS);
|
||||
return Word32Equal(Word32Shr(elements_kind, Int32Constant(1)),
|
||||
Int32Constant(PACKED_DOUBLE_ELEMENTS / 2));
|
||||
}
|
||||
|
||||
Node* CodeStubAssembler::IsFastSmiOrTaggedElementsKind(Node* elements_kind) {
|
||||
STATIC_ASSERT(FIRST_ELEMENTS_KIND == FIRST_FAST_ELEMENTS_KIND);
|
||||
STATIC_ASSERT(PACKED_DOUBLE_ELEMENTS > TERMINAL_FAST_ELEMENTS_KIND);
|
||||
|
@ -180,6 +180,24 @@ struct IteratorRecord {
|
||||
#define CSA_SLOW_ASSERT(csa, ...) ((void)0)
|
||||
#endif
|
||||
|
||||
class int31_t {
|
||||
public:
|
||||
int31_t() : value_(0) {}
|
||||
int31_t(int value) : value_(value) { // NOLINT(runtime/explicit)
|
||||
DCHECK_EQ((value & 0x80000000) != 0, (value & 0x40000000) != 0);
|
||||
}
|
||||
int31_t& operator=(int value) {
|
||||
DCHECK_EQ((value & 0x80000000) != 0, (value & 0x40000000) != 0);
|
||||
value_ = value;
|
||||
return *this;
|
||||
}
|
||||
int32_t value() const { return value_; }
|
||||
operator int32_t() const { return value_; }
|
||||
|
||||
private:
|
||||
int32_t value_;
|
||||
};
|
||||
|
||||
// Provides JavaScript-specific "macro-assembler" functionality on top of the
|
||||
// CodeAssembler. By factoring the JavaScript-isms out of the CodeAssembler,
|
||||
// it's possible to add JavaScript-specific useful CodeAssembler "macros"
|
||||
@ -290,6 +308,50 @@ class V8_EXPORT_PRIVATE CodeStubAssembler : public compiler::CodeAssembler {
|
||||
return CAST(result);
|
||||
}
|
||||
|
||||
TNode<HeapNumber> UnsafeCastNumberToHeapNumber(TNode<Number> p_n) {
|
||||
return CAST(p_n);
|
||||
}
|
||||
|
||||
TNode<FixedArray> UnsafeCastObjectToFixedArray(TNode<Object> p_o) {
|
||||
return CAST(p_o);
|
||||
}
|
||||
|
||||
TNode<FixedDoubleArray> UnsafeCastObjectToFixedDoubleArray(
|
||||
TNode<Object> p_o) {
|
||||
return CAST(p_o);
|
||||
}
|
||||
|
||||
TNode<HeapNumber> UnsafeCastObjectToHeapNumber(TNode<Object> p_o) {
|
||||
return CAST(p_o);
|
||||
}
|
||||
|
||||
TNode<HeapObject> UnsafeCastObjectToCallable(TNode<Object> p_o) {
|
||||
return CAST(p_o);
|
||||
}
|
||||
|
||||
TNode<Smi> UnsafeCastObjectToSmi(TNode<Object> p_o) { return CAST(p_o); }
|
||||
|
||||
TNode<Number> UnsafeCastObjectToNumber(TNode<Object> p_o) {
|
||||
return CAST(p_o);
|
||||
}
|
||||
|
||||
TNode<HeapObject> UnsafeCastObjectToHeapObject(TNode<Object> p_o) {
|
||||
return CAST(p_o);
|
||||
}
|
||||
|
||||
TNode<JSArray> UnsafeCastObjectToJSArray(TNode<Object> p_o) {
|
||||
return CAST(p_o);
|
||||
}
|
||||
|
||||
TNode<FixedTypedArrayBase> UnsafeCastObjectToFixedTypedArrayBase(
|
||||
TNode<Object> p_o) {
|
||||
return CAST(p_o);
|
||||
}
|
||||
|
||||
TNode<Object> UnsafeCastObjectToCompareBuiltinFn(TNode<Object> p_o) {
|
||||
return p_o;
|
||||
}
|
||||
|
||||
Node* MatchesParameterMode(Node* value, ParameterMode mode);
|
||||
|
||||
#define PARAMETER_BINOP(OpName, IntPtrOpName, SmiOpName) \
|
||||
@ -1638,10 +1700,18 @@ class V8_EXPORT_PRIVATE CodeStubAssembler : public compiler::CodeAssembler {
|
||||
ParameterMode mode = INTPTR_PARAMETERS);
|
||||
|
||||
// ElementsKind helpers:
|
||||
TNode<BoolT> ElementsKindEqual(TNode<Int32T> a, TNode<Int32T> b) {
|
||||
return Word32Equal(a, b);
|
||||
}
|
||||
bool ElementsKindEqual(ElementsKind a, ElementsKind b) { return a == b; }
|
||||
Node* IsFastElementsKind(Node* elements_kind);
|
||||
bool IsFastElementsKind(ElementsKind kind) {
|
||||
return v8::internal::IsFastElementsKind(kind);
|
||||
}
|
||||
TNode<BoolT> IsDoubleElementsKind(TNode<Int32T> elements_kind);
|
||||
bool IsDoubleElementsKind(ElementsKind kind) {
|
||||
return v8::internal::IsDoubleElementsKind(kind);
|
||||
}
|
||||
Node* IsFastSmiOrTaggedElementsKind(Node* elements_kind);
|
||||
Node* IsFastSmiElementsKind(Node* elements_kind);
|
||||
Node* IsHoleyFastElementsKind(Node* elements_kind);
|
||||
|
@ -364,7 +364,10 @@ void Assembler::GetCode(Isolate* isolate, CodeDesc* desc) {
|
||||
}
|
||||
}
|
||||
if (can_opt) {
|
||||
jump_opt->set_optimizable();
|
||||
// Disable for now due to bug flushed out by unrelated CSA/Torque
|
||||
// changes
|
||||
// TODO(7839): reenable when fixed
|
||||
// jump_opt->set_optimizable();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -14,11 +14,8 @@ BUILTIN: 'builtin';
|
||||
RUNTIME: 'runtime';
|
||||
MODULE: 'module';
|
||||
JAVASCRIPT: 'javascript';
|
||||
IMPLICIT: 'implicit';
|
||||
DEFERRED: 'deferred';
|
||||
IF: 'if';
|
||||
UNSAFE_CAST_KEYWORD: 'unsafe_cast';
|
||||
CONVERT_KEYWORD: 'convert';
|
||||
FOR: 'for';
|
||||
WHILE: 'while';
|
||||
RETURN: 'return';
|
||||
@ -215,8 +212,6 @@ primaryExpression
|
||||
: helperCall
|
||||
| DECIMAL_LITERAL
|
||||
| STRING_LITERAL
|
||||
| UNSAFE_CAST_KEYWORD '<' type '>' '(' expression ')'
|
||||
| CONVERT_KEYWORD '<' type '>' '(' expression ')'
|
||||
| ('(' expression ')');
|
||||
|
||||
forInitialization : variableDeclarationWithInitialization?;
|
||||
@ -277,7 +272,7 @@ typeDeclaration : 'type' IDENTIFIER extendsDeclaration? generatesDeclaration? co
|
||||
typeAliasDeclaration : 'type' IDENTIFIER '=' type ';';
|
||||
|
||||
externalBuiltin : EXTERN JAVASCRIPT? BUILTIN IDENTIFIER optionalGenericTypeList '(' typeList ')' optionalType ';';
|
||||
externalMacro : EXTERN (IMPLICIT? 'operator' STRING_LITERAL)? MACRO IDENTIFIER optionalGenericTypeList typeListMaybeVarArgs optionalType optionalLabelList ';';
|
||||
externalMacro : EXTERN ('operator' STRING_LITERAL)? MACRO IDENTIFIER optionalGenericTypeList typeListMaybeVarArgs optionalType optionalLabelList ';';
|
||||
externalRuntime : EXTERN RUNTIME IDENTIFIER typeListMaybeVarArgs optionalType ';';
|
||||
builtinDeclaration : JAVASCRIPT? BUILTIN IDENTIFIER optionalGenericTypeList parameterList optionalType (helperBody | ';');
|
||||
genericSpecialization: IDENTIFIER genericSpecializationTypeList parameterList optionalType optionalLabelList helperBody;
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -39,63 +39,60 @@ class TorqueLexer : public antlr4::Lexer {
|
||||
RUNTIME = 24,
|
||||
MODULE = 25,
|
||||
JAVASCRIPT = 26,
|
||||
IMPLICIT = 27,
|
||||
DEFERRED = 28,
|
||||
IF = 29,
|
||||
UNSAFE_CAST_KEYWORD = 30,
|
||||
CONVERT_KEYWORD = 31,
|
||||
FOR = 32,
|
||||
WHILE = 33,
|
||||
RETURN = 34,
|
||||
CONSTEXPR = 35,
|
||||
CONTINUE = 36,
|
||||
BREAK = 37,
|
||||
GOTO = 38,
|
||||
OTHERWISE = 39,
|
||||
TRY = 40,
|
||||
LABEL = 41,
|
||||
LABELS = 42,
|
||||
TAIL = 43,
|
||||
ISNT = 44,
|
||||
IS = 45,
|
||||
LET = 46,
|
||||
EXTERN = 47,
|
||||
ASSERT_TOKEN = 48,
|
||||
CHECK_TOKEN = 49,
|
||||
UNREACHABLE_TOKEN = 50,
|
||||
DEBUG_TOKEN = 51,
|
||||
ASSIGNMENT = 52,
|
||||
ASSIGNMENT_OPERATOR = 53,
|
||||
EQUAL = 54,
|
||||
PLUS = 55,
|
||||
MINUS = 56,
|
||||
MULTIPLY = 57,
|
||||
DIVIDE = 58,
|
||||
MODULO = 59,
|
||||
BIT_OR = 60,
|
||||
BIT_AND = 61,
|
||||
BIT_NOT = 62,
|
||||
MAX = 63,
|
||||
MIN = 64,
|
||||
NOT_EQUAL = 65,
|
||||
LESS_THAN = 66,
|
||||
LESS_THAN_EQUAL = 67,
|
||||
GREATER_THAN = 68,
|
||||
GREATER_THAN_EQUAL = 69,
|
||||
SHIFT_LEFT = 70,
|
||||
SHIFT_RIGHT = 71,
|
||||
SHIFT_RIGHT_ARITHMETIC = 72,
|
||||
VARARGS = 73,
|
||||
EQUALITY_OPERATOR = 74,
|
||||
INCREMENT = 75,
|
||||
DECREMENT = 76,
|
||||
NOT = 77,
|
||||
STRING_LITERAL = 78,
|
||||
IDENTIFIER = 79,
|
||||
WS = 80,
|
||||
BLOCK_COMMENT = 81,
|
||||
LINE_COMMENT = 82,
|
||||
DECIMAL_LITERAL = 83
|
||||
DEFERRED = 27,
|
||||
IF = 28,
|
||||
FOR = 29,
|
||||
WHILE = 30,
|
||||
RETURN = 31,
|
||||
CONSTEXPR = 32,
|
||||
CONTINUE = 33,
|
||||
BREAK = 34,
|
||||
GOTO = 35,
|
||||
OTHERWISE = 36,
|
||||
TRY = 37,
|
||||
LABEL = 38,
|
||||
LABELS = 39,
|
||||
TAIL = 40,
|
||||
ISNT = 41,
|
||||
IS = 42,
|
||||
LET = 43,
|
||||
EXTERN = 44,
|
||||
ASSERT_TOKEN = 45,
|
||||
CHECK_TOKEN = 46,
|
||||
UNREACHABLE_TOKEN = 47,
|
||||
DEBUG_TOKEN = 48,
|
||||
ASSIGNMENT = 49,
|
||||
ASSIGNMENT_OPERATOR = 50,
|
||||
EQUAL = 51,
|
||||
PLUS = 52,
|
||||
MINUS = 53,
|
||||
MULTIPLY = 54,
|
||||
DIVIDE = 55,
|
||||
MODULO = 56,
|
||||
BIT_OR = 57,
|
||||
BIT_AND = 58,
|
||||
BIT_NOT = 59,
|
||||
MAX = 60,
|
||||
MIN = 61,
|
||||
NOT_EQUAL = 62,
|
||||
LESS_THAN = 63,
|
||||
LESS_THAN_EQUAL = 64,
|
||||
GREATER_THAN = 65,
|
||||
GREATER_THAN_EQUAL = 66,
|
||||
SHIFT_LEFT = 67,
|
||||
SHIFT_RIGHT = 68,
|
||||
SHIFT_RIGHT_ARITHMETIC = 69,
|
||||
VARARGS = 70,
|
||||
EQUALITY_OPERATOR = 71,
|
||||
INCREMENT = 72,
|
||||
DECREMENT = 73,
|
||||
NOT = 74,
|
||||
STRING_LITERAL = 75,
|
||||
IDENTIFIER = 76,
|
||||
WS = 77,
|
||||
BLOCK_COMMENT = 78,
|
||||
LINE_COMMENT = 79,
|
||||
DECIMAL_LITERAL = 80
|
||||
};
|
||||
|
||||
explicit TorqueLexer(antlr4::CharStream* input);
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -39,63 +39,60 @@ class TorqueParser : public antlr4::Parser {
|
||||
RUNTIME = 24,
|
||||
MODULE = 25,
|
||||
JAVASCRIPT = 26,
|
||||
IMPLICIT = 27,
|
||||
DEFERRED = 28,
|
||||
IF = 29,
|
||||
UNSAFE_CAST_KEYWORD = 30,
|
||||
CONVERT_KEYWORD = 31,
|
||||
FOR = 32,
|
||||
WHILE = 33,
|
||||
RETURN = 34,
|
||||
CONSTEXPR = 35,
|
||||
CONTINUE = 36,
|
||||
BREAK = 37,
|
||||
GOTO = 38,
|
||||
OTHERWISE = 39,
|
||||
TRY = 40,
|
||||
LABEL = 41,
|
||||
LABELS = 42,
|
||||
TAIL = 43,
|
||||
ISNT = 44,
|
||||
IS = 45,
|
||||
LET = 46,
|
||||
EXTERN = 47,
|
||||
ASSERT_TOKEN = 48,
|
||||
CHECK_TOKEN = 49,
|
||||
UNREACHABLE_TOKEN = 50,
|
||||
DEBUG_TOKEN = 51,
|
||||
ASSIGNMENT = 52,
|
||||
ASSIGNMENT_OPERATOR = 53,
|
||||
EQUAL = 54,
|
||||
PLUS = 55,
|
||||
MINUS = 56,
|
||||
MULTIPLY = 57,
|
||||
DIVIDE = 58,
|
||||
MODULO = 59,
|
||||
BIT_OR = 60,
|
||||
BIT_AND = 61,
|
||||
BIT_NOT = 62,
|
||||
MAX = 63,
|
||||
MIN = 64,
|
||||
NOT_EQUAL = 65,
|
||||
LESS_THAN = 66,
|
||||
LESS_THAN_EQUAL = 67,
|
||||
GREATER_THAN = 68,
|
||||
GREATER_THAN_EQUAL = 69,
|
||||
SHIFT_LEFT = 70,
|
||||
SHIFT_RIGHT = 71,
|
||||
SHIFT_RIGHT_ARITHMETIC = 72,
|
||||
VARARGS = 73,
|
||||
EQUALITY_OPERATOR = 74,
|
||||
INCREMENT = 75,
|
||||
DECREMENT = 76,
|
||||
NOT = 77,
|
||||
STRING_LITERAL = 78,
|
||||
IDENTIFIER = 79,
|
||||
WS = 80,
|
||||
BLOCK_COMMENT = 81,
|
||||
LINE_COMMENT = 82,
|
||||
DECIMAL_LITERAL = 83
|
||||
DEFERRED = 27,
|
||||
IF = 28,
|
||||
FOR = 29,
|
||||
WHILE = 30,
|
||||
RETURN = 31,
|
||||
CONSTEXPR = 32,
|
||||
CONTINUE = 33,
|
||||
BREAK = 34,
|
||||
GOTO = 35,
|
||||
OTHERWISE = 36,
|
||||
TRY = 37,
|
||||
LABEL = 38,
|
||||
LABELS = 39,
|
||||
TAIL = 40,
|
||||
ISNT = 41,
|
||||
IS = 42,
|
||||
LET = 43,
|
||||
EXTERN = 44,
|
||||
ASSERT_TOKEN = 45,
|
||||
CHECK_TOKEN = 46,
|
||||
UNREACHABLE_TOKEN = 47,
|
||||
DEBUG_TOKEN = 48,
|
||||
ASSIGNMENT = 49,
|
||||
ASSIGNMENT_OPERATOR = 50,
|
||||
EQUAL = 51,
|
||||
PLUS = 52,
|
||||
MINUS = 53,
|
||||
MULTIPLY = 54,
|
||||
DIVIDE = 55,
|
||||
MODULO = 56,
|
||||
BIT_OR = 57,
|
||||
BIT_AND = 58,
|
||||
BIT_NOT = 59,
|
||||
MAX = 60,
|
||||
MIN = 61,
|
||||
NOT_EQUAL = 62,
|
||||
LESS_THAN = 63,
|
||||
LESS_THAN_EQUAL = 64,
|
||||
GREATER_THAN = 65,
|
||||
GREATER_THAN_EQUAL = 66,
|
||||
SHIFT_LEFT = 67,
|
||||
SHIFT_RIGHT = 68,
|
||||
SHIFT_RIGHT_ARITHMETIC = 69,
|
||||
VARARGS = 70,
|
||||
EQUALITY_OPERATOR = 71,
|
||||
INCREMENT = 72,
|
||||
DECREMENT = 73,
|
||||
NOT = 74,
|
||||
STRING_LITERAL = 75,
|
||||
IDENTIFIER = 76,
|
||||
WS = 77,
|
||||
BLOCK_COMMENT = 78,
|
||||
LINE_COMMENT = 79,
|
||||
DECIMAL_LITERAL = 80
|
||||
};
|
||||
|
||||
enum {
|
||||
@ -731,10 +728,7 @@ class TorqueParser : public antlr4::Parser {
|
||||
HelperCallContext* helperCall();
|
||||
antlr4::tree::TerminalNode* DECIMAL_LITERAL();
|
||||
antlr4::tree::TerminalNode* STRING_LITERAL();
|
||||
antlr4::tree::TerminalNode* UNSAFE_CAST_KEYWORD();
|
||||
TypeContext* type();
|
||||
ExpressionContext* expression();
|
||||
antlr4::tree::TerminalNode* CONVERT_KEYWORD();
|
||||
|
||||
void enterRule(antlr4::tree::ParseTreeListener* listener) override;
|
||||
void exitRule(antlr4::tree::ParseTreeListener* listener) override;
|
||||
@ -1312,7 +1306,6 @@ class TorqueParser : public antlr4::Parser {
|
||||
OptionalTypeContext* optionalType();
|
||||
OptionalLabelListContext* optionalLabelList();
|
||||
antlr4::tree::TerminalNode* STRING_LITERAL();
|
||||
antlr4::tree::TerminalNode* IMPLICIT();
|
||||
|
||||
void enterRule(antlr4::tree::ParseTreeListener* listener) override;
|
||||
void exitRule(antlr4::tree::ParseTreeListener* listener) override;
|
||||
|
@ -222,7 +222,6 @@ antlrcpp::Any AstGenerator::visitExternalMacro(
|
||||
MacroDeclaration* macro = RegisterNode(new ExternalMacroDeclaration{
|
||||
Pos(context),
|
||||
context->IDENTIFIER()->getSymbol()->getText(),
|
||||
context->IMPLICIT() != nullptr,
|
||||
{},
|
||||
std::move(
|
||||
context->typeListMaybeVarArgs()->accept(this).as<ParameterList>()),
|
||||
@ -281,12 +280,12 @@ antlrcpp::Any AstGenerator::visitGenericSpecialization(
|
||||
auto name = context->IDENTIFIER()->getSymbol()->getText();
|
||||
auto specialization_parameters =
|
||||
GetTypeVector(context->genericSpecializationTypeList()->typeList());
|
||||
Statement* body = context->helperBody()->accept(this).as<Statement*>();
|
||||
return implicit_cast<Declaration*>(RegisterNode(new SpecializationDeclaration{
|
||||
Pos(context), name, specialization_parameters,
|
||||
Pos(context), name, false, specialization_parameters,
|
||||
GetOptionalParameterList(context->parameterList()),
|
||||
GetOptionalType(context->optionalType()),
|
||||
GetOptionalLabelAndTypeList(context->optionalLabelList()), body}));
|
||||
GetOptionalLabelAndTypeList(context->optionalLabelList()),
|
||||
context->helperBody()->accept(this).as<Statement*>()}));
|
||||
}
|
||||
|
||||
antlrcpp::Any AstGenerator::visitConstDeclaration(
|
||||
@ -538,14 +537,6 @@ antlrcpp::Any AstGenerator::visitPrimaryExpression(
|
||||
if (auto* e = context->STRING_LITERAL())
|
||||
return implicit_cast<Expression*>(RegisterNode(
|
||||
new StringLiteralExpression{Pos(context), e->getSymbol()->getText()}));
|
||||
if (context->CONVERT_KEYWORD())
|
||||
return implicit_cast<Expression*>(RegisterNode(new ConvertExpression{
|
||||
Pos(context), GetType(context->type()),
|
||||
context->expression()->accept(this).as<Expression*>()}));
|
||||
if (context->UNSAFE_CAST_KEYWORD())
|
||||
return implicit_cast<Expression*>(RegisterNode(new UnsafeCastExpression{
|
||||
Pos(context), GetType(context->type()),
|
||||
context->expression()->accept(this).as<Expression*>()}));
|
||||
return context->expression()->accept(this);
|
||||
}
|
||||
|
||||
|
@ -38,9 +38,7 @@ DECLARE_CONTEXTUAL_VARIABLE(CurrentSourcePosition, SourcePosition)
|
||||
V(FieldAccessExpression) \
|
||||
V(ElementAccessExpression) \
|
||||
V(AssignmentExpression) \
|
||||
V(IncrementDecrementExpression) \
|
||||
V(UnsafeCastExpression) \
|
||||
V(ConvertExpression)
|
||||
V(IncrementDecrementExpression)
|
||||
|
||||
#define AST_TYPE_EXPRESSION_NODE_KIND_LIST(V) \
|
||||
V(BasicTypeExpression) \
|
||||
@ -301,22 +299,6 @@ struct NumberLiteralExpression : Expression {
|
||||
std::string number;
|
||||
};
|
||||
|
||||
struct ConvertExpression : Expression {
|
||||
DEFINE_AST_NODE_LEAF_BOILERPLATE(ConvertExpression)
|
||||
ConvertExpression(SourcePosition p, TypeExpression* t, Expression* v)
|
||||
: Expression(kKind, p), type(t), value(v) {}
|
||||
TypeExpression* type;
|
||||
Expression* value;
|
||||
};
|
||||
|
||||
struct UnsafeCastExpression : Expression {
|
||||
DEFINE_AST_NODE_LEAF_BOILERPLATE(UnsafeCastExpression)
|
||||
UnsafeCastExpression(SourcePosition p, TypeExpression* t, Expression* v)
|
||||
: Expression(kKind, p), type(t), value(v) {}
|
||||
TypeExpression* type;
|
||||
Expression* value;
|
||||
};
|
||||
|
||||
struct ElementAccessExpression : LocationExpression {
|
||||
DEFINE_AST_NODE_LEAF_BOILERPLATE(ElementAccessExpression)
|
||||
ElementAccessExpression(SourcePosition p, Expression* a, Expression* i)
|
||||
@ -591,27 +573,26 @@ struct CallableNode : AstNode {
|
||||
|
||||
struct MacroDeclaration : CallableNode {
|
||||
DEFINE_AST_NODE_INNER_BOILERPLATE(MacroDeclaration)
|
||||
MacroDeclaration(AstNode::Kind kind, SourcePosition p, std::string n, bool i,
|
||||
MacroDeclaration(AstNode::Kind kind, SourcePosition p, std::string n,
|
||||
base::Optional<std::string> o, ParameterList pl,
|
||||
TypeExpression* r, const LabelAndTypesVector& l)
|
||||
: CallableNode(kind, p, n, pl, r, l), implicit(i), op(std::move(o)) {}
|
||||
bool implicit;
|
||||
: CallableNode(kind, p, n, pl, r, l), op(std::move(o)) {}
|
||||
base::Optional<std::string> op;
|
||||
};
|
||||
|
||||
struct ExternalMacroDeclaration : MacroDeclaration {
|
||||
DEFINE_AST_NODE_LEAF_BOILERPLATE(ExternalMacroDeclaration)
|
||||
ExternalMacroDeclaration(SourcePosition p, std::string n, bool i,
|
||||
ExternalMacroDeclaration(SourcePosition p, std::string n,
|
||||
base::Optional<std::string> o, ParameterList pl,
|
||||
TypeExpression* r, const LabelAndTypesVector& l)
|
||||
: MacroDeclaration(kKind, p, n, i, o, pl, r, l) {}
|
||||
: MacroDeclaration(kKind, p, n, o, pl, r, l) {}
|
||||
};
|
||||
|
||||
struct TorqueMacroDeclaration : MacroDeclaration {
|
||||
DEFINE_AST_NODE_LEAF_BOILERPLATE(TorqueMacroDeclaration)
|
||||
TorqueMacroDeclaration(SourcePosition p, std::string n, ParameterList pl,
|
||||
TypeExpression* r, const LabelAndTypesVector& l)
|
||||
: MacroDeclaration(kKind, p, n, false, {}, pl, r, l) {}
|
||||
: MacroDeclaration(kKind, p, n, {}, pl, r, l) {}
|
||||
};
|
||||
|
||||
struct BuiltinDeclaration : CallableNode {
|
||||
@ -666,16 +647,18 @@ struct GenericDeclaration : Declaration {
|
||||
|
||||
struct SpecializationDeclaration : Declaration {
|
||||
DEFINE_AST_NODE_LEAF_BOILERPLATE(SpecializationDeclaration)
|
||||
SpecializationDeclaration(SourcePosition p, std::string n,
|
||||
SpecializationDeclaration(SourcePosition p, std::string n, bool e,
|
||||
std::vector<TypeExpression*> gp, ParameterList pl,
|
||||
TypeExpression* r, LabelAndTypesVector l,
|
||||
Statement* b)
|
||||
: Declaration(kKind, p),
|
||||
name(std::move(n)),
|
||||
external(e),
|
||||
generic_parameters(gp),
|
||||
signature(new CallableNodeSignature{pl, r, l}),
|
||||
body(b) {}
|
||||
std::string name;
|
||||
bool external;
|
||||
std::vector<TypeExpression*> generic_parameters;
|
||||
std::unique_ptr<CallableNodeSignature> signature;
|
||||
Statement* body;
|
||||
|
@ -140,20 +140,6 @@ void DeclarationVisitor::Visit(ExternalMacroDeclaration* decl,
|
||||
}
|
||||
i->second.push_back(handler);
|
||||
}
|
||||
|
||||
if (decl->implicit) {
|
||||
if (!decl->op || *decl->op != "convert<>") {
|
||||
ReportError("implicit can only be used with cast<> operator");
|
||||
}
|
||||
|
||||
const TypeVector& parameter_types = signature.parameter_types.types;
|
||||
if (parameter_types.size() != 1 || signature.parameter_types.var_args) {
|
||||
ReportError(
|
||||
"implicit cast operators doesn't only have a single parameter");
|
||||
}
|
||||
TypeOracle::RegisterImplicitConversion(signature.return_type,
|
||||
parameter_types[0]);
|
||||
}
|
||||
}
|
||||
|
||||
void DeclarationVisitor::Visit(TorqueBuiltinDeclaration* decl,
|
||||
@ -185,7 +171,9 @@ void DeclarationVisitor::Visit(TorqueMacroDeclaration* decl,
|
||||
}
|
||||
|
||||
PushControlSplit();
|
||||
Visit(body);
|
||||
if (body != nullptr) {
|
||||
Visit(body);
|
||||
}
|
||||
auto changed_vars = PopControlSplit();
|
||||
global_context_.AddControlSplitChangedVariables(
|
||||
decl, declarations()->GetCurrentSpecializationTypeNamesVector(),
|
||||
@ -202,8 +190,14 @@ void DeclarationVisitor::Visit(GenericDeclaration* decl) {
|
||||
}
|
||||
|
||||
void DeclarationVisitor::Visit(SpecializationDeclaration* decl) {
|
||||
GenericList* generic_list = declarations()->LookupGeneric(decl->name);
|
||||
if ((decl->body != nullptr) == decl->external) {
|
||||
std::stringstream stream;
|
||||
stream << "specialization of " << decl->name
|
||||
<< " must either be marked 'extern' or have a body";
|
||||
ReportError(stream.str());
|
||||
}
|
||||
|
||||
GenericList* generic_list = declarations()->LookupGeneric(decl->name);
|
||||
// Find the matching generic specialization based on the concrete parameter
|
||||
// list.
|
||||
CallableNode* matching_callable = nullptr;
|
||||
|
@ -59,8 +59,6 @@ class DeclarationVisitor : public FileVisitor {
|
||||
Visit(expr->index);
|
||||
}
|
||||
void Visit(FieldAccessExpression* expr) { Visit(expr->object); }
|
||||
void Visit(UnsafeCastExpression* expr) { Visit(expr->value); }
|
||||
void Visit(ConvertExpression* expr) { Visit(expr->value); }
|
||||
void Visit(BlockStatement* expr) {
|
||||
Declarations::NodeScopeActivator scope(declarations(), expr);
|
||||
for (Statement* stmt : expr->statements) Visit(stmt);
|
||||
@ -344,11 +342,13 @@ class DeclarationVisitor : public FileVisitor {
|
||||
}
|
||||
|
||||
void DeclareSignature(const Signature& signature) {
|
||||
auto name_iterator = signature.parameter_names.begin();
|
||||
for (auto t : signature.types()) {
|
||||
const std::string& name(*name_iterator++);
|
||||
declarations()->DeclareParameter(name, GetParameterVariableFromName(name),
|
||||
t);
|
||||
auto type_iterator = signature.parameter_types.types.begin();
|
||||
for (auto name : signature.parameter_names) {
|
||||
const Type* t(*type_iterator++);
|
||||
if (name.size() != 0) {
|
||||
declarations()->DeclareParameter(name,
|
||||
GetParameterVariableFromName(name), t);
|
||||
}
|
||||
}
|
||||
for (auto& label : signature.labels) {
|
||||
auto label_params = label.types;
|
||||
|
@ -145,9 +145,9 @@ Label* Declarations::LookupLabel(const std::string& name) {
|
||||
return Label::cast(d);
|
||||
}
|
||||
|
||||
Macro* Declarations::LookupMacro(const std::string& name,
|
||||
const TypeVector& types) {
|
||||
Declarable* declarable = Lookup(name);
|
||||
Macro* Declarations::TryLookupMacro(const std::string& name,
|
||||
const TypeVector& types) {
|
||||
Declarable* declarable = TryLookup(name);
|
||||
if (declarable != nullptr) {
|
||||
if (declarable->IsMacroList()) {
|
||||
for (auto& m : MacroList::cast(declarable)->list()) {
|
||||
@ -158,6 +158,13 @@ Macro* Declarations::LookupMacro(const std::string& name,
|
||||
}
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Macro* Declarations::LookupMacro(const std::string& name,
|
||||
const TypeVector& types) {
|
||||
Macro* result = TryLookupMacro(name, types);
|
||||
if (result != nullptr) return result;
|
||||
std::stringstream stream;
|
||||
stream << "macro " << name << " with parameter types " << types
|
||||
<< " is not defined";
|
||||
@ -337,6 +344,16 @@ TypeVector Declarations::GetCurrentSpecializationTypeNamesVector() {
|
||||
return result;
|
||||
}
|
||||
|
||||
std::string GetGeneratedCallableName(const std::string& name,
|
||||
const TypeVector& specialized_types) {
|
||||
std::string result = name;
|
||||
for (auto type : specialized_types) {
|
||||
std::string type_string = type->MangledName();
|
||||
result += std::to_string(type_string.size()) + type_string;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
} // namespace torque
|
||||
} // namespace internal
|
||||
} // namespace v8
|
||||
|
@ -15,6 +15,8 @@ namespace v8 {
|
||||
namespace internal {
|
||||
namespace torque {
|
||||
|
||||
static constexpr const char* const kFromConstexprMacroName = "from_constexpr";
|
||||
|
||||
class Declarations {
|
||||
public:
|
||||
Declarations()
|
||||
@ -58,6 +60,7 @@ class Declarations {
|
||||
|
||||
Value* LookupValue(const std::string& name);
|
||||
|
||||
Macro* TryLookupMacro(const std::string& name, const TypeVector& types);
|
||||
Macro* LookupMacro(const std::string& name, const TypeVector& types);
|
||||
|
||||
Builtin* LookupBuiltin(const std::string& name);
|
||||
@ -199,6 +202,9 @@ class Declarations::ScopedGenericScopeChainSnapshot {
|
||||
ScopeChain::ScopedSnapshotRestorer restorer_;
|
||||
};
|
||||
|
||||
std::string GetGeneratedCallableName(const std::string& name,
|
||||
const TypeVector& specialized_types);
|
||||
|
||||
} // namespace torque
|
||||
} // namespace internal
|
||||
} // namespace v8
|
||||
|
@ -25,16 +25,6 @@ Signature FileVisitor::MakeSignature(const CallableNodeSignature* signature) {
|
||||
return result;
|
||||
}
|
||||
|
||||
std::string FileVisitor::GetGeneratedCallableName(
|
||||
const std::string& name, const TypeVector& specialized_types) {
|
||||
std::string result = name;
|
||||
for (auto type : specialized_types) {
|
||||
std::string type_string = type->MangledName();
|
||||
result += std::to_string(type_string.size()) + type_string;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
Callable* FileVisitor::LookupCall(const std::string& name,
|
||||
const TypeVector& parameter_types) {
|
||||
Callable* result = nullptr;
|
||||
|
@ -72,9 +72,6 @@ class FileVisitor {
|
||||
|
||||
Signature MakeSignature(const CallableNodeSignature* signature);
|
||||
|
||||
std::string GetGeneratedCallableName(const std::string& name,
|
||||
const TypeVector& specialized_types);
|
||||
|
||||
struct PendingSpecialization {
|
||||
SpecializationKey key;
|
||||
CallableNode* callable;
|
||||
|
@ -160,67 +160,69 @@ void ImplementationVisitor::Visit(TorqueMacroDeclaration* decl,
|
||||
|
||||
CurrentCallableActivator activator(global_context_, macro, decl);
|
||||
|
||||
header_out() << " ";
|
||||
GenerateMacroFunctionDeclaration(header_out(), "", macro);
|
||||
header_out() << ";" << std::endl;
|
||||
if (body != nullptr) {
|
||||
header_out() << " ";
|
||||
GenerateMacroFunctionDeclaration(header_out(), "", macro);
|
||||
header_out() << ";" << std::endl;
|
||||
|
||||
GenerateMacroFunctionDeclaration(
|
||||
source_out(), GetDSLAssemblerName(CurrentModule()) + "::", macro);
|
||||
source_out() << " {" << std::endl;
|
||||
GenerateMacroFunctionDeclaration(
|
||||
source_out(), GetDSLAssemblerName(CurrentModule()) + "::", macro);
|
||||
source_out() << " {" << std::endl;
|
||||
|
||||
const Variable* result_var = nullptr;
|
||||
if (macro->HasReturnValue()) {
|
||||
const Type* return_type = macro->signature().return_type;
|
||||
if (!return_type->IsConstexpr()) {
|
||||
const Variable* result_var = nullptr;
|
||||
if (macro->HasReturnValue()) {
|
||||
const Type* return_type = macro->signature().return_type;
|
||||
if (!return_type->IsConstexpr()) {
|
||||
GenerateIndent();
|
||||
source_out() << "Node* return_default = &*SmiConstant(0);" << std::endl;
|
||||
}
|
||||
VisitResult init = {return_type,
|
||||
return_type->IsConstexpr()
|
||||
? (return_type->GetGeneratedTypeName() + "()")
|
||||
: (std::string("UncheckedCast<") +
|
||||
return_type->GetGeneratedTNodeTypeName() +
|
||||
">(return_default)")};
|
||||
result_var =
|
||||
GenerateVariableDeclaration(decl, kReturnValueVariable, {}, init);
|
||||
}
|
||||
Label* macro_end = declarations()->DeclareLabel("macro_end");
|
||||
GenerateLabelDefinition(macro_end, decl);
|
||||
|
||||
const Type* result = Visit(body);
|
||||
if (result->IsNever()) {
|
||||
if (!macro->signature().return_type->IsNever() && !macro->HasReturns()) {
|
||||
std::stringstream s;
|
||||
s << "macro " << decl->name
|
||||
<< " that never returns must have return type never";
|
||||
ReportError(s.str());
|
||||
}
|
||||
} else {
|
||||
if (macro->signature().return_type->IsNever()) {
|
||||
std::stringstream s;
|
||||
s << "macro " << decl->name
|
||||
<< " has implicit return at end of its declartion but return type "
|
||||
"never";
|
||||
ReportError(s.str());
|
||||
} else if (!macro->signature().return_type->IsVoid()) {
|
||||
std::stringstream s;
|
||||
s << "macro " << decl->name
|
||||
<< " expects to return a value but doesn't on all paths";
|
||||
ReportError(s.str());
|
||||
}
|
||||
}
|
||||
if (macro->HasReturns()) {
|
||||
if (!result->IsNever()) {
|
||||
GenerateLabelGoto(macro_end);
|
||||
}
|
||||
GenerateLabelBind(macro_end);
|
||||
}
|
||||
if (result_var != nullptr) {
|
||||
GenerateIndent();
|
||||
source_out() << "Node* return_default = &*SmiConstant(0);" << std::endl;
|
||||
source_out() << "return " << result_var->GetValueForRead() << ";"
|
||||
<< std::endl;
|
||||
}
|
||||
VisitResult init = {
|
||||
return_type,
|
||||
return_type->IsConstexpr()
|
||||
? (return_type->GetGeneratedTypeName() + "()")
|
||||
: (std::string("UncheckedCast<") +
|
||||
return_type->GetGeneratedTNodeTypeName() + ">(return_default)")};
|
||||
result_var =
|
||||
GenerateVariableDeclaration(decl, kReturnValueVariable, {}, init);
|
||||
source_out() << "}" << std::endl << std::endl;
|
||||
}
|
||||
Label* macro_end = declarations()->DeclareLabel("macro_end");
|
||||
GenerateLabelDefinition(macro_end, decl);
|
||||
|
||||
const Type* result = Visit(body);
|
||||
if (result->IsNever()) {
|
||||
if (!macro->signature().return_type->IsNever() && !macro->HasReturns()) {
|
||||
std::stringstream s;
|
||||
s << "macro " << decl->name
|
||||
<< " that never returns must have return type never";
|
||||
ReportError(s.str());
|
||||
}
|
||||
} else {
|
||||
if (macro->signature().return_type->IsNever()) {
|
||||
std::stringstream s;
|
||||
s << "macro " << decl->name
|
||||
<< " has implicit return at end of its declartion but return type "
|
||||
"never";
|
||||
ReportError(s.str());
|
||||
} else if (!macro->signature().return_type->IsVoid()) {
|
||||
std::stringstream s;
|
||||
s << "macro " << decl->name
|
||||
<< " expects to return a value but doesn't on all paths";
|
||||
ReportError(s.str());
|
||||
}
|
||||
}
|
||||
if (macro->HasReturns()) {
|
||||
if (!result->IsNever()) {
|
||||
GenerateLabelGoto(macro_end);
|
||||
}
|
||||
GenerateLabelBind(macro_end);
|
||||
}
|
||||
if (result_var != nullptr) {
|
||||
GenerateIndent();
|
||||
source_out() << "return " << result_var->GetValueForRead() << ";"
|
||||
<< std::endl;
|
||||
}
|
||||
source_out() << "}" << std::endl << std::endl;
|
||||
}
|
||||
|
||||
void ImplementationVisitor::Visit(TorqueBuiltinDeclaration* decl,
|
||||
@ -520,28 +522,6 @@ VisitResult ImplementationVisitor::Visit(IdentifierExpression* expr) {
|
||||
return GenerateFetchFromLocation(expr, GetLocationReference(expr));
|
||||
}
|
||||
|
||||
VisitResult ImplementationVisitor::Visit(UnsafeCastExpression* expr) {
|
||||
const Type* type = declarations()->GetType(expr->type);
|
||||
if (type->IsConstexpr()) {
|
||||
ReportError("unsafe_cast can only be used for non constexpr types.");
|
||||
}
|
||||
|
||||
VisitResult result = Visit(expr->value);
|
||||
|
||||
std::string result_variable_name = GenerateNewTempVariable(type);
|
||||
source_out() << "CAST(";
|
||||
source_out() << result.variable();
|
||||
source_out() << ");\n";
|
||||
return VisitResult{type, result_variable_name};
|
||||
}
|
||||
|
||||
VisitResult ImplementationVisitor::Visit(ConvertExpression* expr) {
|
||||
Arguments args;
|
||||
args.parameters = {Visit(expr->value)};
|
||||
return GenerateOperation("convert<>", args,
|
||||
declarations()->GetType(expr->type));
|
||||
}
|
||||
|
||||
const Type* ImplementationVisitor::Visit(GotoStatement* stmt) {
|
||||
Label* label = declarations()->LookupLabel(stmt->label);
|
||||
|
||||
@ -1632,11 +1612,11 @@ VisitResult ImplementationVisitor::GenerateImplicitConvert(
|
||||
if (destination_type == source.type()) {
|
||||
return source;
|
||||
}
|
||||
|
||||
if (TypeOracle::IsImplicitlyConverableFrom(destination_type, source.type())) {
|
||||
VisitResult result(source.type(), source.variable());
|
||||
Arguments args;
|
||||
args.parameters = {result};
|
||||
return GenerateOperation("convert<>", args, destination_type);
|
||||
std::string name =
|
||||
GetGeneratedCallableName(kFromConstexprMacroName, {destination_type});
|
||||
return GenerateCall(name, {{source}, {}}, false);
|
||||
} else if (IsAssignableFrom(destination_type, source.type())) {
|
||||
return VisitResult(destination_type, source.variable());
|
||||
} else {
|
||||
|
@ -83,9 +83,6 @@ class ImplementationVisitor : public FileVisitor {
|
||||
return GenerateFetchFromLocation(expr, GetLocationReference(expr));
|
||||
}
|
||||
|
||||
VisitResult Visit(UnsafeCastExpression* expr);
|
||||
VisitResult Visit(ConvertExpression* expr);
|
||||
|
||||
void Visit(ModuleDeclaration* decl);
|
||||
void Visit(DefaultModuleDeclaration* decl) {
|
||||
Visit(implicit_cast<ModuleDeclaration*>(decl));
|
||||
|
@ -20,10 +20,6 @@ class TypeOracle : public ContextualClass<TypeOracle> {
|
||||
explicit TypeOracle(Declarations* declarations)
|
||||
: declarations_(declarations) {}
|
||||
|
||||
static void RegisterImplicitConversion(const Type* to, const Type* from) {
|
||||
Get().implicit_conversions_.push_back(std::make_pair(to, from));
|
||||
}
|
||||
|
||||
static const Type* GetArgumentsType() {
|
||||
return Get().GetBuiltinType(ARGUMENTS_TYPE_STRING);
|
||||
}
|
||||
@ -61,12 +57,8 @@ class TypeOracle : public ContextualClass<TypeOracle> {
|
||||
}
|
||||
|
||||
static bool IsImplicitlyConverableFrom(const Type* to, const Type* from) {
|
||||
for (auto& conversion : Get().implicit_conversions_) {
|
||||
if (conversion.first == to && conversion.second == from) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
std::string name = GetGeneratedCallableName(kFromConstexprMacroName, {to});
|
||||
return Get().declarations_->TryLookupMacro(name, {from}) != nullptr;
|
||||
}
|
||||
|
||||
private:
|
||||
@ -75,7 +67,6 @@ class TypeOracle : public ContextualClass<TypeOracle> {
|
||||
}
|
||||
|
||||
Declarations* declarations_;
|
||||
std::vector<std::pair<const Type*, const Type*>> implicit_conversions_;
|
||||
};
|
||||
|
||||
} // namespace torque
|
||||
|
@ -223,6 +223,10 @@ bool IsCompatibleSignature(const ParameterTypes& to, const TypeVector& from) {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool operator<(const Type& a, const Type& b) {
|
||||
return a.MangledName() < b.MangledName();
|
||||
}
|
||||
|
||||
} // namespace torque
|
||||
} // namespace internal
|
||||
} // namespace v8
|
||||
|
@ -5,6 +5,7 @@
|
||||
#ifndef V8_TORQUE_TYPES_H_
|
||||
#define V8_TORQUE_TYPES_H_
|
||||
|
||||
#include <algorithm>
|
||||
#include <set>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
@ -175,6 +176,13 @@ class FunctionPointerType final : public Type {
|
||||
const Type* const return_type_;
|
||||
};
|
||||
|
||||
bool operator<(const Type& a, const Type& b);
|
||||
struct TypeLess {
|
||||
bool operator()(const Type* const a, const Type* const b) const {
|
||||
return *a < *b;
|
||||
}
|
||||
};
|
||||
|
||||
class UnionType final : public Type {
|
||||
public:
|
||||
DECLARE_TYPE_BOILERPLATE(UnionType);
|
||||
@ -257,7 +265,7 @@ class UnionType final : public Type {
|
||||
private:
|
||||
explicit UnionType(const Type* t) : Type(Kind::kUnionType, t), types_({t}) {}
|
||||
|
||||
std::set<const Type*> types_;
|
||||
std::set<const Type*, TypeLess> types_;
|
||||
};
|
||||
|
||||
inline std::ostream& operator<<(std::ostream& os, const Type* t) {
|
||||
|
@ -3311,6 +3311,55 @@ TEST(SingleInputPhiElimination) {
|
||||
// single-input phi is properly eliminated.
|
||||
}
|
||||
|
||||
TEST(IsDoubleElementsKind) {
|
||||
Isolate* isolate(CcTest::InitIsolateOnce());
|
||||
const int kNumParams = 2;
|
||||
CodeAssemblerTester ft_tester(isolate, kNumParams);
|
||||
{
|
||||
CodeStubAssembler m(ft_tester.state());
|
||||
m.Return(m.SmiFromInt32(m.UncheckedCast<Int32T>(
|
||||
m.IsDoubleElementsKind(m.SmiToInt32(m.Parameter(0))))));
|
||||
}
|
||||
FunctionTester ft(ft_tester.GenerateCode(), kNumParams);
|
||||
CHECK_EQ(
|
||||
(*Handle<Smi>::cast(
|
||||
ft.Call(Handle<Smi>(Smi::FromInt(PACKED_DOUBLE_ELEMENTS), isolate))
|
||||
.ToHandleChecked()))
|
||||
->value(),
|
||||
1);
|
||||
CHECK_EQ(
|
||||
(*Handle<Smi>::cast(
|
||||
ft.Call(Handle<Smi>(Smi::FromInt(HOLEY_DOUBLE_ELEMENTS), isolate))
|
||||
.ToHandleChecked()))
|
||||
->value(),
|
||||
1);
|
||||
CHECK_EQ((*Handle<Smi>::cast(
|
||||
ft.Call(Handle<Smi>(Smi::FromInt(HOLEY_ELEMENTS), isolate))
|
||||
.ToHandleChecked()))
|
||||
->value(),
|
||||
0);
|
||||
CHECK_EQ((*Handle<Smi>::cast(
|
||||
ft.Call(Handle<Smi>(Smi::FromInt(PACKED_ELEMENTS), isolate))
|
||||
.ToHandleChecked()))
|
||||
->value(),
|
||||
0);
|
||||
CHECK_EQ((*Handle<Smi>::cast(
|
||||
ft.Call(Handle<Smi>(Smi::FromInt(PACKED_SMI_ELEMENTS), isolate))
|
||||
.ToHandleChecked()))
|
||||
->value(),
|
||||
0);
|
||||
CHECK_EQ((*Handle<Smi>::cast(
|
||||
ft.Call(Handle<Smi>(Smi::FromInt(HOLEY_SMI_ELEMENTS), isolate))
|
||||
.ToHandleChecked()))
|
||||
->value(),
|
||||
0);
|
||||
CHECK_EQ((*Handle<Smi>::cast(
|
||||
ft.Call(Handle<Smi>(Smi::FromInt(DICTIONARY_ELEMENTS), isolate))
|
||||
.ToHandleChecked()))
|
||||
->value(),
|
||||
0);
|
||||
}
|
||||
|
||||
} // namespace compiler
|
||||
} // namespace internal
|
||||
} // namespace v8
|
||||
|
@ -36,7 +36,7 @@ module test {
|
||||
}
|
||||
|
||||
macro TestConstexpr1() {
|
||||
check(convert<bool>(IsFastElementsKind(PACKED_SMI_ELEMENTS)));
|
||||
check(from_constexpr<bool>(IsFastElementsKind(PACKED_SMI_ELEMENTS)));
|
||||
}
|
||||
|
||||
macro TestConstexprIf() {
|
||||
@ -46,10 +46,10 @@ module test {
|
||||
}
|
||||
|
||||
macro TestConstexprReturn() {
|
||||
check(convert<bool>(ElementsKindTestHelper3(UINT8_ELEMENTS)));
|
||||
check(convert<bool>(ElementsKindTestHelper3(UINT16_ELEMENTS)));
|
||||
check(!convert<bool>(ElementsKindTestHelper3(UINT32_ELEMENTS)));
|
||||
check(convert<bool>(!ElementsKindTestHelper3(UINT32_ELEMENTS)));
|
||||
check(from_constexpr<bool>(ElementsKindTestHelper3(UINT8_ELEMENTS)));
|
||||
check(from_constexpr<bool>(ElementsKindTestHelper3(UINT16_ELEMENTS)));
|
||||
check(!from_constexpr<bool>(ElementsKindTestHelper3(UINT32_ELEMENTS)));
|
||||
check(from_constexpr<bool>(!ElementsKindTestHelper3(UINT32_ELEMENTS)));
|
||||
}
|
||||
|
||||
macro TestGotoLabel(): Boolean {
|
||||
|
Loading…
Reference in New Issue
Block a user