[torque] no longer generate assemblers per namespace

Instead of generating one CodeStubAssembler-like class per namespace,
Torque-generated macros are now free-standing functions not included
from CSA code, and explicitly exported macros become part of the new
TorqueGeneratedExportedMacrosAssembler, which CodeStubAssembler
inherits from, thus making them available to all CSA code.

Structs are now defined in a new header csa-types-tq.h as free-standing
types with the prefix "TorqueStruct".

This is a preparation for generating per Torque-file instead of per
namespace.

Change-Id: I60fadc493a63f85d1d340768ec6f11ae47be0cb8
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1628787
Commit-Queue: Tobias Tebbi <tebbi@chromium.org>
Reviewed-by: Sigurd Schneider <sigurds@chromium.org>
Cr-Commit-Position: refs/heads/master@{#61865}
This commit is contained in:
Tobias Tebbi 2019-05-27 21:25:38 +02:00 committed by Commit Bot
parent 70bd7cf0ef
commit 19d8bfa5a8
27 changed files with 358 additions and 258 deletions

View File

@ -1063,6 +1063,9 @@ action("run_torque") {
"$target_gen_dir/torque-generated/class-definitions-tq.cc",
"$target_gen_dir/torque-generated/class-definitions-tq-inl.h",
"$target_gen_dir/torque-generated/class-definitions-tq.h",
"$target_gen_dir/torque-generated/exported-macros-assembler-tq.cc",
"$target_gen_dir/torque-generated/exported-macros-assembler-tq.h",
"$target_gen_dir/torque-generated/csa-types-tq.h",
]
foreach(namespace, torque_namespaces) {
outputs += [
@ -1104,7 +1107,11 @@ v8_source_set("torque_generated_initializers") {
":v8_maybe_icu",
]
sources = []
sources = [
"$target_gen_dir/torque-generated/csa-types-tq.h",
"$target_gen_dir/torque-generated/exported-macros-assembler-tq.cc",
"$target_gen_dir/torque-generated/exported-macros-assembler-tq.h",
]
foreach(namespace, torque_namespaces) {
sources += [
"$target_gen_dir/torque-generated/builtins-$namespace-gen-tq.cc",

View File

@ -112,9 +112,8 @@ Node* ArgumentsBuiltinsAssembler::EmitFastNewRestParameter(Node* context,
ParameterMode mode = OptimalParameterMode();
Node* zero = IntPtrOrSmiConstant(0, mode);
TorqueGeneratedArgumentsBuiltinsAssembler::ArgumentsInfo info =
GetArgumentsFrameAndCount(CAST(context),
UncheckedCast<JSFunction>(function));
TorqueStructArgumentsInfo info = GetArgumentsFrameAndCount(
CAST(context), UncheckedCast<JSFunction>(function));
VARIABLE(result, MachineRepresentation::kTagged);
Label no_rest_parameters(this), runtime(this, Label::kDeferred),
@ -167,9 +166,8 @@ Node* ArgumentsBuiltinsAssembler::EmitFastNewStrictArguments(Node* context,
ParameterMode mode = OptimalParameterMode();
Node* zero = IntPtrOrSmiConstant(0, mode);
TorqueGeneratedArgumentsBuiltinsAssembler::ArgumentsInfo info =
GetArgumentsFrameAndCount(CAST(context),
UncheckedCast<JSFunction>(function));
TorqueStructArgumentsInfo info = GetArgumentsFrameAndCount(
CAST(context), UncheckedCast<JSFunction>(function));
GotoIfFixedArraySizeDoesntFitInNewSpace(
info.argument_count, &runtime,
@ -216,9 +214,8 @@ Node* ArgumentsBuiltinsAssembler::EmitFastNewSloppyArguments(Node* context,
Label done(this, &result), empty(this), no_parameters(this),
runtime(this, Label::kDeferred);
TorqueGeneratedArgumentsBuiltinsAssembler::ArgumentsInfo info =
GetArgumentsFrameAndCount(CAST(context),
UncheckedCast<JSFunction>(function));
TorqueStructArgumentsInfo info = GetArgumentsFrameAndCount(
CAST(context), UncheckedCast<JSFunction>(function));
GotoIf(WordEqual(info.argument_count, zero), &empty);

View File

@ -6,7 +6,6 @@
#define V8_BUILTINS_BUILTINS_ARGUMENTS_GEN_H_
#include "src/codegen/code-stub-assembler.h"
#include "torque-generated/builtins-arguments-gen-tq.h"
namespace v8 {
namespace internal {
@ -15,13 +14,10 @@ using Node = compiler::Node;
using CodeAssemblerState = compiler::CodeAssemblerState;
using CodeAssemblerLabel = compiler::CodeAssemblerLabel;
class ArgumentsBuiltinsAssembler
: public CodeStubAssembler,
public TorqueGeneratedArgumentsBuiltinsAssembler {
class ArgumentsBuiltinsAssembler : public CodeStubAssembler {
public:
explicit ArgumentsBuiltinsAssembler(CodeAssemblerState* state)
: CodeStubAssembler(state),
TorqueGeneratedArgumentsBuiltinsAssembler(state) {}
: CodeStubAssembler(state) {}
Node* EmitFastNewStrictArguments(Node* context, Node* function);
Node* EmitFastNewSloppyArguments(Node* context, Node* function);

View File

@ -15,13 +15,12 @@
#include "src/objects/allocation-site-inl.h"
#include "src/objects/arguments-inl.h"
#include "src/objects/property-cell.h"
#include "torque-generated/builtins-typed-array-createtypedarray-gen-tq.h"
namespace v8 {
namespace internal {
using Node = compiler::Node;
using IteratorRecord = TorqueGeneratedIteratorBuiltinsAssembler::IteratorRecord;
using IteratorRecord = TorqueStructIteratorRecord;
ArrayBuiltinsAssembler::ArrayBuiltinsAssembler(
compiler::CodeAssemblerState* state)
@ -37,9 +36,7 @@ ArrayBuiltinsAssembler::ArrayBuiltinsAssembler(
TNode<Smi> length = CAST(len_);
const char* method_name = "%TypedArray%.prototype.map";
TorqueGeneratedTypedArrayCreatetypedarrayBuiltinsAssembler typedarray_asm(
state());
TNode<JSTypedArray> a = typedarray_asm.TypedArraySpeciesCreateByLength(
TNode<JSTypedArray> a = TypedArraySpeciesCreateByLength(
context(), method_name, original_array, length);
// In the Spec and our current implementation, the length check is already
// performed in TypedArraySpeciesCreate.

View File

@ -13,8 +13,6 @@
#include "src/objects/hash-table-inl.h"
#include "src/objects/js-collection.h"
#include "src/objects/ordered-hash-table.h"
#include "torque-generated/builtins-base-gen-tq.h"
#include "torque-generated/builtins-collections-gen-tq.h"
namespace v8 {
namespace internal {
@ -25,13 +23,10 @@ using TNode = compiler::TNode<T>;
template <class T>
using TVariable = compiler::TypedCodeAssemblerVariable<T>;
class BaseCollectionsAssembler
: public CodeStubAssembler,
public TorqueGeneratedCollectionsBuiltinsAssembler {
class BaseCollectionsAssembler : public CodeStubAssembler {
public:
explicit BaseCollectionsAssembler(compiler::CodeAssemblerState* state)
: CodeStubAssembler(state),
TorqueGeneratedCollectionsBuiltinsAssembler(state) {}
: CodeStubAssembler(state) {}
virtual ~BaseCollectionsAssembler() = default;
@ -160,7 +155,7 @@ void BaseCollectionsAssembler::AddConstructorEntry(
var_exception);
CSA_ASSERT(this, Word32BinaryNot(IsTheHole(key_value)));
if (variant == kMap || variant == kWeakMap) {
TorqueGeneratedBaseBuiltinsAssembler::KeyValuePair pair =
TorqueStructKeyValuePair pair =
if_may_have_side_effects != nullptr
? LoadKeyValuePairNoSideEffects(context, key_value,
if_may_have_side_effects)
@ -320,7 +315,7 @@ void BaseCollectionsAssembler::AddConstructorEntriesFromIterable(
TNode<Object> add_func = GetAddFunction(variant, context, collection);
IteratorBuiltinsAssembler iterator_assembler(this->state());
IteratorBuiltinsAssembler::IteratorRecord iterator =
TorqueStructIteratorRecord iterator =
iterator_assembler.GetIterator(context, iterable);
CSA_ASSERT(this, Word32BinaryNot(IsUndefined(iterator.object)));

View File

@ -11,13 +11,11 @@
#include "src/builtins/builtins.h"
#include "src/codegen/code-stub-assembler.h"
#include "src/heap/factory-inl.h"
#include "torque-generated/builtins-base-gen-tq.h"
namespace v8 {
namespace internal {
using IteratorRecord = TorqueGeneratedIteratorBuiltinsAssembler::IteratorRecord;
using IteratorRecord = TorqueStructIteratorRecord;
using compiler::Node;
TNode<Object> IteratorBuiltinsAssembler::GetIteratorMethod(Node* context,

View File

@ -6,21 +6,18 @@
#define V8_BUILTINS_BUILTINS_ITERATOR_GEN_H_
#include "src/codegen/code-stub-assembler.h"
#include "torque-generated/builtins-base-gen-tq.h"
#include "torque-generated/builtins-iterator-gen-tq.h"
namespace v8 {
namespace internal {
using compiler::Node;
class IteratorBuiltinsAssembler
: public CodeStubAssembler,
public TorqueGeneratedIteratorBuiltinsAssembler {
class IteratorBuiltinsAssembler : public CodeStubAssembler {
public:
explicit IteratorBuiltinsAssembler(compiler::CodeAssemblerState* state)
: CodeStubAssembler(state),
TorqueGeneratedIteratorBuiltinsAssembler(state) {}
: CodeStubAssembler(state) {}
using IteratorRecord = TorqueStructIteratorRecord;
// Returns object[Symbol.iterator].
TNode<Object> GetIteratorMethod(Node* context, Node* object);

View File

@ -21,7 +21,7 @@ namespace internal {
using Node = compiler::Node;
template <class T>
using TNode = CodeStubAssembler::TNode<T>;
using IteratorRecord = IteratorBuiltinsAssembler::IteratorRecord;
using IteratorRecord = TorqueStructIteratorRecord;
Node* PromiseBuiltinsAssembler::AllocateJSPromise(Node* context) {
Node* const native_context = LoadNativeContext(context);

View File

@ -7,8 +7,6 @@
#include "src/codegen/code-stub-assembler.h"
#include "src/objects/promise.h"
#include "torque-generated/builtins-base-gen-tq.h"
#include "torque-generated/builtins-iterator-gen-tq.h"
namespace v8 {
namespace internal {
@ -140,7 +138,7 @@ class V8_EXPORT_PRIVATE PromiseBuiltinsAssembler : public CodeStubAssembler {
Node* PerformPromiseAll(
Node* context, Node* constructor, Node* capability,
const TorqueGeneratedIteratorBuiltinsAssembler::IteratorRecord& record,
const TorqueStructIteratorRecord& record,
const PromiseAllResolvingElementFunction& create_resolve_element_function,
const PromiseAllResolvingElementFunction& create_reject_element_function,
Label* if_exception, Variable* var_exception);

View File

@ -7,7 +7,6 @@
#include "src/codegen/code-stub-assembler.h"
#include "src/objects/js-proxy.h"
#include "torque-generated/builtins-proxy-gen-tq.h"
namespace v8 {
namespace internal {

View File

@ -10,7 +10,6 @@
#include "src/builtins/growable-fixed-array-gen.h"
#include "src/handles/handles-inl.h"
#include "src/heap/factory-inl.h"
#include "torque-generated/builtins-typed-array-createtypedarray-gen-tq.h"
namespace v8 {
namespace internal {
@ -226,7 +225,7 @@ TNode<IntPtrT> TypedArrayBuiltinsAssembler::GetTypedArrayElementSize(
return element_size.value();
}
TorqueGeneratedTypedArrayBuiltinsAssembler::TypedArrayElementsInfo
TorqueStructTypedArrayElementsInfo
TypedArrayBuiltinsAssembler::GetTypedArrayElementsInfo(
TNode<JSTypedArray> typed_array) {
TNode<Int32T> elements_kind = LoadElementsKind(typed_array);
@ -241,8 +240,8 @@ TypedArrayBuiltinsAssembler::GetTypedArrayElementsInfo(
var_size_log2 = UintPtrConstant(ElementsKindToShiftSize(kind));
});
return TorqueGeneratedTypedArrayBuiltinsAssembler::TypedArrayElementsInfo{
var_size_log2.value(), elements_kind};
return TorqueStructTypedArrayElementsInfo{var_size_log2.value(),
elements_kind};
}
TNode<JSFunction> TypedArrayBuiltinsAssembler::GetDefaultConstructor(

View File

@ -6,15 +6,13 @@
#define V8_BUILTINS_BUILTINS_TYPED_ARRAY_GEN_H_
#include "src/codegen/code-stub-assembler.h"
#include "torque-generated/builtins-typed-array-gen-tq.h"
namespace v8 {
namespace internal {
class TypedArrayBuiltinsAssembler : public CodeStubAssembler {
public:
using ElementsInfo =
TorqueGeneratedTypedArrayBuiltinsAssembler::TypedArrayElementsInfo;
using ElementsInfo = TorqueStructTypedArrayElementsInfo;
explicit TypedArrayBuiltinsAssembler(compiler::CodeAssemblerState* state)
: CodeStubAssembler(state) {}

View File

@ -30,7 +30,7 @@ using SloppyTNode = compiler::SloppyTNode<T>;
CodeStubAssembler::CodeStubAssembler(compiler::CodeAssemblerState* state)
: compiler::CodeAssembler(state),
TorqueGeneratedBaseBuiltinsAssembler(state) {
TorqueGeneratedExportedMacrosAssembler(state) {
if (DEBUG_BOOL && FLAG_csa_trap_on_node != nullptr) {
HandleBreakOnNode();
}
@ -13724,15 +13724,13 @@ Node* CodeStubAssembler::CheckEnumCache(Node* receiver, Label* if_empty,
return receiver_map;
}
TNode<Object> CodeStubAssembler::GetArgumentValue(
TorqueGeneratedBaseBuiltinsAssembler::Arguments args,
TNode<IntPtrT> index) {
TNode<Object> CodeStubAssembler::GetArgumentValue(TorqueStructArguments args,
TNode<IntPtrT> index) {
return CodeStubArguments(this, args).GetOptionalArgumentValue(index);
}
TorqueGeneratedBaseBuiltinsAssembler::Arguments
CodeStubAssembler::GetFrameArguments(TNode<RawPtrT> frame,
TNode<IntPtrT> argc) {
TorqueStructArguments CodeStubAssembler::GetFrameArguments(
TNode<RawPtrT> frame, TNode<IntPtrT> argc) {
return CodeStubArguments(this, argc, frame, INTPTR_PARAMETERS)
.GetTorqueArguments();
}

View File

@ -20,7 +20,7 @@
#include "src/objects/smi.h"
#include "src/roots/roots.h"
#include "torque-generated/builtins-base-gen-tq.h"
#include "torque-generated/exported-macros-assembler-tq.h"
namespace v8 {
namespace internal {
@ -205,7 +205,7 @@ enum class PrimitiveType { kBoolean, kNumber, kString, kSymbol };
// from a compiler directory OWNER).
class V8_EXPORT_PRIVATE CodeStubAssembler
: public compiler::CodeAssembler,
public TorqueGeneratedBaseBuiltinsAssembler {
public TorqueGeneratedExportedMacrosAssembler {
public:
using Node = compiler::Node;
template <class T>
@ -3311,12 +3311,11 @@ class V8_EXPORT_PRIVATE CodeStubAssembler
Label* if_fast, Label* if_slow);
Node* CheckEnumCache(Node* receiver, Label* if_empty, Label* if_runtime);
TNode<Object> GetArgumentValue(
TorqueGeneratedBaseBuiltinsAssembler::Arguments args,
TNode<IntPtrT> index);
TNode<Object> GetArgumentValue(TorqueStructArguments args,
TNode<IntPtrT> index);
TorqueGeneratedBaseBuiltinsAssembler::Arguments GetFrameArguments(
TNode<RawPtrT> frame, TNode<IntPtrT> argc);
TorqueStructArguments GetFrameArguments(TNode<RawPtrT> frame,
TNode<IntPtrT> argc);
// Support for printf-style debugging
void Print(const char* s);
@ -3620,9 +3619,8 @@ class V8_EXPORT_PRIVATE CodeStubArguments {
// Used by Torque to construct arguments based on a Torque-defined
// struct of values.
CodeStubArguments(
CodeStubAssembler* assembler,
TorqueGeneratedBaseBuiltinsAssembler::Arguments torque_arguments)
CodeStubArguments(CodeStubAssembler* assembler,
TorqueStructArguments torque_arguments)
: assembler_(assembler),
argc_mode_(CodeStubAssembler::INTPTR_PARAMETERS),
receiver_mode_(ReceiverMode::kHasReceiver),
@ -3659,11 +3657,10 @@ class V8_EXPORT_PRIVATE CodeStubArguments {
return argc_;
}
TorqueGeneratedBaseBuiltinsAssembler::Arguments GetTorqueArguments() const {
TorqueStructArguments GetTorqueArguments() const {
DCHECK_EQ(argc_mode_, CodeStubAssembler::INTPTR_PARAMETERS);
return TorqueGeneratedBaseBuiltinsAssembler::Arguments{
assembler_->UncheckedCast<RawPtrT>(fp_), base_,
assembler_->UncheckedCast<IntPtrT>(argc_)};
return TorqueStructArguments{assembler_->UncheckedCast<RawPtrT>(fp_), base_,
assembler_->UncheckedCast<IntPtrT>(argc_)};
}
TNode<Object> GetOptionalArgumentValue(TNode<IntPtrT> index) {

View File

@ -474,12 +474,12 @@ struct types_have_common_values<MaybeObject, T> {
template <class T>
class TNode {
public:
static_assert(is_valid_type_tag<T>::value, "invalid type tag");
template <class U,
typename std::enable_if<is_subtype<U, T>::value, int>::type = 0>
TNode(const TNode<U>& other) : node_(other) {}
TNode() : node_(nullptr) {}
TNode(const TNode<U>& other) : node_(other) {
LazyTemplateChecks();
}
TNode() : TNode(nullptr) {}
TNode operator=(TNode other) {
DCHECK_NOT_NULL(other.node_);
@ -492,9 +492,14 @@ class TNode {
static TNode UncheckedCast(compiler::Node* node) { return TNode(node); }
protected:
explicit TNode(compiler::Node* node) : node_(node) {}
explicit TNode(compiler::Node* node) : node_(node) { LazyTemplateChecks(); }
private:
// These checks shouldn't be checked before TNode is actually used.
void LazyTemplateChecks() {
static_assert(is_valid_type_tag<T>::value, "invalid type tag");
}
compiler::Node* node_;
};

View File

@ -131,8 +131,7 @@ void CSAGenerator::EmitInstruction(
} else if (results.size() == 1) {
out_ << results[0] << " = ";
}
out_ << instruction.constant->ExternalAssemblerName() << "(state_)."
<< instruction.constant->name()->value << "()";
out_ << instruction.constant->external_name() << "(state_)";
if (type->IsStructType()) {
out_ << ".Flatten();\n";
} else {
@ -321,8 +320,12 @@ void CSAGenerator::EmitInstruction(const CallCsaMacroInstruction& instruction,
DCHECK_EQ(0, results.size());
}
}
out_ << instruction.macro->external_assembler_name() << "(state_)."
<< instruction.macro->ExternalName() << "(";
if (ExternMacro* extern_macro = ExternMacro::DynamicCast(instruction.macro)) {
out_ << extern_macro->external_assembler_name() << "(state_).";
} else {
args.insert(args.begin(), "state_");
}
out_ << instruction.macro->ExternalName() << "(";
PrintCommaSeparatedList(out_, args);
if (needs_flattening) {
out_ << ").Flatten();\n";
@ -386,8 +389,12 @@ void CSAGenerator::EmitInstruction(
PrintCommaSeparatedList(out_, results);
out_ << ") = ";
}
out_ << instruction.macro->external_assembler_name() << "(state_)."
<< instruction.macro->ExternalName() << "(";
if (ExternMacro* extern_macro = ExternMacro::DynamicCast(instruction.macro)) {
out_ << extern_macro->external_assembler_name() << "(state_).";
} else {
args.insert(args.begin(), "state_");
}
out_ << instruction.macro->ExternalName() << "(";
PrintCommaSeparatedList(out_, args);
bool first = args.empty();
for (size_t i = 0; i < label_names.size(); ++i) {

View File

@ -43,7 +43,8 @@ class Declarable {
virtual ~Declarable() = default;
enum Kind {
kNamespace,
kMacro,
kTorqueMacro,
kExternMacro,
kMethod,
kBuiltin,
kRuntimeFunction,
@ -55,8 +56,10 @@ class Declarable {
};
Kind kind() const { return kind_; }
bool IsNamespace() const { return kind() == kNamespace; }
bool IsMacro() const { return kind() == kMacro || kind() == kMethod; }
bool IsMacro() const { return IsTorqueMacro() || IsExternMacro(); }
bool IsTorqueMacro() const { return kind() == kTorqueMacro || IsMethod(); }
bool IsMethod() const { return kind() == kMethod; }
bool IsExternMacro() const { return kind() == kExternMacro; }
bool IsIntrinsic() const { return kind() == kIntrinsic; }
bool IsBuiltin() const { return kind() == kBuiltin; }
bool IsRuntimeFunction() const { return kind() == kRuntimeFunction; }
@ -178,9 +181,6 @@ class Namespace : public Scope {
explicit Namespace(const std::string& name)
: Scope(Declarable::kNamespace), name_(name) {}
const std::string& name() const { return name_; }
std::string ExternalName() const {
return "TorqueGenerated" + CamelifyString(name()) + "BuiltinsAssembler";
}
bool IsDefaultNamespace() const;
bool IsTestNamespace() const;
std::ostream& source_stream() { return source_stream_; }
@ -231,18 +231,19 @@ class NamespaceConstant : public Value {
public:
DECLARE_DECLARABLE_BOILERPLATE(NamespaceConstant, constant)
Expression* body() { return body_; }
std::string ExternalAssemblerName() const {
return Namespace::cast(ParentScope())->ExternalName();
}
const std::string& external_name() const { return external_name_; }
Expression* body() const { return body_; }
private:
friend class Declarations;
explicit NamespaceConstant(Identifier* constant_name, const Type* type,
explicit NamespaceConstant(Identifier* constant_name,
std::string external_name, const Type* type,
Expression* body)
: Value(Declarable::kNamespaceConstant, type, constant_name),
external_name_(std::move(external_name)),
body_(body) {}
std::string external_name_;
Expression* body_;
};
@ -317,42 +318,67 @@ class Macro : public Callable {
return Callable::ShouldBeInlined();
}
const std::string& external_assembler_name() const {
return external_assembler_name_;
}
bool IsAccessibleFromCSA() const { return accessible_from_csa_; }
protected:
Macro(Declarable::Kind kind, std::string external_name,
std::string readable_name, std::string external_assembler_name,
const Signature& signature, bool transitioning,
base::Optional<Statement*> body, bool is_user_defined,
bool accessible_from_csa)
std::string readable_name, const Signature& signature,
bool transitioning, base::Optional<Statement*> body)
: Callable(kind, std::move(external_name), std::move(readable_name),
signature, transitioning, body),
external_assembler_name_(std::move(external_assembler_name)),
accessible_from_csa_(accessible_from_csa) {
SetIsUserDefined(is_user_defined);
signature, transitioning, body) {
if (signature.parameter_types.var_args) {
ReportError("Varargs are not supported for macros.");
}
}
};
class ExternMacro : public Macro {
public:
DECLARE_DECLARABLE_BOILERPLATE(ExternMacro, ExternMacro)
const std::string& external_assembler_name() const {
return external_assembler_name_;
}
private:
friend class Declarations;
Macro(std::string external_name, std::string readable_name,
std::string external_assembler_name, const Signature& signature,
bool transitioning, base::Optional<Statement*> body,
bool is_user_defined, bool accessible_from_csa)
: Macro(Declarable::kMacro, std::move(external_name),
std::move(readable_name), external_assembler_name, signature,
transitioning, body, is_user_defined, accessible_from_csa) {}
ExternMacro(const std::string& name, std::string external_assembler_name,
Signature signature, bool transitioning)
: Macro(Declarable::kExternMacro, name, name, std::move(signature),
transitioning, base::nullopt),
external_assembler_name_(std::move(external_assembler_name)) {}
std::string external_assembler_name_;
bool accessible_from_csa_;
};
class Method : public Macro {
class TorqueMacro : public Macro {
public:
DECLARE_DECLARABLE_BOILERPLATE(TorqueMacro, TorqueMacro)
bool IsExportedToCSA() const { return exported_to_csa_; }
protected:
TorqueMacro(Declarable::Kind kind, std::string external_name,
std::string readable_name, const Signature& signature,
bool transitioning, base::Optional<Statement*> body,
bool is_user_defined, bool exported_to_csa)
: Macro(kind, std::move(external_name), std::move(readable_name),
signature, transitioning, body),
exported_to_csa_(exported_to_csa) {
SetIsUserDefined(is_user_defined);
}
private:
friend class Declarations;
TorqueMacro(std::string external_name, std::string readable_name,
const Signature& signature, bool transitioning,
base::Optional<Statement*> body, bool is_user_defined,
bool exported_to_csa)
: TorqueMacro(Declarable::kTorqueMacro, std::move(external_name),
std::move(readable_name), signature, transitioning, body,
is_user_defined, exported_to_csa) {}
bool exported_to_csa_ = false;
};
class Method : public TorqueMacro {
public:
DECLARE_DECLARABLE_BOILERPLATE(Method, Method)
bool ShouldBeInlined() const override {
@ -366,11 +392,11 @@ class Method : public Macro {
private:
friend class Declarations;
Method(AggregateType* aggregate_type, std::string external_name,
std::string readable_name, std::string external_assembler_name,
const Signature& signature, bool transitioning, Statement* body)
: Macro(Declarable::kMethod, std::move(external_name),
std::move(readable_name), std::move(external_assembler_name),
signature, transitioning, body, true, false),
std::string readable_name, const Signature& signature,
bool transitioning, Statement* body)
: TorqueMacro(Declarable::kMethod, std::move(external_name),
std::move(readable_name), signature, transitioning, body,
true, false),
aggregate_type_(aggregate_type) {}
AggregateType* aggregate_type_;
};

View File

@ -371,9 +371,9 @@ Callable* DeclarationVisitor::Specialize(
readable_name << ">";
Callable* callable;
if (MacroDeclaration::DynamicCast(declaration) != nullptr) {
callable = Declarations::CreateMacro(
generated_name, readable_name.str(), false, base::nullopt,
type_signature, declaration->transitioning, *body, true);
callable = Declarations::CreateTorqueMacro(
generated_name, readable_name.str(), false, type_signature,
declaration->transitioning, *body, true);
} else if (IntrinsicDeclaration::DynamicCast(declaration) != nullptr) {
callable = Declarations::CreateIntrinsic(declaration->name, type_signature);
} else {

View File

@ -152,23 +152,24 @@ const TypeAlias* Declarations::PredeclareTypeAlias(const Identifier* name,
return Declare(name->value, std::move(alias_ptr));
}
Macro* Declarations::CreateMacro(
std::string external_name, std::string readable_name,
bool accessible_from_csa,
base::Optional<std::string> external_assembler_name, Signature signature,
bool transitioning, base::Optional<Statement*> body, bool is_user_defined) {
if (!accessible_from_csa) {
// TODO(tebbi): Switch to more predictable names to improve incremental
// compilation.
external_name += "_" + std::to_string(GlobalContext::FreshId());
}
if (!external_assembler_name) {
external_assembler_name = CurrentNamespace()->ExternalName();
}
return RegisterDeclarable(std::unique_ptr<Macro>(
new Macro(std::move(external_name), std::move(readable_name),
std::move(*external_assembler_name), std::move(signature),
transitioning, body, is_user_defined, accessible_from_csa)));
TorqueMacro* Declarations::CreateTorqueMacro(
std::string external_name, std::string readable_name, bool exported_to_csa,
Signature signature, bool transitioning, base::Optional<Statement*> body,
bool is_user_defined) {
// TODO(tebbi): Switch to more predictable names to improve incremental
// compilation.
external_name += "_" + std::to_string(GlobalContext::FreshId());
return RegisterDeclarable(std::unique_ptr<TorqueMacro>(new TorqueMacro(
std::move(external_name), std::move(readable_name), std::move(signature),
transitioning, body, is_user_defined, exported_to_csa)));
}
ExternMacro* Declarations::CreateExternMacro(
std::string name, std::string external_assembler_name, Signature signature,
bool transitioning) {
return RegisterDeclarable(std::unique_ptr<ExternMacro>(
new ExternMacro(std::move(name), std::move(external_assembler_name),
std::move(signature), transitioning)));
}
Macro* Declarations::DeclareMacro(
@ -181,9 +182,14 @@ Macro* Declarations::DeclareMacro(
ReportError("cannot redeclare macro ", name,
" with identical explicit parameters");
}
Macro* macro = CreateMacro(name, name, accessible_from_csa,
std::move(external_assembler_name), signature,
transitioning, body, is_user_defined);
Macro* macro;
if (external_assembler_name) {
macro = CreateExternMacro(name, std::move(*external_assembler_name),
signature, transitioning);
} else {
macro = CreateTorqueMacro(name, name, accessible_from_csa, signature,
transitioning, body, is_user_defined);
}
Declare(name, macro);
if (op) {
if (TryLookupMacro(*op, signature.GetExplicitTypes())) {
@ -201,8 +207,7 @@ Method* Declarations::CreateMethod(AggregateType* container_type,
std::string generated_name{container_type->GetGeneratedMethodName(name)};
Method* result = RegisterDeclarable(std::unique_ptr<Method>(
new Method(container_type, container_type->GetGeneratedMethodName(name),
name, CurrentNamespace()->ExternalName(), std::move(signature),
transitioning, body)));
name, std::move(signature), transitioning, body)));
container_type->RegisterMethod(result);
return result;
}
@ -260,7 +265,10 @@ NamespaceConstant* Declarations::DeclareNamespaceConstant(Identifier* name,
const Type* type,
Expression* body) {
CheckAlreadyDeclared<Value>(name->value, "constant");
NamespaceConstant* result = new NamespaceConstant(name, type, body);
std::string external_name =
name->value + "_" + std::to_string(GlobalContext::FreshId());
NamespaceConstant* result =
new NamespaceConstant(name, std::move(external_name), type, body);
Declare(name->value, std::unique_ptr<Declarable>(result));
return result;
}

View File

@ -77,12 +77,16 @@ class Declarations {
static const TypeAlias* PredeclareTypeAlias(const Identifier* name,
TypeDeclaration* type,
bool redeclaration);
static Macro* CreateMacro(std::string external_name,
std::string readable_name, bool accessible_from_csa,
base::Optional<std::string> external_assembler_name,
Signature signature, bool transitioning,
base::Optional<Statement*> body,
bool is_user_defined);
static TorqueMacro* CreateTorqueMacro(std::string external_name,
std::string readable_name,
bool exported_to_csa,
Signature signature, bool transitioning,
base::Optional<Statement*> body,
bool is_user_defined);
static ExternMacro* CreateExternMacro(std::string name,
std::string external_assembler_name,
Signature signature,
bool transitioning);
static Macro* DeclareMacro(
const std::string& name, bool accessible_from_csa,
base::Optional<std::string> external_assembler_name,

View File

@ -74,25 +74,15 @@ void ImplementationVisitor::BeginNamespaceFile(Namespace* nspace) {
header << "#ifndef " << headerDefine << "\n";
header << "#define " << headerDefine << "\n\n";
header << "#include \"src/compiler/code-assembler.h\"\n";
if (nspace != GlobalContext::GetDefaultNamespace()) {
header << "#include \"src/codegen/code-stub-assembler.h\"\n";
}
header << "#include \"src/codegen/code-stub-assembler.h\"\n";
header << "#include \"src/utils/utils.h\"\n";
header << "#include \"torque-generated/field-offsets-tq.h\"\n";
header << "#include \"torque-generated/csa-types-tq.h\"\n";
header << "\n";
header << "namespace v8 {\n"
<< "namespace internal {\n"
<< "\n";
header << "class ";
// TODO(sigurds): Decide which assemblers we should export for testing.
header << "V8_EXPORT_PRIVATE ";
header << nspace->ExternalName() << " {\n";
header << " public:\n";
header << " explicit " << nspace->ExternalName()
<< "(compiler::CodeAssemblerState* state) : state_(state), ca_(state) "
"{ USE(state_, ca_); }\n";
}
void ImplementationVisitor::EndNamespaceFile(Namespace* nspace) {
@ -109,10 +99,6 @@ void ImplementationVisitor::EndNamespaceFile(Namespace* nspace) {
<< "} // namespace v8\n"
<< "\n";
header << " private:\n"
<< " compiler::CodeAssemblerState* const state_;\n"
<< " compiler::CodeAssembler ca_;\n"
<< "};\n\n";
header << "} // namespace internal\n"
<< "} // namespace v8\n"
<< "\n";
@ -121,18 +107,18 @@ void ImplementationVisitor::EndNamespaceFile(Namespace* nspace) {
void ImplementationVisitor::Visit(NamespaceConstant* decl) {
Signature signature{{}, base::nullopt, {{}, false}, 0, decl->type(), {}};
const std::string& name = decl->name()->value;
BindingsManagersScope bindings_managers_scope;
header_out() << " ";
GenerateFunctionDeclaration(header_out(), "", name, signature, {});
GenerateFunctionDeclaration(header_out(), "", decl->external_name(),
signature, {});
header_out() << ";\n";
GenerateFunctionDeclaration(source_out(),
CurrentNamespace()->ExternalName() + "::", name,
GenerateFunctionDeclaration(source_out(), "", decl->external_name(),
signature, {});
source_out() << " {\n";
source_out() << " compiler::CodeAssembler ca_(state_);\n";
DCHECK(!signature.return_type->IsVoidOrNever());
@ -161,41 +147,6 @@ void ImplementationVisitor::Visit(TypeAlias* alias) {
"extern classes are currently only supported in the default "
"namespace");
}
} else if (const StructType* struct_type =
StructType::DynamicCast(alias->type())) {
const std::string& name = struct_type->name();
header_out() << " struct " << name << " {\n";
for (auto& field : struct_type->fields()) {
header_out() << " "
<< field.name_and_type.type->GetGeneratedTypeName();
header_out() << " " << field.name_and_type.name << ";\n";
}
header_out() << "\n std::tuple<";
bool first = true;
for (const Type* type : LowerType(struct_type)) {
if (!first) {
header_out() << ", ";
}
first = false;
header_out() << type->GetGeneratedTypeName();
}
header_out() << "> Flatten() const {\n"
<< " return std::tuple_cat(";
first = true;
for (auto& field : struct_type->fields()) {
if (!first) {
header_out() << ", ";
}
first = false;
if (field.name_and_type.type->IsStructType()) {
header_out() << field.name_and_type.name << ".Flatten()";
} else {
header_out() << "std::make_tuple(" << field.name_and_type.name << ")";
}
}
header_out() << ");\n";
header_out() << " }\n";
header_out() << " };\n";
}
}
@ -314,13 +265,12 @@ void ImplementationVisitor::VisitMacroCommon(Macro* macro) {
bool has_return_value =
can_return && return_type != TypeOracle::GetVoidType();
header_out() << " ";
GenerateMacroFunctionDeclaration(header_out(), "", macro);
header_out() << ";\n";
GenerateMacroFunctionDeclaration(
source_out(), CurrentNamespace()->ExternalName() + "::", macro);
GenerateMacroFunctionDeclaration(source_out(), "", macro);
source_out() << " {\n";
source_out() << " compiler::CodeAssembler ca_(state_);\n";
Stack<std::string> lowered_parameters;
Stack<const Type*> lowered_parameter_types;
@ -416,8 +366,7 @@ void ImplementationVisitor::VisitMacroCommon(Macro* macro) {
source_out() << "}\n\n";
}
void ImplementationVisitor::Visit(Macro* macro) {
if (macro->IsExternal()) return;
void ImplementationVisitor::Visit(TorqueMacro* macro) {
VisitMacroCommon(macro);
}
@ -481,7 +430,7 @@ void ImplementationVisitor::Visit(Builtin* builtin) {
<< " TNode<IntPtrT> arguments_length(ChangeInt32ToIntPtr(argc));\n";
source_out() << " TNode<RawPtrT> arguments_frame = "
"UncheckedCast<RawPtrT>(LoadFramePointer());\n";
source_out() << " TorqueGeneratedBaseBuiltinsAssembler::Arguments "
source_out() << " TorqueStructArguments "
"torque_arguments(GetFrameArguments(arguments_frame, "
"arguments_length));\n";
source_out() << " CodeStubArguments arguments(this, torque_arguments);\n";
@ -1536,9 +1485,11 @@ void ImplementationVisitor::GenerateMacroFunctionDeclaration(
macro->signature(), macro->parameter_names());
}
void ImplementationVisitor::GenerateFunctionDeclaration(
std::vector<std::string> ImplementationVisitor::GenerateFunctionDeclaration(
std::ostream& o, const std::string& macro_prefix, const std::string& name,
const Signature& signature, const NameVector& parameter_names) {
const Signature& signature, const NameVector& parameter_names,
bool pass_code_assembler_state) {
std::vector<std::string> generated_parameter_names;
if (signature.return_type->IsVoidOrNever()) {
o << "void";
} else {
@ -1546,27 +1497,32 @@ void ImplementationVisitor::GenerateFunctionDeclaration(
}
o << " " << macro_prefix << name << "(";
DCHECK_EQ(signature.types().size(), parameter_names.size());
auto type_iterator = signature.types().begin();
bool first = true;
for (const Identifier* name : parameter_names) {
if (!first) {
o << ", ";
}
const Type* parameter_type = *type_iterator;
if (pass_code_assembler_state) {
first = false;
o << "compiler::CodeAssemblerState* state_";
}
DCHECK_GE(signature.types().size(), parameter_names.size());
for (size_t i = 0; i < signature.types().size(); ++i) {
if (!first) o << ", ";
first = false;
const Type* parameter_type = signature.types()[i];
const std::string& generated_type_name =
parameter_type->GetGeneratedTypeName();
o << generated_type_name << " " << ExternalParameterName(name->value);
type_iterator++;
first = false;
generated_parameter_names.push_back(ExternalParameterName(
i < parameter_names.size() ? parameter_names[i]->value
: std::to_string(i)));
o << generated_type_name << " " << generated_parameter_names.back();
}
for (const LabelDeclaration& label_info : signature.labels) {
if (!first) {
o << ", ";
}
o << "compiler::CodeAssemblerLabel* "
<< ExternalLabelName(label_info.name->value);
if (!first) o << ", ";
first = false;
generated_parameter_names.push_back(
ExternalLabelName(label_info.name->value));
o << "compiler::CodeAssemblerLabel* " << generated_parameter_names.back();
size_t i = 0;
for (const Type* type : label_info.types) {
std::string generated_type_name;
@ -1578,13 +1534,15 @@ void ImplementationVisitor::GenerateFunctionDeclaration(
generated_type_name += ">*";
}
o << ", ";
o << generated_type_name << " "
<< ExternalLabelParameterName(label_info.name->value, i);
generated_parameter_names.push_back(
ExternalLabelParameterName(label_info.name->value, i));
o << generated_type_name << " " << generated_parameter_names.back();
++i;
}
}
o << ")";
return generated_parameter_names;
}
namespace {
@ -1955,9 +1913,7 @@ LocationReference ImplementationVisitor::GetLocationReference(
if (auto* constant = NamespaceConstant::DynamicCast(value)) {
if (constant->type()->IsConstexpr()) {
return LocationReference::Temporary(
VisitResult(constant->type(), constant->ExternalAssemblerName() +
"(state_)." +
constant->name()->value + "()"),
VisitResult(constant->type(), constant->external_name() + "(state_)"),
"namespace constant " + expr->name->value);
}
assembler().Emit(NamespaceConstantInstruction{constant});
@ -2214,9 +2170,15 @@ VisitResult ImplementationVisitor::GenerateCall(
if (return_type->IsConstexpr()) {
DCHECK_EQ(0, arguments.labels.size());
std::stringstream result;
result << "(" << macro->external_assembler_name() << "(state_)."
<< macro->ExternalName() << "(";
result << "(";
bool first = true;
if (auto* extern_macro = ExternMacro::DynamicCast(macro)) {
result << extern_macro->external_assembler_name() << "(state_)."
<< extern_macro->ExternalName() << "(";
} else {
result << macro->ExternalName() << "(state_";
first = false;
}
for (VisitResult arg : arguments.parameters) {
DCHECK(!arg.IsOnStack());
if (!first) {
@ -2629,8 +2591,10 @@ void ImplementationVisitor::Visit(Declarable* declarable) {
CurrentScope::Scope current_scope(declarable->ParentScope());
CurrentSourcePosition::Scope current_source_position(declarable->Position());
switch (declarable->kind()) {
case Declarable::kMacro:
return Visit(Macro::cast(declarable));
case Declarable::kExternMacro:
return Visit(ExternMacro::cast(declarable));
case Declarable::kTorqueMacro:
return Visit(TorqueMacro::cast(declarable));
case Declarable::kMethod:
return Visit(Method::cast(declarable));
case Declarable::kBuiltin:
@ -3504,6 +3468,117 @@ void ImplementationVisitor::GenerateClassVerifiers(
WriteFile(output_directory + "/" + file_name + ".cc", cc_contents.str());
}
void ImplementationVisitor::GenerateExportedMacrosAssembler(
const std::string& output_directory) {
std::string file_name = "exported-macros-assembler-tq";
std::stringstream h_contents;
std::stringstream cc_contents;
{
IncludeGuardScope include_guard(h_contents, file_name + ".h");
h_contents << "#include \"src/compiler/code-assembler.h\"\n";
h_contents << "#include \"src/execution/frames.h\"\n";
h_contents << "#include \"torque-generated/csa-types-tq.h\"\n";
cc_contents << "#include \"torque-generated/" << file_name << ".h\"\n";
for (Namespace* n : GlobalContext::Get().GetNamespaces()) {
cc_contents << "#include \"torque-generated/builtins-" +
DashifyString(n->name()) + "-gen-tq.h\"\n";
}
NamespaceScope h_namespaces(h_contents, {"v8", "internal"});
NamespaceScope cc_namespaces(cc_contents, {"v8", "internal"});
h_contents << "class V8_EXPORT_PRIVATE "
"TorqueGeneratedExportedMacrosAssembler {\n"
<< " public:\n"
<< " explicit TorqueGeneratedExportedMacrosAssembler"
"(compiler::CodeAssemblerState* state) : state_(state) {\n"
<< " USE(state_);\n"
<< " }\n";
for (auto& declarable : GlobalContext::AllDeclarables()) {
TorqueMacro* macro = TorqueMacro::DynamicCast(declarable.get());
if (!(macro && macro->IsExportedToCSA())) continue;
h_contents << " ";
GenerateFunctionDeclaration(h_contents, "", macro->ReadableName(),
macro->signature(), macro->parameter_names(),
false);
h_contents << ";\n";
std::vector<std::string> parameter_names = GenerateFunctionDeclaration(
cc_contents,
"TorqueGeneratedExportedMacrosAssembler::", macro->ReadableName(),
macro->signature(), macro->parameter_names(), false);
cc_contents << "{\n";
cc_contents << "return " << macro->ExternalName() << "(state_";
for (auto& name : parameter_names) {
cc_contents << ", " << name;
}
cc_contents << ");\n";
cc_contents << "}\n";
}
h_contents << " private:\n"
<< " compiler::CodeAssemblerState* state_;\n"
<< "};\n";
}
WriteFile(output_directory + "/" + file_name + ".h", h_contents.str());
WriteFile(output_directory + "/" + file_name + ".cc", cc_contents.str());
}
void ImplementationVisitor::GenerateCSATypes(
const std::string& output_directory) {
std::string file_name = "csa-types-tq";
std::stringstream h_contents;
{
IncludeGuardScope include_guard(h_contents, file_name + ".h");
h_contents << "#include \"src/compiler/code-assembler.h\"\n\n";
NamespaceScope h_namespaces(h_contents, {"v8", "internal"});
for (auto& declarable : GlobalContext::AllDeclarables()) {
TypeAlias* alias = TypeAlias::DynamicCast(declarable.get());
if (!alias || alias->IsRedeclaration()) continue;
const StructType* struct_type = StructType::DynamicCast(alias->type());
if (!struct_type) continue;
const std::string& name = struct_type->name();
h_contents << "struct TorqueStruct" << name << " {\n";
for (auto& field : struct_type->fields()) {
h_contents << " " << field.name_and_type.type->GetGeneratedTypeName();
h_contents << " " << field.name_and_type.name << ";\n";
}
h_contents << "\n std::tuple<";
bool first = true;
for (const Type* type : LowerType(struct_type)) {
if (!first) {
h_contents << ", ";
}
first = false;
h_contents << type->GetGeneratedTypeName();
}
h_contents << "> Flatten() const {\n"
<< " return std::tuple_cat(";
first = true;
for (auto& field : struct_type->fields()) {
if (!first) {
h_contents << ", ";
}
first = false;
if (field.name_and_type.type->IsStructType()) {
h_contents << field.name_and_type.name << ".Flatten()";
} else {
h_contents << "std::make_tuple(" << field.name_and_type.name << ")";
}
}
h_contents << ");\n";
h_contents << " }\n";
h_contents << "};\n";
}
}
WriteFile(output_directory + "/" + file_name + ".h", h_contents.str());
}
} // namespace torque
} // namespace internal
} // namespace v8

View File

@ -280,6 +280,8 @@ class ImplementationVisitor {
void GeneratePrintDefinitions(const std::string& output_directory);
void GenerateClassDefinitions(const std::string& output_directory);
void GenerateClassVerifiers(const std::string& output_directory);
void GenerateExportedMacrosAssembler(const std::string& output_directory);
void GenerateCSATypes(const std::string& output_directory);
VisitResult Visit(Expression* expr);
const Type* Visit(Statement* stmt);
@ -327,7 +329,8 @@ class ImplementationVisitor {
const std::vector<VisitResult>& arguments,
const std::vector<Block*> label_blocks);
void VisitMacroCommon(Macro* macro);
void Visit(Macro* macro);
void Visit(ExternMacro* macro) {}
void Visit(TorqueMacro* macro);
void Visit(Method* macro);
void Visit(Builtin* builtin);
void Visit(NamespaceConstant* decl);
@ -538,11 +541,10 @@ class ImplementationVisitor {
void GenerateMacroFunctionDeclaration(std::ostream& o,
const std::string& macro_prefix,
Macro* macro);
void GenerateFunctionDeclaration(std::ostream& o,
const std::string& macro_prefix,
const std::string& name,
const Signature& signature,
const NameVector& parameter_names);
std::vector<std::string> GenerateFunctionDeclaration(
std::ostream& o, const std::string& macro_prefix, const std::string& name,
const Signature& signature, const NameVector& parameter_names,
bool pass_code_assembler_state = true);
VisitResult GenerateImplicitConvert(const Type* destination_type,
VisitResult source);

View File

@ -83,6 +83,8 @@ void CompileCurrentAst(TorqueCompilerOptions options) {
implementation_visitor.GeneratePrintDefinitions(output_directory);
implementation_visitor.GenerateClassDefinitions(output_directory);
implementation_visitor.GenerateClassVerifiers(output_directory);
implementation_visitor.GenerateExportedMacrosAssembler(output_directory);
implementation_visitor.GenerateCSATypes(output_directory);
for (Namespace* n : GlobalContext::Get().GetNamespaces()) {
implementation_visitor.EndNamespaceFile(n);

View File

@ -10,6 +10,7 @@ namespace torque {
DEFINE_CONTEXTUAL_VARIABLE(TypeOracle)
// static
void TypeOracle::FinalizeClassTypes() {
for (const std::unique_ptr<AggregateType>& p : Get().struct_types_) {
p->Finalize();

View File

@ -95,7 +95,7 @@ std::string Type::GetGeneratedTypeName() const {
std::string Type::GetGeneratedTNodeTypeName() const {
std::string result = GetGeneratedTNodeTypeNameImpl();
if (result.empty()) {
if (result.empty() || IsConstexpr()) {
ReportError("Generated TNode type is required for type '", ToString(),
"'. Use 'generates' clause in definition.");
}
@ -272,7 +272,7 @@ const Field& AggregateType::LookupField(const std::string& name) const {
}
std::string StructType::GetGeneratedTypeNameImpl() const {
return nspace()->ExternalName() + "::" + name();
return "TorqueStruct" + name();
}
std::vector<Method*> AggregateType::Methods(const std::string& name) const {
@ -310,11 +310,7 @@ bool ClassType::HasIndexedField() const {
}
std::string ClassType::GetGeneratedTNodeTypeNameImpl() const {
if (!IsExtern()) return generates_;
std::string prefix = nspace()->IsDefaultNamespace()
? std::string{}
: (nspace()->ExternalName() + "::");
return prefix + generates_;
return generates_;
}
std::string ClassType::GetGeneratedTypeNameImpl() const {

View File

@ -30,11 +30,10 @@ namespace {
using Label = CodeAssemblerLabel;
using Variable = CodeAssemblerVariable;
class TestTorqueAssembler : public CodeStubAssembler,
public TorqueGeneratedTestBuiltinsAssembler {
class TestTorqueAssembler : public CodeStubAssembler {
public:
explicit TestTorqueAssembler(CodeAssemblerState* state)
: CodeStubAssembler(state), TorqueGeneratedTestBuiltinsAssembler(state) {}
: CodeStubAssembler(state) {}
};
} // namespace

View File

@ -339,9 +339,8 @@ namespace test {
return TestStructC{x: TestStruct2(), y: TestStruct2()};
}
@export
macro TestStructInLabel(implicit context: Context)(): never labels
Foo(TestStructA) {
Foo(TestStructA) {
goto Foo(TestStruct2());
}
macro CallTestStructInLabel(implicit context: Context)() {