Skip to content

Commit 9a1516f

Browse files
authored
[NFC] Simplify printing of unreachable replacements (#8616)
When an instruction has a type immediate that we cannot print because the expression it is supposed to come from has unreachable or null type, we instead print an unreachable block with a comment saying what instruction we failed to print. We previously handled this via different code paths for type immediates that come from child expressions that type immediates that come from the printed expression's own return type. Unify these code paths in the printer by improving `Properties::hasUnwritableTypeImmediate` to handle both cases. Also fix the printing of `ShallowExpression` to check for unwritable type immediates first to avoid assertion failures.
1 parent f051945 commit 9a1516f

File tree

3 files changed

+41
-72
lines changed

3 files changed

+41
-72
lines changed

src/ir/properties.h

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -521,8 +521,8 @@ inline MemoryOrder getMemoryOrder(Expression* curr) {
521521
}
522522

523523
// Whether this instruction will be unwritable in the text and binary formats
524-
// because it requires a type index immediate giving the type of a child that
525-
// has unreachable or null type, and therefore does not have a type index.
524+
// because it requires a type index immediate computed from an expression with
525+
// unreachable or null type, and therefore no type index.
526526
inline bool hasUnwritableTypeImmediate(Expression* curr) {
527527
#define DELEGATE_ID curr->_id
528528

@@ -534,6 +534,24 @@ inline bool hasUnwritableTypeImmediate(Expression* curr) {
534534
} \
535535
}
536536

537+
#define DELEGATE_IMMEDIATE_TYPED_RESULT(id) \
538+
if (curr->type == Type::unreachable) { \
539+
if constexpr (id::SpecificId == Expression::Id::RefCastId) { \
540+
auto* cast = curr->cast<RefCast>(); \
541+
if (!cast->desc) { \
542+
return true; \
543+
} \
544+
if (!cast->desc->type.isRef()) { \
545+
return true; \
546+
} \
547+
if (!cast->desc->type.getHeapType().getDescribedType()) { \
548+
return true; \
549+
} \
550+
return false; \
551+
} \
552+
return true; \
553+
}
554+
537555
#define DELEGATE_FIELD_CHILD(id, field)
538556
#define DELEGATE_FIELD_CHILD_VECTOR(id, field)
539557
#define DELEGATE_FIELD_INT(id, field)

src/passes/Print.cpp

Lines changed: 4 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -320,63 +320,6 @@ struct PrintSExpression : public UnifiedExpressionVisitor<PrintSExpression> {
320320
void visitTryTable(TryTable* curr);
321321

322322
void printUnreachableReplacement(Expression* curr);
323-
bool maybePrintUnreachableReplacement(Expression* curr, Type type);
324-
void visitRefCast(RefCast* curr) {
325-
if ((curr->desc && curr->desc->type != Type::unreachable) ||
326-
!maybePrintUnreachableReplacement(curr, curr->type)) {
327-
visitExpression(curr);
328-
}
329-
}
330-
void visitStructNew(StructNew* curr) {
331-
if (!maybePrintUnreachableReplacement(curr, curr->type)) {
332-
visitExpression(curr);
333-
}
334-
}
335-
void visitArrayNew(ArrayNew* curr) {
336-
if (!maybePrintUnreachableReplacement(curr, curr->type)) {
337-
visitExpression(curr);
338-
}
339-
}
340-
void visitArrayNewData(ArrayNewData* curr) {
341-
if (!maybePrintUnreachableReplacement(curr, curr->type)) {
342-
visitExpression(curr);
343-
}
344-
}
345-
void visitArrayNewElem(ArrayNewElem* curr) {
346-
if (!maybePrintUnreachableReplacement(curr, curr->type)) {
347-
visitExpression(curr);
348-
}
349-
}
350-
void visitArrayNewFixed(ArrayNewFixed* curr) {
351-
if (!maybePrintUnreachableReplacement(curr, curr->type)) {
352-
visitExpression(curr);
353-
}
354-
}
355-
void visitContNew(ContNew* curr) {
356-
if (!maybePrintUnreachableReplacement(curr, curr->type)) {
357-
visitExpression(curr);
358-
}
359-
}
360-
void visitContBind(ContBind* curr) {
361-
if (!maybePrintUnreachableReplacement(curr, curr->type)) {
362-
visitExpression(curr);
363-
}
364-
}
365-
void visitResume(Resume* curr) {
366-
if (!maybePrintUnreachableReplacement(curr, curr->type)) {
367-
visitExpression(curr);
368-
}
369-
}
370-
void visitResumeThrow(ResumeThrow* curr) {
371-
if (!maybePrintUnreachableReplacement(curr, curr->type)) {
372-
visitExpression(curr);
373-
}
374-
}
375-
void visitStackSwitch(StackSwitch* curr) {
376-
if (!maybePrintUnreachableReplacement(curr, curr->type)) {
377-
visitExpression(curr);
378-
}
379-
}
380323

381324
// Module-level visitors
382325
void handleSignature(Function* curr, bool printImplicitNames = false);
@@ -3143,19 +3086,6 @@ void PrintSExpression::printUnreachableReplacement(Expression* curr) {
31433086
decIndent();
31443087
}
31453088

3146-
bool PrintSExpression::maybePrintUnreachableReplacement(Expression* curr,
3147-
Type type) {
3148-
// When we cannot print an instruction because the child from which it's
3149-
// supposed to get a type immediate is unreachable, then we print a
3150-
// semantically-equivalent block that drops each of the children and ends in
3151-
// an unreachable.
3152-
if (type == Type::unreachable) {
3153-
printUnreachableReplacement(curr);
3154-
return true;
3155-
}
3156-
return false;
3157-
}
3158-
31593089
static bool requiresExplicitFuncType(HeapType type) {
31603090
// When the `(type $f)` in a function's typeuse is omitted, the typeuse
31613091
// matches or declares an MVP function type. When the intended type is not an
@@ -4009,6 +3939,10 @@ std::ostream& operator<<(std::ostream& o, wasm::ModuleExpression pair) {
40093939
}
40103940

40113941
std::ostream& operator<<(std::ostream& o, wasm::ShallowExpression expression) {
3942+
if (Properties::hasUnwritableTypeImmediate(expression.expr)) {
3943+
o << "(; unreachable " << getExpressionName(expression.expr) << " ;)";
3944+
return o;
3945+
}
40123946
wasm::PrintSExpression printer(o);
40133947
printer.setModule(expression.module);
40143948
wasm::PrintExpressionContents(printer).visit(expression.expr);

src/wasm-delegations-fields.def

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,10 @@
2929
//
3030
// DELEGATE_END(id) - called at the end of a case.
3131
//
32+
// DELEGATE_IMMEDIATE_TYPED_RESULT(id) - does not actually represent a field,
33+
// but is called for expressions whose result types are used to compute type
34+
// immediates. Defining this is optional.
35+
//
3236
// DELEGATE_GET_FIELD(id, field) - called to get a field by its name. This must
3337
// know the object on which to get it, so it is just useful for the case
3438
// where you operate on a single such object, but in that case it is nice
@@ -117,6 +121,10 @@
117121
#define DELEGATE_END(id)
118122
#endif
119123

124+
#ifndef DELEGATE_IMMEDIATE_TYPED_RESULT
125+
#define DELEGATE_IMMEDIATE_TYPED_RESULT(id)
126+
#endif
127+
120128
#ifndef DELEGATE_FIELD_CHILD
121129
#error please define DELEGATE_FIELD_CHILD(id, field)
122130
#endif
@@ -659,6 +667,7 @@ DELEGATE_FIELD_CHILD(RefTest, ref)
659667
DELEGATE_FIELD_CASE_END(RefTest)
660668

661669
DELEGATE_FIELD_CASE_START(RefCast)
670+
DELEGATE_IMMEDIATE_TYPED_RESULT(RefCast)
662671
DELEGATE_FIELD_OPTIONAL_IMMEDIATE_TYPED_CHILD(RefCast, desc)
663672
DELEGATE_FIELD_CHILD(RefCast, ref)
664673
DELEGATE_FIELD_CASE_END(RefCast)
@@ -676,6 +685,7 @@ DELEGATE_FIELD_CHILD(BrOn, ref)
676685
DELEGATE_FIELD_CASE_END(BrOn)
677686

678687
DELEGATE_FIELD_CASE_START(StructNew)
688+
DELEGATE_IMMEDIATE_TYPED_RESULT(StructNew)
679689
DELEGATE_FIELD_OPTIONAL_CHILD(StructNew, desc)
680690
DELEGATE_FIELD_CHILD_VECTOR(StructNew, operands)
681691
DELEGATE_FIELD_CASE_END(StructNew)
@@ -711,23 +721,27 @@ DELEGATE_FIELD_INT(StructCmpxchg, order)
711721
DELEGATE_FIELD_CASE_END(StructCmpxchg)
712722

713723
DELEGATE_FIELD_CASE_START(ArrayNew)
724+
DELEGATE_IMMEDIATE_TYPED_RESULT(ArrayNew)
714725
DELEGATE_FIELD_CHILD(ArrayNew, size)
715726
DELEGATE_FIELD_OPTIONAL_CHILD(ArrayNew, init)
716727
DELEGATE_FIELD_CASE_END(ArrayNew)
717728

718729
DELEGATE_FIELD_CASE_START(ArrayNewData)
730+
DELEGATE_IMMEDIATE_TYPED_RESULT(ArrayNewData)
719731
DELEGATE_FIELD_NAME_KIND(ArrayNewData, segment, ModuleItemKind::DataSegment)
720732
DELEGATE_FIELD_CHILD(ArrayNewData, size)
721733
DELEGATE_FIELD_CHILD(ArrayNewData, offset)
722734
DELEGATE_FIELD_CASE_END(ArrayNewData)
723735

724736
DELEGATE_FIELD_CASE_START(ArrayNewElem)
737+
DELEGATE_IMMEDIATE_TYPED_RESULT(ArrayNewElem)
725738
DELEGATE_FIELD_NAME_KIND(ArrayNewElem, segment, ModuleItemKind::ElementSegment)
726739
DELEGATE_FIELD_CHILD(ArrayNewElem, size)
727740
DELEGATE_FIELD_CHILD(ArrayNewElem, offset)
728741
DELEGATE_FIELD_CASE_END(ArrayNewElem)
729742

730743
DELEGATE_FIELD_CASE_START(ArrayNewFixed)
744+
DELEGATE_IMMEDIATE_TYPED_RESULT(ArrayNewFixed)
731745
DELEGATE_FIELD_CHILD_VECTOR(ArrayNewFixed, values)
732746
DELEGATE_FIELD_CASE_END(ArrayNewFixed)
733747

@@ -866,10 +880,12 @@ DELEGATE_FIELD_CHILD(StringSliceWTF, ref)
866880
DELEGATE_FIELD_CASE_END(StringSliceWTF)
867881

868882
DELEGATE_FIELD_CASE_START(ContNew)
883+
DELEGATE_IMMEDIATE_TYPED_RESULT(ContNew)
869884
DELEGATE_FIELD_CHILD(ContNew, func)
870885
DELEGATE_FIELD_CASE_END(ContNew)
871886

872887
DELEGATE_FIELD_CASE_START(ContBind)
888+
DELEGATE_IMMEDIATE_TYPED_RESULT(ContBind)
873889
DELEGATE_FIELD_IMMEDIATE_TYPED_CHILD(ContBind, cont)
874890
DELEGATE_FIELD_CHILD_VECTOR(ContBind, operands)
875891
DELEGATE_FIELD_CASE_END(ContBind)
@@ -921,6 +937,7 @@ DELEGATE_FIELD_MAIN_END
921937
#undef DELEGATE_ID
922938
#undef DELEGATE_START
923939
#undef DELEGATE_END
940+
#undef DELEGATE_IMMEDIATE_TYPED_RESULT
924941
#undef DELEGATE_FIELD_CHILD
925942
#undef DELEGATE_FIELD_IMMEDIATE_TYPED_CHILD
926943
#undef DELEGATE_FIELD_OPTIONAL_CHILD

0 commit comments

Comments
 (0)