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
This diff is collapsed.
......@@ -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());
}
out_ << "TORQUE_CAST";
} 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});
size_t return_slot_count =
LoweredSlotCount(intrinsic->signature().return_type);
return VisitResult(return_type, assembler().TopRange(return_slot_count));
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