Skip to content

Commit 1744c8e

Browse files
committed
[NFC] Simplify printing of unreachable replacements
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 2d093c2 commit 1744c8e

File tree

2 files changed

+25
-72
lines changed

2 files changed

+25
-72
lines changed

src/ir/properties.h

Lines changed: 21 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

@@ -552,6 +552,25 @@ inline bool hasUnwritableTypeImmediate(Expression* curr) {
552552

553553
#include "wasm-delegations-fields.def"
554554

555+
if (curr->type == Type::unreachable) {
556+
if (curr->is<StructNew>() || curr->is<ArrayNew>() ||
557+
curr->is<ArrayNewData>() || curr->is<ArrayNewElem>() ||
558+
curr->is<ArrayNewFixed>() || curr->is<ContNew>() ||
559+
curr->is<ContBind>()) {
560+
return true;
561+
}
562+
if (auto* cast = curr->dynCast<RefCast>()) {
563+
if (!cast->desc) {
564+
return true;
565+
}
566+
if (!cast->desc->type.isRef()) {
567+
return true;
568+
}
569+
if (!cast->desc->type.getHeapType().getDescribedType()) {
570+
return true;
571+
};
572+
}
573+
}
555574
return false;
556575
}
557576

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);

0 commit comments

Comments
 (0)