Skip to content

Commit

Permalink
Add string parameter to WASM_UNREACHABLE
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 (where asserts are disabled).

Right now binaryen always builds with asserts on, even in release builds
mains so that WASM_UNREACHABLE can report useful information.  However
with this new method we can turn on asserts and still have
WASM_UNREACHABLE be useful.
  • Loading branch information
sbc100 committed Dec 4, 2019
1 parent 19d929c commit 47bdfe3
Show file tree
Hide file tree
Showing 56 changed files with 435 additions and 419 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 @@ -781,7 +781,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
14 changes: 7 additions & 7 deletions src/ir/ReFinalize.cpp
Expand Up @@ -180,13 +180,13 @@ 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 47bdfe3

Please sign in to comment.