blob: 87327ef2858d5810cfb74ba23e29ac3d631a0e3f [file] [log] [blame]
// 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.
#include "src/objects/turboshaft-types.h"
extern enum AbortReason { kTurboshaftTypeAssertionFailed, ...}
extern macro Abort(constexpr AbortReason): never;
bitfield struct TurboshaftFloatSpecialValues extends uint32 {
nan: bool: 1 bit;
minus_zero: bool: 1 bit;
_unused: uint32: 30 bit;
}
@abstract
extern class TurboshaftType extends HeapObject {}
@generateBodyDescriptor
@generateUniqueMap
@generateFactoryFunction
extern class TurboshaftWord32Type extends TurboshaftType {}
@generateBodyDescriptor
@generateUniqueMap
@generateFactoryFunction
extern class TurboshaftWord32RangeType extends TurboshaftWord32Type {
from: uint32;
to: uint32;
}
@generateBodyDescriptor
@generateUniqueMap
@generateFactoryFunction
extern class TurboshaftWord32SetType extends TurboshaftWord32Type {
const set_size: uint32;
elements[set_size]: uint32;
}
@generateBodyDescriptor
@generateUniqueMap
@generateFactoryFunction
extern class TurboshaftWord64Type extends TurboshaftType {}
@generateBodyDescriptor
@generateUniqueMap
@generateFactoryFunction
extern class TurboshaftWord64RangeType extends TurboshaftWord64Type {
from_high: uint32;
from_low: uint32;
to_high: uint32;
to_low: uint32;
}
@generateBodyDescriptor
@generateUniqueMap
@generateFactoryFunction
extern class TurboshaftWord64SetType extends TurboshaftWord64Type {
const set_size: uint32;
elements_high[set_size]: uint32;
elements_low[set_size]: uint32;
}
@generateBodyDescriptor
@generateUniqueMap
@generateFactoryFunction
extern class TurboshaftFloat64Type extends TurboshaftType {
special_values: TurboshaftFloatSpecialValues;
}
@generateBodyDescriptor
@generateUniqueMap
@generateFactoryFunction
extern class TurboshaftFloat64RangeType extends TurboshaftFloat64Type {
_padding: uint32;
min: float64;
max: float64;
}
@generateBodyDescriptor
@generateUniqueMap
@generateFactoryFunction
extern class TurboshaftFloat64SetType extends TurboshaftFloat64Type {
const set_size: uint32;
elements[set_size]: float64;
}
macro TestTurboshaftWord32Type(
value: uint32, expected: TurboshaftWord32Type): bool {
typeswitch (expected) {
case (range: TurboshaftWord32RangeType): {
if (range.from > range.to) {
return value <= range.to || range.from <= value;
}
return range.from <= value && value <= range.to;
}
case (set: TurboshaftWord32SetType): {
for (let i: uint32 = 0; i < set.set_size; ++i) {
if (set.elements[i] == value) return true;
}
return false;
}
case (TurboshaftWord32Type): {
unreachable;
}
}
}
macro CompareUint64HighLow(
lhsHigh: uint32, lhsLow: uint32, rhsHigh: uint32, rhsLow: uint32): int32 {
if (lhsHigh == rhsHigh) {
if (lhsLow == rhsLow) return 0;
return lhsLow < rhsLow ? Convert<int32>(-1) : 1;
} else {
return lhsHigh < rhsHigh ? Convert<int32>(-1) : 1;
}
}
macro TestTurboshaftWord64Type(
valueHigh: uint32, valueLow: uint32, expected: TurboshaftWord64Type): bool {
typeswitch (expected) {
case (range: TurboshaftWord64RangeType): {
const greaterThanOrEqualFrom =
CompareUint64HighLow(
valueHigh, valueLow, range.from_high, range.from_low) >= 0;
const lessThanOrEqualTo =
CompareUint64HighLow(
valueHigh, valueLow, range.to_high, range.to_low) <= 0;
const isWrapping =
CompareUint64HighLow(
range.from_high, range.from_low, range.to_high, range.to_low) > 0;
return (isWrapping && (greaterThanOrEqualFrom || lessThanOrEqualTo)) ||
(greaterThanOrEqualFrom && lessThanOrEqualTo);
}
case (set: TurboshaftWord64SetType): {
for (let i: uint32 = 0; i < set.set_size; ++i) {
if (CompareUint64HighLow(
set.elements_high[i], set.elements_low[i], valueHigh,
valueLow) == 0) {
return true;
}
}
return false;
}
case (TurboshaftWord64Type): {
unreachable;
}
}
}
macro TestTurboshaftFloat64Type(
value: float64, expected: TurboshaftFloat64Type): bool {
if (Float64IsNaN(value)) return expected.special_values.nan;
if (IsMinusZero(value)) return expected.special_values.minus_zero;
const kMaxRelativeError = 0.0000001;
typeswitch (expected) {
case (range: TurboshaftFloat64RangeType): {
return (range.min < value ||
Float64AlmostEqual(range.min, value, kMaxRelativeError)) &&
(value < range.max ||
Float64AlmostEqual(value, range.max, kMaxRelativeError));
}
case (set: TurboshaftFloat64SetType): {
for (let i: uint32 = 0; i < set.set_size; ++i) {
if (Float64AlmostEqual(set.elements[i], value, kMaxRelativeError)) {
return true;
}
}
return false;
}
case (TurboshaftFloat64Type): {
unreachable;
}
}
}
builtin CheckTurboshaftWord32Type(
implicit context: Context)(value: uint32,
expectedType: TurboshaftWord32Type, nodeId: Smi): Undefined {
if (TestTurboshaftWord32Type(value, expectedType)) {
return Undefined;
}
Print('Type assertion failed!');
Print('Node id', nodeId);
Print('Actual value', Convert<Number>(value));
Print('Expected type', expectedType);
Abort(AbortReason::kTurboshaftTypeAssertionFailed);
}
builtin CheckTurboshaftWord64Type(
implicit context: Context)(valueHigh: uint32, valueLow: uint32,
expectedType: TurboshaftWord64Type, nodeId: Smi): Undefined {
if (TestTurboshaftWord64Type(valueHigh, valueLow, expectedType)) {
return Undefined;
}
Print('Type assertion failed!');
Print('Node id', nodeId);
Print('Actual value (high)', Convert<Number>(valueHigh));
Print('Actual vlaue (low)', Convert<Number>(valueLow));
Print('Expected type', expectedType);
Abort(AbortReason::kTurboshaftTypeAssertionFailed);
}
// Builtin needs custom interface descriptor to allow float32 argument type.
@customInterfaceDescriptor
builtin CheckTurboshaftFloat32Type(
implicit context: Context)(value: float32,
expectedType: TurboshaftFloat64Type, nodeId: Smi): Undefined {
const v = Convert<float64>(value);
if (TestTurboshaftFloat64Type(v, expectedType)) {
return Undefined;
}
Print('Type assertion failed!');
Print('Node id', nodeId);
Print('Actual value', v);
Print('Expected type', expectedType);
Abort(AbortReason::kTurboshaftTypeAssertionFailed);
}
// Builtin needs custom interface descriptor to allow float64 argument type.
@customInterfaceDescriptor
builtin CheckTurboshaftFloat64Type(
implicit context: Context)(value: float64,
expectedType: TurboshaftFloat64Type, nodeId: Smi): Undefined {
if (TestTurboshaftFloat64Type(value, expectedType)) {
return Undefined;
}
Print('Type assertion failed!');
Print('Node id', nodeId);
Print('Actual value', value);
Print('Expected type', expectedType);
Abort(AbortReason::kTurboshaftTypeAssertionFailed);
}
@customInterfaceDescriptor
builtin DebugPrintWordPtr(
implicit context: Context)(value: uintptr): Undefined {
Print('DebugPrint (word): ', value);
return Undefined;
}
@customInterfaceDescriptor
builtin DebugPrintFloat64(
implicit context: Context)(value: float64): Undefined {
Print('DebugPrint (float64): ', value);
return Undefined;
}