Commit 6b158455 authored by Seth Brenith's avatar Seth Brenith Committed by V8 LUCI CQ

[torque] Emit an error if a macro recursively calls itself

Rather than letting a recursive macro expansion cause a stack overflow
and crash the compiler, this change updates Torque to emit an error as
soon as the recursion is detected. Eventually it would be nice to make
Cast macros a little more magical so they don't require so much human
effort to maintain, but at least this way Torque displays some
information about what went wrong. An example error message (manually
wrapped to 72 character width) follows.

src/builtins/cast.tq:157:10: Torque Error: Recursive macro call to
  callable Cast<(class Context | Undefined | Zero)>(implicit class
  Context)(Object): (class Context | Undefined | Zero)
src/builtins/cast.tq:758:3: Torque Error: Note: in specialization
  Cast<(class Context | Undefined | Zero)> requested here
src/builtins/cast.tq:764:10: Torque Error: Note: in specialization
  Is<(class Context | Undefined | Zero), Object> requested here
src/builtins/torque-internal.tq:64:3: Torque Error: Note: in
  specialization UnsafeCast<(class Context | Undefined | Zero)>
  requested here
src/objects/contexts.tq:75:10: Torque Error: Note: in specialization
  ReferenceCast<(class Context | Undefined | Zero), Object> requested
  here
src/builtins/iterator.tq:142:16: Torque Error: Note: in specialization
  ContextSlot<class Context, class Context, (class Context | Undefined |
  Zero)> requested here

Bug: v8:11727
Change-Id: I7b5b1852dee16a6860f593f27783f6b2d9366146
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2965032Reviewed-by: 's avatarNico Hartmann <nicohartmann@chromium.org>
Commit-Queue: Seth Brenith <seth.brenith@microsoft.com>
Cr-Commit-Position: refs/heads/master@{#75184}
parent 274aaaaf
......@@ -244,10 +244,28 @@ void ImplementationVisitor::Visit(TypeAlias* alias) {
}
}
class ImplementationVisitor::MacroInliningScope {
public:
MacroInliningScope(ImplementationVisitor* visitor, const Macro* macro)
: visitor_(visitor), macro_(macro) {
if (!visitor_->inlining_macros_.insert(macro).second) {
// Recursive macro expansion would just keep going until stack overflow.
// To avoid crashes, throw an error immediately.
ReportError("Recursive macro call to ", *macro);
}
}
~MacroInliningScope() { visitor_->inlining_macros_.erase(macro_); }
private:
ImplementationVisitor* visitor_;
const Macro* macro_;
};
VisitResult ImplementationVisitor::InlineMacro(
Macro* macro, base::Optional<LocationReference> this_reference,
const std::vector<VisitResult>& arguments,
const std::vector<Block*> label_blocks) {
MacroInliningScope macro_inlining_scope(this, macro);
CurrentScope::Scope current_scope(macro);
BindingsManagersScope bindings_managers_scope;
CurrentCallable::Scope current_callable(macro);
......
......@@ -842,6 +842,8 @@ class ImplementationVisitor {
}
}
class MacroInliningScope;
base::Optional<CfgAssembler> assembler_;
NullOStream null_stream_;
bool is_dry_run_;
......@@ -854,6 +856,10 @@ class ImplementationVisitor {
std::unordered_map<const Expression*, const Identifier*>
bitfield_expressions_;
// For emitting warnings. Contains the current set of macros being inlined in
// calls to InlineMacro.
std::unordered_set<const Macro*> inlining_macros_;
// The contents of the debug macros output files. These contain all Torque
// macros that have been generated using the C++ backend with debug purpose.
std::stringstream debug_macros_cc_;
......
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