Skip to content

Commit

Permalink
Add string parameter to WASM_UNREACHABLE (#2499)
Browse files Browse the repository at this point in the history
This works more like llvm's unreachable handler in that is preserves
information even in release builds.
  • Loading branch information
sbc100 committed Dec 5, 2019
1 parent cbf121d commit a28343a
Show file tree
Hide file tree
Showing 56 changed files with 450 additions and 420 deletions.
2 changes: 1 addition & 1 deletion src/abi/stack.h
Expand Up @@ -93,7 +93,7 @@ getStackSpace(Index local, Function* func, Index size, Module& wasm) {
builder.makeLocalGet(local, PointerType),
builder.makeConst(Literal(int32_t(size))));
} else {
WASM_UNREACHABLE();
WASM_UNREACHABLE("unhandled PointerType");
}
block->list.push_back(builder.makeGlobalSet(stackPointer->name, added));
auto makeStackRestore = [&]() {
Expand Down
8 changes: 4 additions & 4 deletions src/asm2wasm.h
Expand Up @@ -1548,7 +1548,7 @@ void Asm2WasmBuilder::processAsm(Ref ast) {
break;
}
default:
WASM_UNREACHABLE();
WASM_UNREACHABLE("unexpected type");
}
} else {
assert(old == none);
Expand Down Expand Up @@ -2060,7 +2060,7 @@ Function* Asm2WasmBuilder::processFunction(Ref ast) {
ret->op = NegFloat32;
ret->type = Type::f32;
} else {
WASM_UNREACHABLE();
WASM_UNREACHABLE("unexpected asm type");
}
return ret;
} else if (ast[1] == B_NOT) {
Expand Down Expand Up @@ -2195,7 +2195,7 @@ Function* Asm2WasmBuilder::processFunction(Ref ast) {
ret->type = value->type;
return ret;
} else {
WASM_UNREACHABLE();
WASM_UNREACHABLE("unexpected type");
}
}
if (name == Math_floor || name == Math_sqrt || name == Math_ceil) {
Expand Down Expand Up @@ -2328,7 +2328,7 @@ Function* Asm2WasmBuilder::processFunction(Ref ast) {
process(ast[2][2]),
asmToWasmType(view.type));
}
WASM_UNREACHABLE();
WASM_UNREACHABLE("unexpected atomic op");
}
bool tableCall = false;
if (wasmOnly) {
Expand Down
10 changes: 5 additions & 5 deletions src/asmjs/asm_v_wasm.cpp
Expand Up @@ -38,7 +38,7 @@ Type asmToWasmType(AsmType asmType) {
case ASM_INT32X4:
return Type::v128;
}
WASM_UNREACHABLE();
WASM_UNREACHABLE("invalid type");
}

AsmType wasmToAsmType(Type type) {
Expand All @@ -60,9 +60,9 @@ AsmType wasmToAsmType(Type type) {
case none:
return ASM_NONE;
case unreachable:
WASM_UNREACHABLE();
WASM_UNREACHABLE("invalid type");
}
WASM_UNREACHABLE();
WASM_UNREACHABLE("invalid type");
}

char getSig(Type type) {
Expand All @@ -84,9 +84,9 @@ char getSig(Type type) {
case none:
return 'v';
case unreachable:
WASM_UNREACHABLE();
WASM_UNREACHABLE("invalid type");
}
WASM_UNREACHABLE();
WASM_UNREACHABLE("invalid type");
}

std::string getSig(const FunctionType* type) {
Expand Down
8 changes: 4 additions & 4 deletions src/binaryen-c.cpp
Expand Up @@ -74,7 +74,7 @@ BinaryenLiteral toBinaryenLiteral(Literal x) {
case Type::exnref: // there's no exnref literals
case Type::none:
case Type::unreachable:
WASM_UNREACHABLE();
WASM_UNREACHABLE("unexpected type");
}
return ret;
}
Expand All @@ -95,9 +95,9 @@ Literal fromBinaryenLiteral(BinaryenLiteral x) {
case Type::exnref: // there's no exnref literals
case Type::none:
case Type::unreachable:
WASM_UNREACHABLE();
WASM_UNREACHABLE("unexpected type");
}
WASM_UNREACHABLE();
WASM_UNREACHABLE("invalid type");
}

// Mutexes (global for now; in theory if multiple modules
Expand Down Expand Up @@ -216,7 +216,7 @@ void printArg(std::ostream& setup, std::ostream& out, BinaryenLiteral arg) {
case Type::exnref: // there's no exnref literals
case Type::none:
case Type::unreachable:
WASM_UNREACHABLE();
WASM_UNREACHABLE("unexpected type");
}
}

Expand Down
2 changes: 1 addition & 1 deletion src/cfg/cfg-traversal.h
Expand Up @@ -365,7 +365,7 @@ struct CFGWalker : public ControlFlowWalker<SubType, VisitorType> {
return;
}
}
WASM_UNREACHABLE();
WASM_UNREACHABLE("not found");
}
};

Expand Down
23 changes: 3 additions & 20 deletions src/compiler-support.h
Expand Up @@ -25,27 +25,10 @@
#define __has_builtin(x) 0
#endif

// If control flow reaches the point of the WASM_UNREACHABLE(), the program is
// undefined.
#if __has_builtin(__builtin_unreachable) && defined(NDEBUG)
#define WASM_UNREACHABLE() __builtin_unreachable()
#if __has_builtin(__builtin_unreachable)
#define WASM_BUILTIN_UNREACHABLE __builtin_unreachable()
#elif defined(_MSC_VER)
#define WASM_UNREACHABLE() __assume(false)
#elif __has_feature(address_sanitizer) || defined(__SANITIZE_ADDRESS__)
#include "sanitizer/common_interface_defs.h"
#define WASM_UNREACHABLE() \
do { \
__sanitizer_print_stack_trace(); \
__builtin_trap(); \
} while (0)
#else
#include <assert.h>
#include <stdlib.h>
#define WASM_UNREACHABLE() \
do { \
assert(false); \
abort(); \
} while (0)
#define WASM_BUILTIN_UNREACHABLE __assume(false)
#endif

#ifdef __GNUC__
Expand Down
4 changes: 2 additions & 2 deletions src/dataflow/graph.h
Expand Up @@ -547,7 +547,7 @@ struct Graph : public UnifiedExpressionVisitor<Graph, Node*> {
opposite = LeUInt64;
break;
default:
WASM_UNREACHABLE();
WASM_UNREACHABLE("unexpected op");
}
auto* ret =
visitBinary(builder.makeBinary(opposite, curr->right, curr->left));
Expand Down Expand Up @@ -783,7 +783,7 @@ struct Graph : public UnifiedExpressionVisitor<Graph, Node*> {
// variable value.
return Builder(*module).makeCall(FAKE_CALL, {}, node->wasmType);
} else {
WASM_UNREACHABLE(); // TODO
WASM_UNREACHABLE("unexpected node type"); // TODO
}
}

Expand Down
2 changes: 1 addition & 1 deletion src/dataflow/node.h
Expand Up @@ -165,7 +165,7 @@ struct Node {
case Bad:
return unreachable;
default:
WASM_UNREACHABLE();
WASM_UNREACHABLE("invalid node type");
}
}

Expand Down
2 changes: 0 additions & 2 deletions src/dataflow/utils.h
Expand Up @@ -67,8 +67,6 @@ inline std::ostream& dump(Node* node, std::ostream& o, size_t indent = 0) {
case Node::Type::Bad:
o << "bad";
break;
default:
WASM_UNREACHABLE();
}
if (!node->values.empty()) {
o << '\n';
Expand Down
16 changes: 9 additions & 7 deletions src/ir/ReFinalize.cpp
Expand Up @@ -151,13 +151,15 @@ void ReFinalize::visitFunction(Function* curr) {
}
}

void ReFinalize::visitFunctionType(FunctionType* curr) { WASM_UNREACHABLE(); }
void ReFinalize::visitExport(Export* curr) { WASM_UNREACHABLE(); }
void ReFinalize::visitGlobal(Global* curr) { WASM_UNREACHABLE(); }
void ReFinalize::visitTable(Table* curr) { WASM_UNREACHABLE(); }
void ReFinalize::visitMemory(Memory* curr) { WASM_UNREACHABLE(); }
void ReFinalize::visitEvent(Event* curr) { WASM_UNREACHABLE(); }
void ReFinalize::visitModule(Module* curr) { WASM_UNREACHABLE(); }
void ReFinalize::visitFunctionType(FunctionType* curr) {
WASM_UNREACHABLE("unimp");
}
void ReFinalize::visitExport(Export* curr) { WASM_UNREACHABLE("unimp"); }
void ReFinalize::visitGlobal(Global* curr) { WASM_UNREACHABLE("unimp"); }
void ReFinalize::visitTable(Table* curr) { WASM_UNREACHABLE("unimp"); }
void ReFinalize::visitMemory(Memory* curr) { WASM_UNREACHABLE("unimp"); }
void ReFinalize::visitEvent(Event* curr) { WASM_UNREACHABLE("unimp"); }
void ReFinalize::visitModule(Module* curr) { WASM_UNREACHABLE("unimp"); }

void ReFinalize::updateBreakValueType(Name name, Type type) {
if (type != unreachable || breakValues.count(name) == 0) {
Expand Down
10 changes: 4 additions & 6 deletions src/ir/abstract.h
Expand Up @@ -78,8 +78,7 @@ inline UnaryOp getUnary(Type type, Op op) {
break;
}
case v128: {
assert(false && "v128 not implemented yet");
WASM_UNREACHABLE();
WASM_UNREACHABLE("v128 not implemented yet");
}
case anyref: // there's no unary instructions for anyref
case exnref: // there's no unary instructions for exnref
Expand All @@ -88,7 +87,7 @@ inline UnaryOp getUnary(Type type, Op op) {
return InvalidUnary;
}
}
WASM_UNREACHABLE();
WASM_UNREACHABLE("invalid type");
}

inline BinaryOp getBinary(Type type, Op op) {
Expand Down Expand Up @@ -210,8 +209,7 @@ inline BinaryOp getBinary(Type type, Op op) {
break;
}
case v128: {
assert(false && "v128 not implemented yet");
WASM_UNREACHABLE();
WASM_UNREACHABLE("v128 not implemented yet");
}
case anyref: // there's no binary instructions for anyref
case exnref: // there's no binary instructions for exnref
Expand All @@ -220,7 +218,7 @@ inline BinaryOp getBinary(Type type, Op op) {
return InvalidBinary;
}
}
WASM_UNREACHABLE();
WASM_UNREACHABLE("invalid type");
}

} // namespace Abstract
Expand Down
4 changes: 2 additions & 2 deletions src/ir/bits.h
Expand Up @@ -60,7 +60,7 @@ struct Bits {
} else if (type == i64) {
return amount & 63;
}
WASM_UNREACHABLE();
WASM_UNREACHABLE("unexpected type");
}

static Index getEffectiveShifts(Expression* expr) {
Expand All @@ -70,7 +70,7 @@ struct Bits {
} else if (amount->type == i64) {
return getEffectiveShifts(amount->value.geti64(), i64);
}
WASM_UNREACHABLE();
WASM_UNREACHABLE("unexpected type");
}

static Expression* makeSignExt(Expression* value, Index bytes, Module& wasm) {
Expand Down
4 changes: 2 additions & 2 deletions src/ir/branch-utils.h
Expand Up @@ -49,7 +49,7 @@ inline bool isBranchReachable(Expression* expr) {
} else if (auto* br = expr->dynCast<BrOnExn>()) {
return isBranchReachable(br);
}
WASM_UNREACHABLE();
WASM_UNREACHABLE("unexpected expression type");
}

inline std::set<Name> getUniqueTargets(Break* br) { return {br->name}; }
Expand Down Expand Up @@ -90,7 +90,7 @@ inline bool replacePossibleTarget(Expression* branch, Name from, Name to) {
worked = true;
}
} else {
WASM_UNREACHABLE();
WASM_UNREACHABLE("unexpected expression type");
}
return worked;
}
Expand Down
4 changes: 2 additions & 2 deletions src/ir/cost.h
Expand Up @@ -188,7 +188,7 @@ struct CostAnalyzer : public Visitor<CostAnalyzer, Index> {
case WidenHighUVecI16x8ToVecI32x4:
return 1;
case InvalidUnary:
WASM_UNREACHABLE();
WASM_UNREACHABLE("invalid unary op");
}
return ret + visit(curr->value);
}
Expand Down Expand Up @@ -709,7 +709,7 @@ struct CostAnalyzer : public Visitor<CostAnalyzer, Index> {
ret = 1;
break;
case InvalidBinary:
WASM_UNREACHABLE();
WASM_UNREACHABLE("invalid binary op");
}
return ret + visit(curr->left) + visit(curr->right);
}
Expand Down
14 changes: 7 additions & 7 deletions src/ir/utils.h
Expand Up @@ -220,13 +220,13 @@ struct ReFinalizeNode : public OverriddenVisitor<ReFinalizeNode> {
void visitPush(Push* curr) { curr->finalize(); }
void visitPop(Pop* curr) { curr->finalize(); }

void visitFunctionType(FunctionType* curr) { WASM_UNREACHABLE(); }
void visitExport(Export* curr) { WASM_UNREACHABLE(); }
void visitGlobal(Global* curr) { WASM_UNREACHABLE(); }
void visitTable(Table* curr) { WASM_UNREACHABLE(); }
void visitMemory(Memory* curr) { WASM_UNREACHABLE(); }
void visitEvent(Event* curr) { WASM_UNREACHABLE(); }
void visitModule(Module* curr) { WASM_UNREACHABLE(); }
void visitFunctionType(FunctionType* curr) { WASM_UNREACHABLE("unimp"); }
void visitExport(Export* curr) { WASM_UNREACHABLE("unimp"); }
void visitGlobal(Global* curr) { WASM_UNREACHABLE("unimp"); }
void visitTable(Table* curr) { WASM_UNREACHABLE("unimp"); }
void visitMemory(Memory* curr) { WASM_UNREACHABLE("unimp"); }
void visitEvent(Event* curr) { WASM_UNREACHABLE("unimp"); }
void visitModule(Module* curr) { WASM_UNREACHABLE("unimp"); }

// given a stack of nested expressions, update them all from child to parent
static void updateStack(ExpressionStack& expressionStack) {
Expand Down
6 changes: 3 additions & 3 deletions src/literal.h
Expand Up @@ -84,9 +84,9 @@ class Literal {
case Type::exnref: // there's no exnref literals
case none:
case unreachable:
WASM_UNREACHABLE();
WASM_UNREACHABLE("unexpected type");
}
WASM_UNREACHABLE();
WASM_UNREACHABLE("unexpected type");
}

inline static Literal makeZero(Type type) { return makeFromInt32(0, type); }
Expand Down Expand Up @@ -467,7 +467,7 @@ template<> struct less<wasm::Literal> {
case wasm::Type::unreachable:
return false;
}
WASM_UNREACHABLE();
WASM_UNREACHABLE("unexpected type");
}
};
} // namespace std
Expand Down
2 changes: 1 addition & 1 deletion src/parsing.h
Expand Up @@ -265,7 +265,7 @@ parseConst(cashew::IString s, Type type, MixedArena& allocator) {
case v128:
case anyref: // there's no anyref.const
case exnref: // there's no exnref.const
WASM_UNREACHABLE();
WASM_UNREACHABLE("unexpected const type");
case none:
case unreachable: {
return nullptr;
Expand Down
8 changes: 5 additions & 3 deletions src/pass.h
Expand Up @@ -254,13 +254,15 @@ class Pass {
virtual void prepareToRun(PassRunner* runner, Module* module) {}

// Implement this with code to run the pass on the whole module
virtual void run(PassRunner* runner, Module* module) { WASM_UNREACHABLE(); }
virtual void run(PassRunner* runner, Module* module) {
WASM_UNREACHABLE("unimplemented");
}

// Implement this with code to run the pass on a single function, for
// a function-parallel pass
virtual void
runOnFunction(PassRunner* runner, Module* module, Function* function) {
WASM_UNREACHABLE();
WASM_UNREACHABLE("unimplemented");
}

// Function parallelism. By default, passes are not run in parallel, but you
Expand All @@ -285,7 +287,7 @@ class Pass {
// This method is used to create instances per function for a
// function-parallel pass. You may need to override this if you subclass a
// Walker, as otherwise this will create the parent class.
virtual Pass* create() { WASM_UNREACHABLE(); }
virtual Pass* create() { WASM_UNREACHABLE("unimplenented"); }

// Whether this pass modifies the Binaryen IR in the module. This is true for
// most passes, except for passes that have no side effects, or passes that
Expand Down

0 comments on commit a28343a

Please sign in to comment.