Commit 79605b45 authored by Daniel Clifford's avatar Daniel Clifford Committed by Commit Bot

[torque] Add new and refine existing Torque intrinsic support

Intrinsic changes:

- Rename %RawCast to %RawObjectCast and add error checking so that it
  only applies to subtypes of Objects.

- Add %RawPointerCast, which is similar to %RawObjectCast but must be
  used for all subtypes of RawPtr.

- Add %RawConstexprCast, which allows one constexpr to be be cast to
  another at compile time. It translate to an appropriate static_cast
  in the generated code

- Add %FromConstexpr, which handles most of the standard cases of
  generating XXXConstant CSA nodes from constexpr constants. It uses
  either SmiConstant, NumberConstant, StringConstant, IntPtrConstant
  or Int32Constant, depending on the cast-to type generic <To> type.

- Add support for intrinsics that return constexpr results.

Cleanup:

- Turn FromConstexpr into a generic with two generic types, a <To> and
  a <From> type. Most FromConstexpr can use the new %FromConstexpr
  intrinsic rather than provide an explicit implementation.

Bug: v8:7793
Change-Id: Icab5db16d203034ec157fa3ad5157d10c7dc8464
Reviewed-on: https://chromium-review.googlesource.com/c/1357049
Commit-Queue: Daniel Clifford <danno@chromium.org>
Reviewed-by: 's avatarTobias Tebbi <tebbi@chromium.org>
Cr-Commit-Position: refs/heads/master@{#58049}
parent ee8bb5f0
......@@ -6,8 +6,8 @@ type Arguments constexpr 'CodeStubArguments*';
type void;
type never;
type Tagged generates 'TNode<Object>';
type Smi extends Tagged generates 'TNode<Smi>';
type Tagged generates 'TNode<Object>' constexpr 'Object*';
type Smi extends Tagged generates 'TNode<Smi>' constexpr 'Smi*';
type HeapObject extends Tagged generates 'TNode<HeapObject>';
type Object = Smi | HeapObject;
type int32 generates 'TNode<Int32T>' constexpr 'int32_t';
......@@ -72,10 +72,12 @@ type SloppyArgumentsElements extends FixedArray
type NumberDictionary extends HeapObject
generates 'TNode<NumberDictionary>';
// RawCasts should *never* be used anywhere in Torque code except for
// RawObjectCasts should *never* be used anywhere in Torque code except for
// in Torque-based UnsafeCast operators preceeded by an appropriate
// type assert()
intrinsic %RawCast<A: type>(o: Object): A;
intrinsic %RawObjectCast<A: type>(o: Object): A;
intrinsic %RawPointerCast<A: type>(p: RawPtr): A;
intrinsic %RawConstexprCast<To: type, From: type>(f: From): To;
type NativeContextSlot generates 'TNode<IntPtrT>' constexpr 'int32_t';
const ARRAY_JOIN_STACK_INDEX: constexpr NativeContextSlot
......@@ -101,7 +103,8 @@ type JSDataView extends JSArrayBufferView generates 'TNode<JSDataView>';
type InstanceType generates 'TNode<Int32T>' constexpr 'InstanceType';
type ElementsKind generates 'TNode<Int32T>' constexpr 'ElementsKind';
type LanguageMode generates 'TNode<Smi>' constexpr 'LanguageMode';
type LanguageMode extends Tagged
generates 'TNode<Smi>' constexpr 'LanguageMode';
type ExtractFixedArrayFlags
generates 'TNode<Smi>'
constexpr 'CodeStubAssembler::ExtractFixedArrayFlags';
......@@ -564,25 +567,25 @@ CastHeapObject<JSArray>(o: HeapObject): JSArray
CastHeapObject<Context>(o: HeapObject): Context
labels CastError {
if (IsContext(o)) return %RawCast<Context>(o);
if (IsContext(o)) return %RawObjectCast<Context>(o);
goto CastError;
}
CastHeapObject<JSObject>(o: HeapObject): JSObject
labels CastError {
if (IsJSObject(o)) return %RawCast<JSObject>(o);
if (IsJSObject(o)) return %RawObjectCast<JSObject>(o);
goto CastError;
}
CastHeapObject<NumberDictionary>(o: HeapObject): NumberDictionary
labels CastError {
if (IsNumberDictionary(o)) return %RawCast<NumberDictionary>(o);
if (IsNumberDictionary(o)) return %RawObjectCast<NumberDictionary>(o);
goto CastError;
}
CastHeapObject<FixedTypedArrayBase>(o: HeapObject): FixedTypedArrayBase
labels CastError {
if (IsFixedTypedArray(o)) return %RawCast<FixedTypedArrayBase>(o);
if (IsFixedTypedArray(o)) return %RawObjectCast<FixedTypedArrayBase>(o);
goto CastError;
}
......@@ -598,13 +601,13 @@ CastHeapObject<Constructor>(o: HeapObject): Constructor
CastHeapObject<HeapNumber>(o: HeapObject): HeapNumber
labels CastError {
if (IsHeapNumber(o)) return %RawCast<HeapNumber>(o);
if (IsHeapNumber(o)) return %RawObjectCast<HeapNumber>(o);
goto CastError;
}
CastHeapObject<Map>(implicit context: Context)(o: HeapObject): Map
labels CastError {
if (IsMap(o)) return %RawCast<Map>(o);
if (IsMap(o)) return %RawObjectCast<Map>(o);
goto CastError;
}
......@@ -620,7 +623,7 @@ CastHeapObject<JSArgumentsObjectWithLength>(implicit context: Context)(
goto CastError;
}
label True {
return %RawCast<JSArgumentsObjectWithLength>(o);
return %RawObjectCast<JSArgumentsObjectWithLength>(o);
}
}
......@@ -638,7 +641,7 @@ CastHeapObject<FastJSArray>(implicit context: Context)(o: HeapObject):
if (!IsPrototypeInitialArrayPrototype(map)) goto CastError;
if (IsNoElementsProtectorCellInvalid()) goto CastError;
return %RawCast<FastJSArray>(o);
return %RawObjectCast<FastJSArray>(o);
}
CastHeapObject<FastJSArrayForCopy>(implicit context: Context)(o: HeapObject):
......@@ -646,7 +649,7 @@ CastHeapObject<FastJSArrayForCopy>(implicit context: Context)(o: HeapObject):
labels CastError {
if (IsArraySpeciesProtectorCellInvalid()) goto CastError;
const a: FastJSArray = Cast<FastJSArray>(o) otherwise CastError;
return %RawCast<FastJSArrayForCopy>(o);
return %RawObjectCast<FastJSArrayForCopy>(o);
}
CastHeapObject<FastJSArrayWithNoCustomIteration>(implicit context: Context)(
......@@ -654,18 +657,18 @@ CastHeapObject<FastJSArrayWithNoCustomIteration>(implicit context: Context)(
labels CastError {
if (IsArrayIteratorProtectorCellInvalid()) goto CastError;
const a: FastJSArray = Cast<FastJSArray>(o) otherwise CastError;
return %RawCast<FastJSArrayWithNoCustomIteration>(o);
return %RawObjectCast<FastJSArrayWithNoCustomIteration>(o);
}
CastHeapObject<JSReceiver>(implicit context: Context)(o: HeapObject): JSReceiver
labels CastError {
if (IsJSReceiver(o)) return %RawCast<JSReceiver>(o);
if (IsJSReceiver(o)) return %RawObjectCast<JSReceiver>(o);
goto CastError;
}
CastHeapObject<JSFunction>(implicit context: Context)(o: HeapObject): JSFunction
labels CastError {
if (IsJSFunction(o)) return %RawCast<JSFunction>(o);
if (IsJSFunction(o)) return %RawObjectCast<JSFunction>(o);
goto CastError;
}
......@@ -733,72 +736,72 @@ extern macro StringConstant(constexpr string): String;
extern macro LanguageModeConstant(constexpr LanguageMode): LanguageMode;
extern macro Int32Constant(constexpr ElementsKind): ElementsKind;
extern macro IntPtrConstant(constexpr NativeContextSlot): NativeContextSlot;
extern macro IntPtrConstant(constexpr intptr): intptr;
macro FromConstexpr<A: type>(o: constexpr int31): A;
FromConstexpr<intptr>(i: constexpr int31): intptr {
return IntPtrConstant(i);
extern macro BitcastWordToTaggedSigned(intptr): Smi;
extern macro BitcastWordToTagged(intptr): Object;
intrinsic %FromConstexpr<To: type, From: type>(b: From): To;
macro FromConstexpr<To: type, From: type>(o: From): To;
FromConstexpr<int31, constexpr int31>(i: constexpr int31): int31 {
return %FromConstexpr<int31>(i);
}
FromConstexpr<int31>(i: constexpr int31): int31 {
return Int32Constant(i);
FromConstexpr<int32, constexpr int31>(i: constexpr int31): int32 {
return %FromConstexpr<int32>(i);
}
FromConstexpr<int32>(i: constexpr int31): int32 {
return Int32Constant(i);
FromConstexpr<int32, constexpr int32>(i: constexpr int32): int32 {
return %FromConstexpr<int32>(i);
}
FromConstexpr<uint32>(i: constexpr int31): uint32 {
return Unsigned(Int32Constant(i));
FromConstexpr<intptr, constexpr int31>(i: constexpr int31): intptr {
return %FromConstexpr<intptr>(i);
}
FromConstexpr<uintptr>(i: constexpr int31): uintptr {
return ChangeUint32ToWord(i);
FromConstexpr<intptr, constexpr int32>(i: constexpr int32): intptr {
return %FromConstexpr<intptr>(i);
}
FromConstexpr<Smi>(i: constexpr int31): Smi {
return SmiConstant(i);
FromConstexpr<Smi, constexpr int31>(i: constexpr int31): Smi {
return %FromConstexpr<Smi>(i);
}
FromConstexpr<Number>(i: constexpr int31): Number {
return SmiConstant(i);
FromConstexpr<String, constexpr string>(s: constexpr string): String {
return %FromConstexpr<String>(s);
}
FromConstexpr<float64>(i: constexpr int31): float64 {
return Float64Constant(i);
FromConstexpr<Number, constexpr uint32>(i: constexpr uint32): Number {
return %FromConstexpr<Number>(i);
}
macro FromConstexpr<A: type>(o: constexpr uint32): A;
FromConstexpr<Number>(i: constexpr uint32): Number {
return NumberConstant(i);
FromConstexpr<Number, constexpr int32>(i: constexpr int32): Number {
return %FromConstexpr<Number>(i);
}
macro FromConstexpr<A: type>(o: constexpr int32): A;
FromConstexpr<intptr>(i: constexpr int32): intptr {
return IntPtrConstant(i);
FromConstexpr<Number, constexpr float64>(f: constexpr float64): Number {
return %FromConstexpr<Number>(f);
}
FromConstexpr<int32>(i: constexpr int32): int32 {
return Int32Constant(i);
FromConstexpr<Number, constexpr int31>(i: constexpr int31): Number {
return %FromConstexpr<Number>(i);
}
FromConstexpr<Number>(i: constexpr int32): Number {
return NumberConstant(i);
FromConstexpr<uint32, constexpr int31>(i: constexpr int31): uint32 {
return Unsigned(Int32Constant(i));
}
macro FromConstexpr<A: type>(o: constexpr float64): A;
FromConstexpr<Number>(f: constexpr float64): Number {
return NumberConstant(f);
FromConstexpr<uintptr, constexpr int31>(i: constexpr int31): uintptr {
return ChangeUint32ToWord(i);
}
FromConstexpr<float64, constexpr int31>(i: constexpr int31): float64 {
return Float64Constant(i);
}
macro FromConstexpr<A: type>(b: constexpr bool): A;
FromConstexpr<bool>(b: constexpr bool): bool {
FromConstexpr<bool, constexpr bool>(b: constexpr bool): bool {
return BoolConstant(b);
}
macro FromConstexpr<A: type>(l: constexpr LanguageMode): A;
FromConstexpr<LanguageMode>(b: constexpr LanguageMode): LanguageMode {
return LanguageModeConstant(b);
FromConstexpr<LanguageMode, constexpr LanguageMode>(m: constexpr LanguageMode):
LanguageMode {
return %RawObjectCast<LanguageMode>(%FromConstexpr<Smi>(m));
}
macro FromConstexpr<A: type>(e: constexpr ElementsKind): A;
FromConstexpr<ElementsKind>(e: constexpr ElementsKind): ElementsKind {
FromConstexpr<ElementsKind, constexpr ElementsKind>(e: constexpr ElementsKind):
ElementsKind {
return Int32Constant(e);
}
macro FromConstexpr<A: type>(s: constexpr string): A;
FromConstexpr<String>(s: constexpr string): String {
return StringConstant(s);
}
FromConstexpr<Object>(s: constexpr string): Object {
FromConstexpr<Object, constexpr string>(s: constexpr string): Object {
return StringConstant(s);
}
macro FromConstexpr<A: type>(e: constexpr NativeContextSlot): A;
FromConstexpr<NativeContextSlot>(c: constexpr NativeContextSlot):
NativeContextSlot {
FromConstexpr<NativeContextSlot, constexpr NativeContextSlot>(
c: constexpr NativeContextSlot): NativeContextSlot {
return IntPtrConstant(c);
}
......@@ -904,16 +907,16 @@ macro Is<A: type, B: type>(implicit context: Context)(o: B): bool {
macro UnsafeCast<A: type>(implicit context: Context)(o: Object): A {
assert(Is<A>(o));
return %RawCast<A>(o);
return %RawObjectCast<A>(o);
}
UnsafeCast<Object>(o: Object): Object {
return o;
}
const kCOWMap: Map = %RawCast<Map>(LoadRoot(kFixedCOWArrayMapRootIndex));
const kCOWMap: Map = %RawObjectCast<Map>(LoadRoot(kFixedCOWArrayMapRootIndex));
const kEmptyFixedArray: FixedArrayBase =
%RawCast<FixedArrayBase>(LoadRoot(kEmptyFixedArrayRootIndex));
%RawObjectCast<FixedArrayBase>(LoadRoot(kEmptyFixedArrayRootIndex));
extern macro IsPrototypeInitialArrayPrototype(implicit context: Context)(Map):
bool;
......
......@@ -22,10 +22,10 @@ namespace typed_array {
// would try to check this through an assert(Is<>), so the test
// is bypassed in this specialization.
UnsafeCast<LoadFn>(implicit context: Context)(o: Object): LoadFn {
return %RawCast<LoadFn>(o);
return %RawObjectCast<LoadFn>(o);
}
UnsafeCast<StoreFn>(implicit context: Context)(o: Object): StoreFn {
return %RawCast<StoreFn>(o);
return %RawObjectCast<StoreFn>(o);
}
macro KindForArrayType<T: type>(): constexpr ElementsKind;
......
......@@ -374,9 +374,6 @@ class V8_EXPORT_PRIVATE CodeStubAssembler
#undef HEAP_CONSTANT_TEST
Node* IntPtrOrSmiConstant(int value, ParameterMode mode);
TNode<Smi> LanguageModeConstant(LanguageMode mode) {
return SmiConstant(static_cast<int>(mode));
}
bool IsIntPtrOrSmiConstantZero(Node* test, ParameterMode mode);
bool TryGetIntPtrOrSmiConstantValue(Node* maybe_constant, int* value,
......
......@@ -180,11 +180,59 @@ void CSAGenerator::EmitInstruction(const CallIntrinsicInstruction& instruction,
}
}
if (instruction.intrinsic->ExternalName() == "%RawCast") {
if (!return_type->IsSubtypeOf(TypeOracle::GetObjectType())) {
ReportError("%RawCast must cast to subtype of Object");
if (instruction.intrinsic->ExternalName() == "%RawObjectCast") {
if (parameter_types.size() != 1) {
ReportError("%RawObjectCast must take a single parameter");
}
if (return_type->IsSubtypeOf(TypeOracle::GetTaggedType())) {
if (return_type->GetGeneratedTNodeTypeName() !=
parameter_types[0]->GetGeneratedTNodeTypeName()) {
out_ << "TORQUE_CAST";
}
} else {
std::stringstream s;
s << "%RawObjectCast must cast to subtype of Tagged (" << *return_type
<< " is not)";
ReportError(s.str());
}
} else if (instruction.intrinsic->ExternalName() == "%RawPointerCast") {
if (parameter_types.size() != 1) {
ReportError("%RawPointerCast must take a single parameter");
}
if (!return_type->IsSubtypeOf(TypeOracle::GetRawPtrType())) {
std::stringstream s;
s << "%RawObjectCast must cast to subtype of RawPtr (" << *return_type
<< " is not)";
ReportError(s.str());
}
} else if (instruction.intrinsic->ExternalName() == "%FromConstexpr") {
if (parameter_types.size() != 1 || !parameter_types[0]->IsConstexpr()) {
ReportError(
"%FromConstexpr must take a single parameter with constexpr "
"type");
}
if (return_type->IsConstexpr()) {
ReportError("%FromConstexpr must return a non-constexpr type");
}
if (return_type->IsSubtypeOf(TypeOracle::GetSmiType())) {
out_ << "ca_.SmiConstant";
} else if (return_type->IsSubtypeOf(TypeOracle::GetNumberType())) {
out_ << "ca_.NumberConstant";
} else if (return_type->IsSubtypeOf(TypeOracle::GetStringType())) {
out_ << "ca_.StringConstant";
} else if (return_type->IsSubtypeOf(TypeOracle::GetObjectType())) {
ReportError(
"%FromConstexpr cannot cast to subclass of HeapObject unless it's a "
"String or Number");
} else if (return_type->IsSubtypeOf(TypeOracle::GetIntPtrType())) {
out_ << "ca_.IntPtrConstant";
} else if (return_type->IsSubtypeOf(TypeOracle::GetInt32Type())) {
out_ << "ca_.Int32Constant";
} else {
std::stringstream s;
s << "%FromConstexpr does not support return type " << *return_type;
ReportError(s.str());
}
} else {
ReportError("no built in intrinsic with name " +
instruction.intrinsic->ExternalName());
......
......@@ -1810,10 +1810,25 @@ VisitResult ImplementationVisitor::GenerateCall(
return VisitResult(return_type, assembler().TopRange(slot_count));
}
} else if (auto* intrinsic = Intrinsic::DynamicCast(callable)) {
assembler().Emit(CallIntrinsicInstruction{intrinsic, constexpr_arguments});
if (intrinsic->ExternalName() == "%RawConstexprCast") {
if (intrinsic->signature().parameter_types.types.size() != 1 ||
constexpr_arguments.size() != 1) {
ReportError(
"%RawConstexprCast must take a single parameter with constexpr "
"type");
}
std::stringstream result;
result << "static_cast<" << return_type->GetGeneratedTypeName() << ">(";
result << constexpr_arguments[0];
result << ")";
return VisitResult(return_type, result.str());
} else {
assembler().Emit(
CallIntrinsicInstruction{intrinsic, constexpr_arguments});
size_t return_slot_count =
LoweredSlotCount(intrinsic->signature().return_type);
return VisitResult(return_type, assembler().TopRange(return_slot_count));
}
} else {
UNREACHABLE();
}
......@@ -1896,7 +1911,7 @@ VisitResult ImplementationVisitor::GenerateImplicitConvert(
if (TypeOracle::IsImplicitlyConvertableFrom(destination_type,
source.type())) {
return scope.Yield(GenerateCall(kFromConstexprMacroName, {{source}, {}},
{destination_type}, false));
{destination_type, source.type()}, false));
} else if (IsAssignableFrom(destination_type, source.type())) {
source.SetType(destination_type);
return scope.Yield(GenerateCopy(source));
......
......@@ -92,18 +92,42 @@ class TypeOracle : public ContextualClass<TypeOracle> {
return Get().GetBuiltinType(VOID_TYPE_STRING);
}
static const Type* GetRawPtrType() {
return Get().GetBuiltinType(RAWPTR_TYPE_STRING);
}
static const Type* GetObjectType() {
return Get().GetBuiltinType(OBJECT_TYPE_STRING);
}
static const Type* GetTaggedType() {
return Get().GetBuiltinType(TAGGED_TYPE_STRING);
}
static const Type* GetSmiType() {
return Get().GetBuiltinType(SMI_TYPE_STRING);
}
static const Type* GetConstStringType() {
return Get().GetBuiltinType(CONST_STRING_TYPE_STRING);
}
static const Type* GetStringType() {
return Get().GetBuiltinType(STRING_TYPE_STRING);
}
static const Type* GetNumberType() {
return Get().GetBuiltinType(NUMBER_TYPE_STRING);
}
static const Type* GetIntPtrType() {
return Get().GetBuiltinType(INTPTR_TYPE_STRING);
}
static const Type* GetInt32Type() {
return Get().GetBuiltinType(INT32_TYPE_STRING);
}
static const Type* GetNeverType() {
return Get().GetBuiltinType(NEVER_TYPE_STRING);
}
......@@ -116,7 +140,7 @@ class TypeOracle : public ContextualClass<TypeOracle> {
for (Generic* from_constexpr :
Declarations::LookupGeneric(kFromConstexprMacroName)) {
if (base::Optional<Callable*> specialization =
from_constexpr->GetSpecialization({to})) {
from_constexpr->GetSpecialization({to, from})) {
if ((*specialization)->signature().GetExplicitTypes() ==
TypeVector{from}) {
return true;
......
......@@ -26,9 +26,15 @@ static const char* const VOID_TYPE_STRING = "void";
static const char* const ARGUMENTS_TYPE_STRING = "constexpr Arguments";
static const char* const CONTEXT_TYPE_STRING = "Context";
static const char* const OBJECT_TYPE_STRING = "Object";
static const char* const SMI_TYPE_STRING = "Smi";
static const char* const TAGGED_TYPE_STRING = "Tagged";
static const char* const RAWPTR_TYPE_STRING = "RawPtr";
static const char* const CONST_STRING_TYPE_STRING = "constexpr string";
static const char* const STRING_TYPE_STRING = "String";
static const char* const NUMBER_TYPE_STRING = "Number";
static const char* const CODE_TYPE_STRING = "Code";
static const char* const INTPTR_TYPE_STRING = "intptr";
static const char* const INT32_TYPE_STRING = "int32";
static const char* const CONST_INT31_TYPE_STRING = "constexpr int31";
static const char* const CONST_INT32_TYPE_STRING = "constexpr int32";
static const char* const CONST_FLOAT64_TYPE_STRING = "constexpr float64";
......@@ -170,7 +176,11 @@ class AbstractType final : public Type {
DECLARE_TYPE_BOILERPLATE(AbstractType);
const std::string& name() const { return name_; }
std::string ToExplicitString() const override { return name(); }
std::string MangledName() const override { return "AT" + name(); }
std::string MangledName() const override {
std::string str(name());
std::replace(str.begin(), str.end(), ' ', '_');
return "AT" + str;
}
std::string GetGeneratedTypeName() const override {
return IsConstexpr() ? generated_type_
: "compiler::TNode<" + generated_type_ + ">";
......
......@@ -259,17 +259,17 @@ namespace array {
UnsafeCast<CompareBuiltinFn>(implicit context: Context)(o: Object):
CompareBuiltinFn {
return %RawCast<CompareBuiltinFn>(o);
return %RawObjectCast<CompareBuiltinFn>(o);
}
UnsafeCast<LoadFn>(implicit context: Context)(o: Object): LoadFn {
return %RawCast<LoadFn>(o);
return %RawObjectCast<LoadFn>(o);
}
UnsafeCast<StoreFn>(implicit context: Context)(o: Object): StoreFn {
return %RawCast<StoreFn>(o);
return %RawObjectCast<StoreFn>(o);
}
UnsafeCast<CanUseSameAccessorFn>(implicit context: Context)(o: Object):
CanUseSameAccessorFn {
return %RawCast<CanUseSameAccessorFn>(o);
return %RawObjectCast<CanUseSameAccessorFn>(o);
}
builtin SortCompareDefault(
......
......@@ -46,7 +46,10 @@ def preprocess(input):
return input
def postprocess(output):
output = re.sub(r'% RawCast', r'%RawCast', output)
output = re.sub(r'% RawObjectCast', r'%RawObjectCast', output)
output = re.sub(r'% RawPointerCast', r'%RawPointerCast', output)
output = re.sub(r'% RawConstexprCast', r'%RawConstexprCast', output)
output = re.sub(r'% FromConstexpr', r'%FromConstexpr', output)
output = re.sub(r'\/\*COxp\*\/', r'constexpr', output)
output = re.sub(r'(\S+)\s*: type([,>])', r'\1: type\2', output)
output = re.sub(r'(\n\s*)labels( [A-Z])', r'\1 labels\2', output)
......
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