summaryrefslogtreecommitdiff
path: root/src/decompiler.cc
diff options
context:
space:
mode:
authorWouter van Oortmerssen <aardappel@gmail.com>2020-01-06 09:05:37 -0800
committerGitHub <noreply@github.com>2020-01-06 09:05:37 -0800
commitb4e473279a8d55557efe6071e9e1fce9a3654b46 (patch)
tree2e00ada387e0fb3d3edf885dc2c9ddab32c2dd64 /src/decompiler.cc
parentd008411c9bb1ae11caf9912c625898bba6e12666 (diff)
downloadwabt-b4e473279a8d55557efe6071e9e1fce9a3654b46.tar.gz
wabt-b4e473279a8d55557efe6071e9e1fce9a3654b46.tar.bz2
wabt-b4e473279a8d55557efe6071e9e1fce9a3654b46.zip
wasm-decompile: supporting some more node types specifically. (#1279)
This outputs some more WABT IR node types with special purpose syntax, rather than the default catch-all of a function call. Still incomplete (especially for >MVP), more later. Reworking br_table will be a seperate PR.
Diffstat (limited to 'src/decompiler.cc')
-rw-r--r--src/decompiler.cc65
1 files changed, 64 insertions, 1 deletions
diff --git a/src/decompiler.cc b/src/decompiler.cc
index 0b443225..0a734e3c 100644
--- a/src/decompiler.cc
+++ b/src/decompiler.cc
@@ -298,6 +298,7 @@ struct Decompiler {
assert(false);
break;
}
+ // Existing ExprTypes.
switch (n.etype) {
case ExprType::Const: {
auto& c = cast<ConstExpr>(n.e)->const_;
@@ -436,25 +437,87 @@ struct Decompiler {
case ExprType::Return: {
return WrapNAry(args, "return ", "", Precedence::None);
}
+ case ExprType::Rethrow: {
+ return WrapNAry(args, "rethrow ", "", Precedence::None);
+ }
case ExprType::Drop: {
// Silent dropping of return values is very common, so currently
// don't output this.
return std::move(args[0]);
}
+ case ExprType::Nop: {
+ return Value{{"nop"}, Precedence::None};
+ }
+ case ExprType::Unreachable: {
+ return Value{{"unreachable"}, Precedence::None};
+ }
+ case ExprType::RefNull: {
+ return Value{{"null"}, Precedence::Atomic};
+ }
+ case ExprType::BrTable: {
+ auto bte = cast<BrTableExpr>(n.e);
+ std::string ts = "br_table[";
+ for (auto &v : bte->targets) {
+ ts += v.name();
+ ts += ", ";
+ }
+ ts += "..";
+ ts += bte->default_target.name();
+ ts += "](";
+ return WrapChild(args[0], ts, ")");
+ }
default: {
+ // Everything that looks like a function call.
std::string name;
+ auto precedence = Precedence::Atomic;
switch (n.etype) {
case ExprType::Call:
name = cast<CallExpr>(n.e)->var.name();
break;
+ case ExprType::ReturnCall:
+ name = "return_call " + cast<ReturnCallExpr>(n.e)->var.name();
+ precedence = Precedence::None;
+ break;
case ExprType::Convert:
name = std::string(OpcodeToToken(cast<ConvertExpr>(n.e)->opcode));
break;
+ case ExprType::Ternary:
+ name = std::string(OpcodeToToken(cast<TernaryExpr>(n.e)->opcode));
+ break;
+ case ExprType::Select:
+ // This one looks like it could be translated to "?:" style ternary,
+ // but the arguments are NOT lazy, and side effects definitely do
+ // occur in the branches. So it has no clear equivalent in C-syntax.
+ // To emphasize that all args are being evaluated in order, we
+ // leave it as a function call.
+ name = "select_if";
+ break;
+ case ExprType::MemoryGrow:
+ name = "memory_grow";
+ break;
+ case ExprType::MemorySize:
+ name = "memory_size";
+ break;
+ case ExprType::MemoryCopy:
+ name = "memory_copy";
+ break;
+ case ExprType::MemoryFill:
+ name = "memory_fill";
+ break;
+ case ExprType::RefIsNull:
+ name = "is_null";
+ break;
+ case ExprType::CallIndirect:
+ name = "call_indirect";
+ break;
+ case ExprType::ReturnCallIndirect:
+ name = "return_call call_indirect";
+ break;
default:
name = GetExprTypeName(n.etype);
break;
}
- return WrapNAry(args, name + "(", ")", Precedence::Atomic);
+ return WrapNAry(args, name + "(", ")", precedence);
}
}
}