summaryrefslogtreecommitdiff
path: root/src/wasm-builder.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/wasm-builder.h')
-rw-r--r--src/wasm-builder.h62
1 files changed, 61 insertions, 1 deletions
diff --git a/src/wasm-builder.h b/src/wasm-builder.h
index 2277fed93..3ca3d9daf 100644
--- a/src/wasm-builder.h
+++ b/src/wasm-builder.h
@@ -18,6 +18,7 @@
#define wasm_wasm_builder_h
#include "ir/manipulation.h"
+#include "parsing.h"
#include "wasm.h"
namespace wasm {
@@ -39,7 +40,7 @@ class Builder {
public:
Builder(Module& wasm) : wasm(wasm) {}
- // make* functions, other globals
+ // make* functions create an expression instance.
static std::unique_ptr<Function> makeFunction(Name name,
Signature sig,
@@ -1116,6 +1117,65 @@ public:
}
};
+// This class adds methods that first inspect the input. They may not have fully
+// comprehensive error checking, when that can be left to the validator; the
+// benefit of the validate* methods is that they can share code between the
+// text and binary format parsers, for handling certain situations in the
+// input which preclude even creating valid IR, which the validator depends
+// on.
+class ValidatingBuilder : public Builder {
+ size_t line = -1, col = -1;
+
+public:
+ ValidatingBuilder(Module& wasm, size_t line) : Builder(wasm), line(line) {}
+ ValidatingBuilder(Module& wasm, size_t line, size_t col)
+ : Builder(wasm), line(line), col(col) {}
+
+ Expression* validateAndMakeBrOn(BrOnOp op,
+ Name name,
+ Expression* ref,
+ Expression* rtt = nullptr) {
+ if (op == BrOnCast) {
+ if (rtt->type == Type::unreachable) {
+ // An unreachable rtt is not supported: the text and binary formats do
+ // not provide the type, so if it's unreachable we should not even
+ // create a br_on_cast in such a case, as we'd have no idea what it
+ // casts to.
+ return makeSequence(makeDrop(ref), rtt);
+ }
+ }
+ if (op == BrOnNull) {
+ if (!ref->type.isRef() && ref->type != Type::unreachable) {
+ throw ParseException("Invalid ref for br_on_null", line, col);
+ }
+ }
+ return makeBrOn(op, name, ref, rtt);
+ }
+
+ template<typename T>
+ Expression* validateAndMakeCallRef(Expression* target,
+ const T& args,
+ bool isReturn = false) {
+ if (!target->type.isRef()) {
+ if (target->type == Type::unreachable) {
+ // An unreachable target is not supported. Similiar to br_on_cast, just
+ // emit an unreachable sequence, since we don't have enough information
+ // to create a full call_ref.
+ auto* block = makeBlock(args);
+ block->list.push_back(target);
+ block->finalize(Type::unreachable);
+ return block;
+ }
+ throw ParseException("Non-reference type for a call_ref", line, col);
+ }
+ auto heapType = target->type.getHeapType();
+ if (!heapType.isSignature()) {
+ throw ParseException("Invalid reference type for a call_ref", line, col);
+ }
+ return makeCallRef(target, args, heapType.getSignature().results, isReturn);
+ }
+};
+
} // namespace wasm
#endif // wasm_wasm_builder_h