summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/binary-reader-interpreter.cc99
-rw-r--r--src/type-checker.cc473
-rw-r--r--src/type-checker.h152
-rw-r--r--src/validator.cc100
4 files changed, 407 insertions, 417 deletions
diff --git a/src/binary-reader-interpreter.cc b/src/binary-reader-interpreter.cc
index 23f5d745..0acd40fe 100644
--- a/src/binary-reader-interpreter.cc
+++ b/src/binary-reader-interpreter.cc
@@ -208,7 +208,6 @@ class BinaryReaderInterpreter : public BinaryReaderNop {
bool HandleError(Offset offset, const char* message);
void PrintError(const char* format, ...);
- static void OnTypecheckerError(const char* msg, void* user_data);
Index TranslateSigIndexToEnv(Index sig_index);
FuncSignature* GetSignatureByModuleIndex(Index sig_index);
@@ -267,7 +266,6 @@ class BinaryReaderInterpreter : public BinaryReaderNop {
Environment* env = nullptr;
DefinedModule* module = nullptr;
DefinedFunc* current_func = nullptr;
- TypeCheckerErrorHandler tc_error_handler;
TypeChecker typechecker;
std::vector<Label> label_stack;
IstreamOffsetVectorVector func_fixups;
@@ -307,9 +305,8 @@ BinaryReaderInterpreter::BinaryReaderInterpreter(
module(module),
istream_writer(std::move(istream)),
istream_offset(istream_writer.output_buffer().size()) {
- tc_error_handler.on_error = OnTypecheckerError;
- tc_error_handler.user_data = this;
- typechecker.error_handler = &tc_error_handler;
+ typechecker.set_error_callback(
+ [this](const char* msg) { PrintError("%s", msg); });
}
std::unique_ptr<OutputBuffer> BinaryReaderInterpreter::ReleaseOutputBuffer() {
@@ -335,12 +332,6 @@ void WABT_PRINTF_FORMAT(2, 3)
HandleError(kInvalidOffset, buffer);
}
-// static
-void BinaryReaderInterpreter::OnTypecheckerError(const char* msg,
- void* user_data) {
- static_cast<BinaryReaderInterpreter*>(user_data)->PrintError("%s", msg);
-}
-
Index BinaryReaderInterpreter::TranslateSigIndexToEnv(Index sig_index) {
assert(sig_index < sig_index_mapping.size());
return sig_index_mapping[sig_index];
@@ -467,15 +458,15 @@ wabt::Result BinaryReaderInterpreter::GetBrDropKeepCount(
Index depth,
Index* out_drop_count,
Index* out_keep_count) {
- TypeCheckerLabel* label;
- CHECK_RESULT(typechecker_get_label(&typechecker, depth, &label));
+ TypeChecker::Label* label;
+ CHECK_RESULT(typechecker.GetLabel(depth, &label));
*out_keep_count =
label->label_type != LabelType::Loop ? label->sig.size() : 0;
- if (typechecker_is_unreachable(&typechecker)) {
+ if (typechecker.IsUnreachable()) {
*out_drop_count = 0;
} else {
*out_drop_count =
- (typechecker.type_stack.size() - label->type_stack_limit) -
+ (typechecker.type_stack_size() - label->type_stack_limit) -
*out_keep_count;
}
return wabt::Result::Ok;
@@ -1077,7 +1068,7 @@ wabt::Result BinaryReaderInterpreter::BeginFunctionBody(Index index) {
for (Type param_type : sig->param_types)
func->param_and_local_types.push_back(param_type);
- CHECK_RESULT(typechecker_begin_function(&typechecker, &sig->result_types));
+ CHECK_RESULT(typechecker.BeginFunction(&sig->result_types));
/* push implicit func label (equivalent to return) */
PushLabel(kInvalidIstreamOffset, kInvalidIstreamOffset);
@@ -1088,7 +1079,7 @@ wabt::Result BinaryReaderInterpreter::EndFunctionBody(Index index) {
FixupTopLabel();
Index drop_count, keep_count;
CHECK_RESULT(GetReturnDropKeepCount(&drop_count, &keep_count));
- CHECK_RESULT(typechecker_end_function(&typechecker));
+ CHECK_RESULT(typechecker.EndFunction());
CHECK_RESULT(EmitDropKeep(drop_count, keep_count));
CHECK_RESULT(EmitOpcode(interpreter::Opcode::Return));
PopLabel();
@@ -1137,13 +1128,13 @@ wabt::Result BinaryReaderInterpreter::CheckAlign(uint32_t alignment_log2,
}
wabt::Result BinaryReaderInterpreter::OnUnaryExpr(wabt::Opcode opcode) {
- CHECK_RESULT(typechecker_on_unary(&typechecker, opcode));
+ CHECK_RESULT(typechecker.OnUnary(opcode));
CHECK_RESULT(EmitOpcode(opcode));
return wabt::Result::Ok;
}
wabt::Result BinaryReaderInterpreter::OnBinaryExpr(wabt::Opcode opcode) {
- CHECK_RESULT(typechecker_on_binary(&typechecker, opcode));
+ CHECK_RESULT(typechecker.OnBinary(opcode));
CHECK_RESULT(EmitOpcode(opcode));
return wabt::Result::Ok;
}
@@ -1151,7 +1142,7 @@ wabt::Result BinaryReaderInterpreter::OnBinaryExpr(wabt::Opcode opcode) {
wabt::Result BinaryReaderInterpreter::OnBlockExpr(Index num_types,
Type* sig_types) {
TypeVector sig(sig_types, sig_types + num_types);
- CHECK_RESULT(typechecker_on_block(&typechecker, &sig));
+ CHECK_RESULT(typechecker.OnBlock(&sig));
PushLabel(kInvalidIstreamOffset, kInvalidIstreamOffset);
return wabt::Result::Ok;
}
@@ -1159,7 +1150,7 @@ wabt::Result BinaryReaderInterpreter::OnBlockExpr(Index num_types,
wabt::Result BinaryReaderInterpreter::OnLoopExpr(Index num_types,
Type* sig_types) {
TypeVector sig(sig_types, sig_types + num_types);
- CHECK_RESULT(typechecker_on_loop(&typechecker, &sig));
+ CHECK_RESULT(typechecker.OnLoop(&sig));
PushLabel(GetIstreamOffset(), kInvalidIstreamOffset);
return wabt::Result::Ok;
}
@@ -1167,7 +1158,7 @@ wabt::Result BinaryReaderInterpreter::OnLoopExpr(Index num_types,
wabt::Result BinaryReaderInterpreter::OnIfExpr(Index num_types,
Type* sig_types) {
TypeVector sig(sig_types, sig_types + num_types);
- CHECK_RESULT(typechecker_on_if(&typechecker, &sig));
+ CHECK_RESULT(typechecker.OnIf(&sig));
CHECK_RESULT(EmitOpcode(interpreter::Opcode::BrUnless));
IstreamOffset fixup_offset = GetIstreamOffset();
CHECK_RESULT(EmitI32(kInvalidIstreamOffset));
@@ -1176,7 +1167,7 @@ wabt::Result BinaryReaderInterpreter::OnIfExpr(Index num_types,
}
wabt::Result BinaryReaderInterpreter::OnElseExpr() {
- CHECK_RESULT(typechecker_on_else(&typechecker));
+ CHECK_RESULT(typechecker.OnElse());
Label* label = TopLabel();
IstreamOffset fixup_cond_offset = label->fixup_offset;
CHECK_RESULT(EmitOpcode(interpreter::Opcode::Br));
@@ -1187,10 +1178,10 @@ wabt::Result BinaryReaderInterpreter::OnElseExpr() {
}
wabt::Result BinaryReaderInterpreter::OnEndExpr() {
- TypeCheckerLabel* label;
- CHECK_RESULT(typechecker_get_label(&typechecker, 0, &label));
+ TypeChecker::Label* label;
+ CHECK_RESULT(typechecker.GetLabel(0, &label));
LabelType label_type = label->label_type;
- CHECK_RESULT(typechecker_on_end(&typechecker));
+ CHECK_RESULT(typechecker.OnEnd());
if (label_type == LabelType::If || label_type == LabelType::Else) {
CHECK_RESULT(EmitI32At(TopLabel()->fixup_offset, GetIstreamOffset()));
}
@@ -1202,14 +1193,14 @@ wabt::Result BinaryReaderInterpreter::OnEndExpr() {
wabt::Result BinaryReaderInterpreter::OnBrExpr(Index depth) {
Index drop_count, keep_count;
CHECK_RESULT(GetBrDropKeepCount(depth, &drop_count, &keep_count));
- CHECK_RESULT(typechecker_on_br(&typechecker, depth));
+ CHECK_RESULT(typechecker.OnBr(depth));
CHECK_RESULT(EmitBr(depth, drop_count, keep_count));
return wabt::Result::Ok;
}
wabt::Result BinaryReaderInterpreter::OnBrIfExpr(Index depth) {
Index drop_count, keep_count;
- CHECK_RESULT(typechecker_on_br_if(&typechecker, depth));
+ CHECK_RESULT(typechecker.OnBrIf(depth));
CHECK_RESULT(GetBrDropKeepCount(depth, &drop_count, &keep_count));
/* flip the br_if so if <cond> is true it can drop values from the stack */
CHECK_RESULT(EmitOpcode(interpreter::Opcode::BrUnless));
@@ -1224,7 +1215,7 @@ wabt::Result BinaryReaderInterpreter::OnBrTableExpr(
Index num_targets,
Index* target_depths,
Index default_target_depth) {
- CHECK_RESULT(typechecker_begin_br_table(&typechecker));
+ CHECK_RESULT(typechecker.BeginBrTable());
CHECK_RESULT(EmitOpcode(interpreter::Opcode::BrTable));
CHECK_RESULT(EmitI32(num_targets));
IstreamOffset fixup_table_offset = GetIstreamOffset();
@@ -1237,11 +1228,11 @@ wabt::Result BinaryReaderInterpreter::OnBrTableExpr(
for (Index i = 0; i <= num_targets; ++i) {
Index depth = i != num_targets ? target_depths[i] : default_target_depth;
- CHECK_RESULT(typechecker_on_br_table_target(&typechecker, depth));
+ CHECK_RESULT(typechecker.OnBrTableTarget(depth));
CHECK_RESULT(EmitBrTableOffset(depth));
}
- CHECK_RESULT(typechecker_end_br_table(&typechecker));
+ CHECK_RESULT(typechecker.EndBrTable());
return wabt::Result::Ok;
}
@@ -1249,7 +1240,7 @@ wabt::Result BinaryReaderInterpreter::OnCallExpr(Index func_index) {
Func* func = GetFuncByModuleIndex(func_index);
FuncSignature* sig = env->GetFuncSignature(func->sig_index);
CHECK_RESULT(
- typechecker_on_call(&typechecker, &sig->param_types, &sig->result_types));
+ typechecker.OnCall(&sig->param_types, &sig->result_types));
if (func->is_host) {
CHECK_RESULT(EmitOpcode(interpreter::Opcode::CallHost));
@@ -1268,7 +1259,7 @@ wabt::Result BinaryReaderInterpreter::OnCallIndirectExpr(Index sig_index) {
return wabt::Result::Error;
}
FuncSignature* sig = GetSignatureByModuleIndex(sig_index);
- CHECK_RESULT(typechecker_on_call_indirect(&typechecker, &sig->param_types,
+ CHECK_RESULT(typechecker.OnCallIndirect(&sig->param_types,
&sig->result_types));
CHECK_RESULT(EmitOpcode(interpreter::Opcode::CallIndirect));
@@ -1286,34 +1277,34 @@ wabt::Result BinaryReaderInterpreter::OnConvertExpr(wabt::Opcode opcode) {
}
wabt::Result BinaryReaderInterpreter::OnDropExpr() {
- CHECK_RESULT(typechecker_on_drop(&typechecker));
+ CHECK_RESULT(typechecker.OnDrop());
CHECK_RESULT(EmitOpcode(interpreter::Opcode::Drop));
return wabt::Result::Ok;
}
wabt::Result BinaryReaderInterpreter::OnI32ConstExpr(uint32_t value) {
- CHECK_RESULT(typechecker_on_const(&typechecker, Type::I32));
+ CHECK_RESULT(typechecker.OnConst(Type::I32));
CHECK_RESULT(EmitOpcode(interpreter::Opcode::I32Const));
CHECK_RESULT(EmitI32(value));
return wabt::Result::Ok;
}
wabt::Result BinaryReaderInterpreter::OnI64ConstExpr(uint64_t value) {
- CHECK_RESULT(typechecker_on_const(&typechecker, Type::I64));
+ CHECK_RESULT(typechecker.OnConst(Type::I64));
CHECK_RESULT(EmitOpcode(interpreter::Opcode::I64Const));
CHECK_RESULT(EmitI64(value));
return wabt::Result::Ok;
}
wabt::Result BinaryReaderInterpreter::OnF32ConstExpr(uint32_t value_bits) {
- CHECK_RESULT(typechecker_on_const(&typechecker, Type::F32));
+ CHECK_RESULT(typechecker.OnConst(Type::F32));
CHECK_RESULT(EmitOpcode(interpreter::Opcode::F32Const));
CHECK_RESULT(EmitI32(value_bits));
return wabt::Result::Ok;
}
wabt::Result BinaryReaderInterpreter::OnF64ConstExpr(uint64_t value_bits) {
- CHECK_RESULT(typechecker_on_const(&typechecker, Type::F64));
+ CHECK_RESULT(typechecker.OnConst(Type::F64));
CHECK_RESULT(EmitOpcode(interpreter::Opcode::F64Const));
CHECK_RESULT(EmitI64(value_bits));
return wabt::Result::Ok;
@@ -1322,7 +1313,7 @@ wabt::Result BinaryReaderInterpreter::OnF64ConstExpr(uint64_t value_bits) {
wabt::Result BinaryReaderInterpreter::OnGetGlobalExpr(Index global_index) {
CHECK_RESULT(CheckGlobal(global_index));
Type type = GetGlobalTypeByModuleIndex(global_index);
- CHECK_RESULT(typechecker_on_get_global(&typechecker, type));
+ CHECK_RESULT(typechecker.OnGetGlobal(type));
CHECK_RESULT(EmitOpcode(interpreter::Opcode::GetGlobal));
CHECK_RESULT(EmitI32(TranslateGlobalIndexToEnv(global_index)));
return wabt::Result::Ok;
@@ -1337,25 +1328,25 @@ wabt::Result BinaryReaderInterpreter::OnSetGlobalExpr(Index global_index) {
return wabt::Result::Error;
}
CHECK_RESULT(
- typechecker_on_set_global(&typechecker, global->typed_value.type));
+ typechecker.OnSetGlobal(global->typed_value.type));
CHECK_RESULT(EmitOpcode(interpreter::Opcode::SetGlobal));
CHECK_RESULT(EmitI32(TranslateGlobalIndexToEnv(global_index)));
return wabt::Result::Ok;
}
Index BinaryReaderInterpreter::TranslateLocalIndex(Index local_index) {
- return typechecker.type_stack.size() +
+ return typechecker.type_stack_size() +
current_func->param_and_local_types.size() - local_index;
}
wabt::Result BinaryReaderInterpreter::OnGetLocalExpr(Index local_index) {
CHECK_RESULT(CheckLocal(local_index));
Type type = GetLocalTypeByIndex(current_func, local_index);
- /* Get the translated index before calling typechecker_on_get_local
- * because it will update the type stack size. We need the index to be
- * relative to the old stack size. */
+ // Get the translated index before calling typechecker.OnGetLocal because it
+ // will update the type stack size. We need the index to be relative to the
+ // old stack size.
Index translated_local_index = TranslateLocalIndex(local_index);
- CHECK_RESULT(typechecker_on_get_local(&typechecker, type));
+ CHECK_RESULT(typechecker.OnGetLocal(type));
CHECK_RESULT(EmitOpcode(interpreter::Opcode::GetLocal));
CHECK_RESULT(EmitI32(translated_local_index));
return wabt::Result::Ok;
@@ -1364,7 +1355,7 @@ wabt::Result BinaryReaderInterpreter::OnGetLocalExpr(Index local_index) {
wabt::Result BinaryReaderInterpreter::OnSetLocalExpr(Index local_index) {
CHECK_RESULT(CheckLocal(local_index));
Type type = GetLocalTypeByIndex(current_func, local_index);
- CHECK_RESULT(typechecker_on_set_local(&typechecker, type));
+ CHECK_RESULT(typechecker.OnSetLocal(type));
CHECK_RESULT(EmitOpcode(interpreter::Opcode::SetLocal));
CHECK_RESULT(EmitI32(TranslateLocalIndex(local_index)));
return wabt::Result::Ok;
@@ -1373,7 +1364,7 @@ wabt::Result BinaryReaderInterpreter::OnSetLocalExpr(Index local_index) {
wabt::Result BinaryReaderInterpreter::OnTeeLocalExpr(Index local_index) {
CHECK_RESULT(CheckLocal(local_index));
Type type = GetLocalTypeByIndex(current_func, local_index);
- CHECK_RESULT(typechecker_on_tee_local(&typechecker, type));
+ CHECK_RESULT(typechecker.OnTeeLocal(type));
CHECK_RESULT(EmitOpcode(interpreter::Opcode::TeeLocal));
CHECK_RESULT(EmitI32(TranslateLocalIndex(local_index)));
return wabt::Result::Ok;
@@ -1381,7 +1372,7 @@ wabt::Result BinaryReaderInterpreter::OnTeeLocalExpr(Index local_index) {
wabt::Result BinaryReaderInterpreter::OnGrowMemoryExpr() {
CHECK_RESULT(CheckHasMemory(wabt::Opcode::GrowMemory));
- CHECK_RESULT(typechecker_on_grow_memory(&typechecker));
+ CHECK_RESULT(typechecker.OnGrowMemory());
CHECK_RESULT(EmitOpcode(interpreter::Opcode::GrowMemory));
CHECK_RESULT(EmitI32(module->memory_index));
return wabt::Result::Ok;
@@ -1392,7 +1383,7 @@ wabt::Result BinaryReaderInterpreter::OnLoadExpr(wabt::Opcode opcode,
Address offset) {
CHECK_RESULT(CheckHasMemory(opcode));
CHECK_RESULT(CheckAlign(alignment_log2, get_opcode_memory_size(opcode)));
- CHECK_RESULT(typechecker_on_load(&typechecker, opcode));
+ CHECK_RESULT(typechecker.OnLoad(opcode));
CHECK_RESULT(EmitOpcode(opcode));
CHECK_RESULT(EmitI32(module->memory_index));
CHECK_RESULT(EmitI32(offset));
@@ -1404,7 +1395,7 @@ wabt::Result BinaryReaderInterpreter::OnStoreExpr(wabt::Opcode opcode,
Address offset) {
CHECK_RESULT(CheckHasMemory(opcode));
CHECK_RESULT(CheckAlign(alignment_log2, get_opcode_memory_size(opcode)));
- CHECK_RESULT(typechecker_on_store(&typechecker, opcode));
+ CHECK_RESULT(typechecker.OnStore(opcode));
CHECK_RESULT(EmitOpcode(opcode));
CHECK_RESULT(EmitI32(module->memory_index));
CHECK_RESULT(EmitI32(offset));
@@ -1413,7 +1404,7 @@ wabt::Result BinaryReaderInterpreter::OnStoreExpr(wabt::Opcode opcode,
wabt::Result BinaryReaderInterpreter::OnCurrentMemoryExpr() {
CHECK_RESULT(CheckHasMemory(wabt::Opcode::CurrentMemory));
- CHECK_RESULT(typechecker_on_current_memory(&typechecker));
+ CHECK_RESULT(typechecker.OnCurrentMemory());
CHECK_RESULT(EmitOpcode(interpreter::Opcode::CurrentMemory));
CHECK_RESULT(EmitI32(module->memory_index));
return wabt::Result::Ok;
@@ -1426,20 +1417,20 @@ wabt::Result BinaryReaderInterpreter::OnNopExpr() {
wabt::Result BinaryReaderInterpreter::OnReturnExpr() {
Index drop_count, keep_count;
CHECK_RESULT(GetReturnDropKeepCount(&drop_count, &keep_count));
- CHECK_RESULT(typechecker_on_return(&typechecker));
+ CHECK_RESULT(typechecker.OnReturn());
CHECK_RESULT(EmitDropKeep(drop_count, keep_count));
CHECK_RESULT(EmitOpcode(interpreter::Opcode::Return));
return wabt::Result::Ok;
}
wabt::Result BinaryReaderInterpreter::OnSelectExpr() {
- CHECK_RESULT(typechecker_on_select(&typechecker));
+ CHECK_RESULT(typechecker.OnSelect());
CHECK_RESULT(EmitOpcode(interpreter::Opcode::Select));
return wabt::Result::Ok;
}
wabt::Result BinaryReaderInterpreter::OnUnreachableExpr() {
- CHECK_RESULT(typechecker_on_unreachable(&typechecker));
+ CHECK_RESULT(typechecker.OnUnreachable());
CHECK_RESULT(EmitOpcode(interpreter::Opcode::Unreachable));
return wabt::Result::Ok;
}
diff --git a/src/type-checker.cc b/src/type-checker.cc
index d7af7e59..eba23c75 100644
--- a/src/type-checker.cc
+++ b/src/type-checker.cc
@@ -16,10 +16,10 @@
#include "type-checker.h"
-#define CHECK_RESULT(expr) \
- do { \
- if (WABT_FAILED(expr)) \
- return Result::Error; \
+#define CHECK_RESULT(expr) \
+ do { \
+ if (WABT_FAILED(expr)) \
+ return Result::Error; \
} while (0)
#define COMBINE_RESULT(result_var, result) \
@@ -30,300 +30,284 @@
namespace wabt {
-TypeCheckerLabel::TypeCheckerLabel(LabelType label_type,
- const TypeVector& sig,
- size_t limit)
+TypeChecker::Label::Label(LabelType label_type,
+ const TypeVector& sig,
+ size_t limit)
: label_type(label_type),
sig(sig),
type_stack_limit(limit),
unreachable(false) {}
-static void WABT_PRINTF_FORMAT(2, 3)
- print_error(TypeChecker* tc, const char* fmt, ...) {
- if (tc->error_handler->on_error) {
+TypeChecker::TypeChecker(const ErrorCallback& error_callback)
+ : error_callback_(error_callback) {}
+
+void TypeChecker::PrintError(const char* fmt, ...) {
+ if (error_callback_) {
WABT_SNPRINTF_ALLOCA(buffer, length, fmt);
- tc->error_handler->on_error(buffer, tc->error_handler->user_data);
+ error_callback_(buffer);
}
}
-Result typechecker_get_label(TypeChecker* tc,
- Index depth,
- TypeCheckerLabel** out_label) {
- if (depth >= tc->label_stack.size()) {
- assert(tc->label_stack.size() > 0);
- print_error(tc, "invalid depth: %" PRIindex " (max %" PRIzd ")", depth,
- tc->label_stack.size() - 1);
+Result TypeChecker::GetLabel(Index depth, Label** out_label) {
+ if (depth >= label_stack_.size()) {
+ assert(label_stack_.size() > 0);
+ PrintError("invalid depth: %" PRIindex " (max %" PRIzd ")", depth,
+ label_stack_.size() - 1);
*out_label = nullptr;
return Result::Error;
}
- *out_label = &tc->label_stack[tc->label_stack.size() - depth - 1];
+ *out_label = &label_stack_[label_stack_.size() - depth - 1];
return Result::Ok;
}
-static Result top_label(TypeChecker* tc, TypeCheckerLabel** out_label) {
- return typechecker_get_label(tc, 0, out_label);
+Result TypeChecker::TopLabel(Label** out_label) {
+ return GetLabel(0, out_label);
}
-bool typechecker_is_unreachable(TypeChecker* tc) {
- TypeCheckerLabel* label;
- if (WABT_FAILED(top_label(tc, &label)))
+bool TypeChecker::IsUnreachable() {
+ Label* label;
+ if (WABT_FAILED(TopLabel(&label)))
return true;
return label->unreachable;
}
-static void reset_type_stack_to_label(TypeChecker* tc,
- TypeCheckerLabel* label) {
- tc->type_stack.resize(label->type_stack_limit);
+void TypeChecker::ResetTypeStackToLabel(Label* label) {
+ type_stack_.resize(label->type_stack_limit);
}
-static Result set_unreachable(TypeChecker* tc) {
- TypeCheckerLabel* label;
- CHECK_RESULT(top_label(tc, &label));
+Result TypeChecker::SetUnreachable() {
+ Label* label;
+ CHECK_RESULT(TopLabel(&label));
label->unreachable = true;
- reset_type_stack_to_label(tc, label);
+ ResetTypeStackToLabel(label);
return Result::Ok;
}
-static void push_label(TypeChecker* tc,
- LabelType label_type,
- const TypeVector& sig) {
- tc->label_stack.emplace_back(label_type, sig, tc->type_stack.size());
+void TypeChecker::PushLabel(LabelType label_type, const TypeVector& sig) {
+ label_stack_.emplace_back(label_type, sig, type_stack_.size());
}
-static Result pop_label(TypeChecker* tc) {
- tc->label_stack.pop_back();
+Result TypeChecker::PopLabel() {
+ label_stack_.pop_back();
return Result::Ok;
}
-static Result check_label_type(TypeCheckerLabel* label, LabelType label_type) {
+Result TypeChecker::CheckLabelType(Label* label, LabelType label_type) {
return label->label_type == label_type ? Result::Ok : Result::Error;
}
-static Result peek_type(TypeChecker* tc, Index depth, Type* out_type) {
- TypeCheckerLabel* label;
- CHECK_RESULT(top_label(tc, &label));
+Result TypeChecker::PeekType(Index depth, Type* out_type) {
+ Label* label;
+ CHECK_RESULT(TopLabel(&label));
- if (label->type_stack_limit + depth >= tc->type_stack.size()) {
+ if (label->type_stack_limit + depth >= type_stack_.size()) {
*out_type = Type::Any;
return label->unreachable ? Result::Ok : Result::Error;
}
- *out_type = tc->type_stack[tc->type_stack.size() - depth - 1];
+ *out_type = type_stack_[type_stack_.size() - depth - 1];
return Result::Ok;
}
-static Result top_type(TypeChecker* tc, Type* out_type) {
- return peek_type(tc, 0, out_type);
+Result TypeChecker::TopType(Type* out_type) {
+ return PeekType(0, out_type);
}
-static Result pop_type(TypeChecker* tc, Type* out_type) {
- TypeCheckerLabel* label;
- CHECK_RESULT(top_label(tc, &label));
- Result result = top_type(tc, out_type);
- if (tc->type_stack.size() > label->type_stack_limit)
- tc->type_stack.pop_back();
+Result TypeChecker::PopType(Type* out_type) {
+ Label* label;
+ CHECK_RESULT(TopLabel(&label));
+ Result result = TopType(out_type);
+ if (type_stack_.size() > label->type_stack_limit)
+ type_stack_.pop_back();
return result;
}
-static Result drop_types(TypeChecker* tc, size_t drop_count) {
- TypeCheckerLabel* label;
- CHECK_RESULT(top_label(tc, &label));
- if (label->type_stack_limit + drop_count > tc->type_stack.size()) {
+Result TypeChecker::DropTypes(size_t drop_count) {
+ Label* label;
+ CHECK_RESULT(TopLabel(&label));
+ if (label->type_stack_limit + drop_count > type_stack_.size()) {
if (label->unreachable) {
- reset_type_stack_to_label(tc, label);
+ ResetTypeStackToLabel(label);
return Result::Ok;
}
return Result::Error;
}
- tc->type_stack.erase(tc->type_stack.end() - drop_count, tc->type_stack.end());
+ type_stack_.erase(type_stack_.end() - drop_count, type_stack_.end());
return Result::Ok;
}
-static void push_type(TypeChecker* tc, Type type) {
+void TypeChecker::PushType(Type type) {
if (type != Type::Void)
- tc->type_stack.push_back(type);
+ type_stack_.push_back(type);
}
-static void push_types(TypeChecker* tc, const TypeVector& types) {
- for (Type type: types)
- push_type(tc, type);
+void TypeChecker::PushTypes(const TypeVector& types) {
+ for (Type type : types)
+ PushType(type);
}
-static Result check_type_stack_limit(TypeChecker* tc,
- size_t expected,
- const char* desc) {
- TypeCheckerLabel* label;
- CHECK_RESULT(top_label(tc, &label));
- size_t avail = tc->type_stack.size() - label->type_stack_limit;
+Result TypeChecker::CheckTypeStackLimit(size_t expected, const char* desc) {
+ Label* label;
+ CHECK_RESULT(TopLabel(&label));
+ size_t avail = type_stack_.size() - label->type_stack_limit;
if (!label->unreachable && expected > avail) {
- print_error(tc, "type stack size too small at %s. got %" PRIzd
- ", expected at least %" PRIzd,
- desc, avail, expected);
+ PrintError("type stack size too small at %s. got %" PRIzd
+ ", expected at least %" PRIzd,
+ desc, avail, expected);
return Result::Error;
}
return Result::Ok;
}
-static Result check_type_stack_end(TypeChecker* tc, const char* desc) {
- TypeCheckerLabel* label;
- CHECK_RESULT(top_label(tc, &label));
- if (tc->type_stack.size() != label->type_stack_limit) {
- print_error(tc, "type stack at end of %s is %" PRIzd ", expected %" PRIzd,
- desc, tc->type_stack.size(), label->type_stack_limit);
+Result TypeChecker::CheckTypeStackEnd(const char* desc) {
+ Label* label;
+ CHECK_RESULT(TopLabel(&label));
+ if (type_stack_.size() != label->type_stack_limit) {
+ PrintError("type stack at end of %s is %" PRIzd ", expected %" PRIzd, desc,
+ type_stack_.size(), label->type_stack_limit);
return Result::Error;
}
return Result::Ok;
}
-static Result check_type(TypeChecker* tc,
- Type actual,
- Type expected,
- const char* desc) {
+Result TypeChecker::CheckType(Type actual, Type expected, const char* desc) {
if (expected != actual && expected != Type::Any && actual != Type::Any) {
- print_error(tc, "type mismatch in %s, expected %s but got %s.", desc,
- get_type_name(expected), get_type_name(actual));
+ PrintError("type mismatch in %s, expected %s but got %s.", desc,
+ get_type_name(expected), get_type_name(actual));
return Result::Error;
}
return Result::Ok;
}
-static Result check_signature(TypeChecker* tc,
- const TypeVector& sig,
- const char* desc) {
+Result TypeChecker::CheckSignature(const TypeVector& sig, const char* desc) {
Result result = Result::Ok;
- COMBINE_RESULT(result, check_type_stack_limit(tc, sig.size(), desc));
+ COMBINE_RESULT(result, CheckTypeStackLimit(sig.size(), desc));
for (size_t i = 0; i < sig.size(); ++i) {
Type actual = Type::Any;
- COMBINE_RESULT(result, peek_type(tc, sig.size() - i - 1, &actual));
- COMBINE_RESULT(result, check_type(tc, actual, sig[i], desc));
+ COMBINE_RESULT(result, PeekType(sig.size() - i - 1, &actual));
+ COMBINE_RESULT(result, CheckType(actual, sig[i], desc));
}
return result;
}
-static Result pop_and_check_signature(TypeChecker* tc,
- const TypeVector& sig,
- const char* desc) {
+Result TypeChecker::PopAndCheckSignature(const TypeVector& sig,
+ const char* desc) {
Result result = Result::Ok;
- COMBINE_RESULT(result, check_signature(tc, sig, desc));
- COMBINE_RESULT(result, drop_types(tc, sig.size()));
+ COMBINE_RESULT(result, CheckSignature(sig, desc));
+ COMBINE_RESULT(result, DropTypes(sig.size()));
return result;
}
-static Result pop_and_check_call(TypeChecker* tc,
- const TypeVector& param_types,
- const TypeVector& result_types,
- const char* desc) {
+Result TypeChecker::PopAndCheckCall(const TypeVector& param_types,
+ const TypeVector& result_types,
+ const char* desc) {
Result result = Result::Ok;
- COMBINE_RESULT(result, check_type_stack_limit(tc, param_types.size(), desc));
+ COMBINE_RESULT(result, CheckTypeStackLimit(param_types.size(), desc));
for (size_t i = 0; i < param_types.size(); ++i) {
Type actual = Type::Any;
- COMBINE_RESULT(result, peek_type(tc, param_types.size() - i - 1, &actual));
- COMBINE_RESULT(result, check_type(tc, actual, param_types[i], desc));
+ COMBINE_RESULT(result, PeekType(param_types.size() - i - 1, &actual));
+ COMBINE_RESULT(result, CheckType(actual, param_types[i], desc));
}
- COMBINE_RESULT(result, drop_types(tc, param_types.size()));
- push_types(tc, result_types);
+ COMBINE_RESULT(result, DropTypes(param_types.size()));
+ PushTypes(result_types);
return result;
}
-static Result pop_and_check_1_type(TypeChecker* tc,
- Type expected,
- const char* desc) {
+Result TypeChecker::PopAndCheck1Type(Type expected, const char* desc) {
Result result = Result::Ok;
Type actual = Type::Any;
- COMBINE_RESULT(result, check_type_stack_limit(tc, 1, desc));
- COMBINE_RESULT(result, pop_type(tc, &actual));
- COMBINE_RESULT(result, check_type(tc, actual, expected, desc));
+ COMBINE_RESULT(result, CheckTypeStackLimit(1, desc));
+ COMBINE_RESULT(result, PopType(&actual));
+ COMBINE_RESULT(result, CheckType(actual, expected, desc));
return result;
}
-static Result pop_and_check_2_types(TypeChecker* tc,
- Type expected1,
- Type expected2,
- const char* desc) {
+Result TypeChecker::PopAndCheck2Types(Type expected1,
+ Type expected2,
+ const char* desc) {
Result result = Result::Ok;
Type actual1 = Type::Any;
Type actual2 = Type::Any;
- COMBINE_RESULT(result, check_type_stack_limit(tc, 2, desc));
- COMBINE_RESULT(result, pop_type(tc, &actual2));
- COMBINE_RESULT(result, pop_type(tc, &actual1));
- COMBINE_RESULT(result, check_type(tc, actual1, expected1, desc));
- COMBINE_RESULT(result, check_type(tc, actual2, expected2, desc));
+ COMBINE_RESULT(result, CheckTypeStackLimit(2, desc));
+ COMBINE_RESULT(result, PopType(&actual2));
+ COMBINE_RESULT(result, PopType(&actual1));
+ COMBINE_RESULT(result, CheckType(actual1, expected1, desc));
+ COMBINE_RESULT(result, CheckType(actual2, expected2, desc));
return result;
}
-static Result pop_and_check_2_types_are_equal(TypeChecker* tc,
- Type* out_type,
+Result TypeChecker::PopAndCheck2TypesAreEqual(Type* out_type,
const char* desc) {
Result result = Result::Ok;
Type right = Type::Any;
Type left = Type::Any;
- COMBINE_RESULT(result, check_type_stack_limit(tc, 2, desc));
- COMBINE_RESULT(result, pop_type(tc, &right));
- COMBINE_RESULT(result, pop_type(tc, &left));
- COMBINE_RESULT(result, check_type(tc, left, right, desc));
+ COMBINE_RESULT(result, CheckTypeStackLimit(2, desc));
+ COMBINE_RESULT(result, PopType(&right));
+ COMBINE_RESULT(result, PopType(&left));
+ COMBINE_RESULT(result, CheckType(left, right, desc));
*out_type = right;
return result;
}
-static Result check_opcode1(TypeChecker* tc, Opcode opcode) {
- Result result = pop_and_check_1_type(tc, get_opcode_param_type_1(opcode),
- get_opcode_name(opcode));
- push_type(tc, get_opcode_result_type(opcode));
+Result TypeChecker::CheckOpcode1(Opcode opcode) {
+ Result result = PopAndCheck1Type(get_opcode_param_type_1(opcode),
+ get_opcode_name(opcode));
+ PushType(get_opcode_result_type(opcode));
return result;
}
-static Result check_opcode2(TypeChecker* tc, Opcode opcode) {
- Result result = pop_and_check_2_types(tc, get_opcode_param_type_1(opcode),
- get_opcode_param_type_2(opcode),
- get_opcode_name(opcode));
- push_type(tc, get_opcode_result_type(opcode));
+Result TypeChecker::CheckOpcode2(Opcode opcode) {
+ Result result = PopAndCheck2Types(get_opcode_param_type_1(opcode),
+ get_opcode_param_type_2(opcode),
+ get_opcode_name(opcode));
+ PushType(get_opcode_result_type(opcode));
return result;
}
-Result typechecker_begin_function(TypeChecker* tc, const TypeVector* sig) {
- tc->type_stack.clear();
- tc->label_stack.clear();
- push_label(tc, LabelType::Func, *sig);
+Result TypeChecker::BeginFunction(const TypeVector* sig) {
+ type_stack_.clear();
+ label_stack_.clear();
+ PushLabel(LabelType::Func, *sig);
return Result::Ok;
}
-Result typechecker_on_binary(TypeChecker* tc, Opcode opcode) {
- return check_opcode2(tc, opcode);
+Result TypeChecker::OnBinary(Opcode opcode) {
+ return CheckOpcode2(opcode);
}
-Result typechecker_on_block(TypeChecker* tc, const TypeVector* sig) {
- push_label(tc, LabelType::Block, *sig);
+Result TypeChecker::OnBlock(const TypeVector* sig) {
+ PushLabel(LabelType::Block, *sig);
return Result::Ok;
}
-Result typechecker_on_br(TypeChecker* tc, Index depth) {
+Result TypeChecker::OnBr(Index depth) {
Result result = Result::Ok;
- TypeCheckerLabel* label;
- CHECK_RESULT(typechecker_get_label(tc, depth, &label));
+ Label* label;
+ CHECK_RESULT(GetLabel(depth, &label));
if (label->label_type != LabelType::Loop)
- COMBINE_RESULT(result, check_signature(tc, label->sig, "br"));
- CHECK_RESULT(set_unreachable(tc));
+ COMBINE_RESULT(result, CheckSignature(label->sig, "br"));
+ CHECK_RESULT(SetUnreachable());
return result;
}
-Result typechecker_on_br_if(TypeChecker* tc, Index depth) {
+Result TypeChecker::OnBrIf(Index depth) {
Result result = Result::Ok;
- COMBINE_RESULT(result, pop_and_check_1_type(tc, Type::I32, "br_if"));
- TypeCheckerLabel* label;
- CHECK_RESULT(typechecker_get_label(tc, depth, &label));
+ COMBINE_RESULT(result, PopAndCheck1Type(Type::I32, "br_if"));
+ Label* label;
+ CHECK_RESULT(GetLabel(depth, &label));
if (label->label_type != LabelType::Loop)
- COMBINE_RESULT(result, check_signature(tc, label->sig, "br_if"));
+ COMBINE_RESULT(result, CheckSignature(label->sig, "br_if"));
return result;
}
-Result typechecker_begin_br_table(TypeChecker* tc) {
- tc->br_table_sig = Type::Any;
- return pop_and_check_1_type(tc, Type::I32, "br_table");
+Result TypeChecker::BeginBrTable() {
+ br_table_sig_ = Type::Any;
+ return PopAndCheck1Type(Type::I32, "br_table");
}
-Result typechecker_on_br_table_target(TypeChecker* tc, Index depth) {
+Result TypeChecker::OnBrTableTarget(Index depth) {
Result result = Result::Ok;
- TypeCheckerLabel* label;
- CHECK_RESULT(typechecker_get_label(tc, depth, &label));
+ Label* label;
+ CHECK_RESULT(GetLabel(depth, &label));
Type label_sig;
if (label->label_type == LabelType::Loop) {
label_sig = Type::Void;
@@ -332,191 +316,184 @@ Result typechecker_on_br_table_target(TypeChecker* tc, Index depth) {
label_sig = label->sig.size() == 0 ? Type::Void : label->sig[0];
}
- COMBINE_RESULT(result,
- check_type(tc, tc->br_table_sig, label_sig, "br_table"));
- tc->br_table_sig = label_sig;
+ COMBINE_RESULT(result, CheckType(br_table_sig_, label_sig, "br_table"));
+ br_table_sig_ = label_sig;
if (label->label_type != LabelType::Loop)
- COMBINE_RESULT(result, check_signature(tc, label->sig, "br_table"));
+ COMBINE_RESULT(result, CheckSignature(label->sig, "br_table"));
return result;
}
-Result typechecker_end_br_table(TypeChecker* tc) {
- return set_unreachable(tc);
+Result TypeChecker::EndBrTable() {
+ return SetUnreachable();
}
-Result typechecker_on_call(TypeChecker* tc,
- const TypeVector* param_types,
+Result TypeChecker::OnCall(const TypeVector* param_types,
const TypeVector* result_types) {
- return pop_and_check_call(tc, *param_types, *result_types, "call");
+ return PopAndCheckCall(*param_types, *result_types, "call");
}
-Result typechecker_on_call_indirect(TypeChecker* tc,
- const TypeVector* param_types,
- const TypeVector* result_types) {
+Result TypeChecker::OnCallIndirect(const TypeVector* param_types,
+ const TypeVector* result_types) {
Result result = Result::Ok;
- COMBINE_RESULT(result, pop_and_check_1_type(tc, Type::I32, "call_indirect"));
- COMBINE_RESULT(result, pop_and_check_call(tc, *param_types, *result_types,
- "call_indirect"));
+ COMBINE_RESULT(result, PopAndCheck1Type(Type::I32, "call_indirect"));
+ COMBINE_RESULT(result,
+ PopAndCheckCall(*param_types, *result_types, "call_indirect"));
return result;
}
-Result typechecker_on_compare(TypeChecker* tc, Opcode opcode) {
- return check_opcode2(tc, opcode);
+Result TypeChecker::OnCompare(Opcode opcode) {
+ return CheckOpcode2(opcode);
}
-Result typechecker_on_const(TypeChecker* tc, Type type) {
- push_type(tc, type);
+Result TypeChecker::OnConst(Type type) {
+ PushType(type);
return Result::Ok;
}
-Result typechecker_on_convert(TypeChecker* tc, Opcode opcode) {
- return check_opcode1(tc, opcode);
+Result TypeChecker::OnConvert(Opcode opcode) {
+ return CheckOpcode1(opcode);
}
-Result typechecker_on_current_memory(TypeChecker* tc) {
- push_type(tc, Type::I32);
+Result TypeChecker::OnCurrentMemory() {
+ PushType(Type::I32);
return Result::Ok;
}
-Result typechecker_on_drop(TypeChecker* tc) {
+Result TypeChecker::OnDrop() {
Result result = Result::Ok;
Type type = Type::Any;
- COMBINE_RESULT(result, check_type_stack_limit(tc, 1, "drop"));
- COMBINE_RESULT(result, pop_type(tc, &type));
+ COMBINE_RESULT(result, CheckTypeStackLimit(1, "drop"));
+ COMBINE_RESULT(result, PopType(&type));
return result;
}
-Result typechecker_on_else(TypeChecker* tc) {
+Result TypeChecker::OnElse() {
Result result = Result::Ok;
- TypeCheckerLabel* label;
- CHECK_RESULT(top_label(tc, &label));
- COMBINE_RESULT(result, check_label_type(label, LabelType::If));
- COMBINE_RESULT(result,
- pop_and_check_signature(tc, label->sig, "if true branch"));
- COMBINE_RESULT(result, check_type_stack_end(tc, "if true branch"));
- reset_type_stack_to_label(tc, label);
+ Label* label;
+ CHECK_RESULT(TopLabel(&label));
+ COMBINE_RESULT(result, CheckLabelType(label, LabelType::If));
+ COMBINE_RESULT(result, PopAndCheckSignature(label->sig, "if true branch"));
+ COMBINE_RESULT(result, CheckTypeStackEnd("if true branch"));
+ ResetTypeStackToLabel(label);
label->label_type = LabelType::Else;
label->unreachable = false;
return result;
}
-static Result on_end(TypeChecker* tc,
- TypeCheckerLabel* label,
- const char* sig_desc,
- const char* end_desc) {
+Result TypeChecker::OnEnd(Label* label,
+ const char* sig_desc,
+ const char* end_desc) {
Result result = Result::Ok;
- COMBINE_RESULT(result, pop_and_check_signature(tc, label->sig, sig_desc));
- COMBINE_RESULT(result, check_type_stack_end(tc, end_desc));
- reset_type_stack_to_label(tc, label);
- push_types(tc, label->sig);
- pop_label(tc);
+ COMBINE_RESULT(result, PopAndCheckSignature(label->sig, sig_desc));
+ COMBINE_RESULT(result, CheckTypeStackEnd(end_desc));
+ ResetTypeStackToLabel(label);
+ PushTypes(label->sig);
+ PopLabel();
return result;
}
-Result typechecker_on_end(TypeChecker* tc) {
+Result TypeChecker::OnEnd() {
Result result = Result::Ok;
static const char* s_label_type_name[] = {"function", "block", "loop", "if",
"if false branch"};
WABT_STATIC_ASSERT(WABT_ARRAY_SIZE(s_label_type_name) == kLabelTypeCount);
- TypeCheckerLabel* label;
- CHECK_RESULT(top_label(tc, &label));
+ Label* label;
+ CHECK_RESULT(TopLabel(&label));
assert(static_cast<int>(label->label_type) < kLabelTypeCount);
if (label->label_type == LabelType::If) {
if (label->sig.size() != 0) {
- print_error(tc, "if without else cannot have type signature.");
+ PrintError("if without else cannot have type signature.");
result = Result::Error;
}
}
const char* desc = s_label_type_name[static_cast<int>(label->label_type)];
- COMBINE_RESULT(result, on_end(tc, label, desc, desc));
+ COMBINE_RESULT(result, OnEnd(label, desc, desc));
return result;
}
-Result typechecker_on_grow_memory(TypeChecker* tc) {
- return check_opcode1(tc, Opcode::GrowMemory);
+Result TypeChecker::OnGrowMemory() {
+ return CheckOpcode1(Opcode::GrowMemory);
}
-Result typechecker_on_if(TypeChecker* tc, const TypeVector* sig) {
- Result result = pop_and_check_1_type(tc, Type::I32, "if");
- push_label(tc, LabelType::If, *sig);
+Result TypeChecker::OnIf(const TypeVector* sig) {
+ Result result = PopAndCheck1Type(Type::I32, "if");
+ PushLabel(LabelType::If, *sig);
return result;
}
-Result typechecker_on_get_global(TypeChecker* tc, Type type) {
- push_type(tc, type);
+Result TypeChecker::OnGetGlobal(Type type) {
+ PushType(type);
return Result::Ok;
}
-Result typechecker_on_get_local(TypeChecker* tc, Type type) {
- push_type(tc, type);
+Result TypeChecker::OnGetLocal(Type type) {
+ PushType(type);
return Result::Ok;
}
-Result typechecker_on_load(TypeChecker* tc, Opcode opcode) {
- return check_opcode1(tc, opcode);
+Result TypeChecker::OnLoad(Opcode opcode) {
+ return CheckOpcode1(opcode);
}
-Result typechecker_on_loop(TypeChecker* tc, const TypeVector* sig) {
- push_label(tc, LabelType::Loop, *sig);
+Result TypeChecker::OnLoop(const TypeVector* sig) {
+ PushLabel(LabelType::Loop, *sig);
return Result::Ok;
}
-Result typechecker_on_return(TypeChecker* tc) {
+Result TypeChecker::OnReturn() {
Result result = Result::Ok;
- TypeCheckerLabel* func_label;
- CHECK_RESULT(
- typechecker_get_label(tc, tc->label_stack.size() - 1, &func_label));
- COMBINE_RESULT(result,
- pop_and_check_signature(tc, func_label->sig, "return"));
- CHECK_RESULT(set_unreachable(tc));
+ Label* func_label;
+ CHECK_RESULT(GetLabel(label_stack_.size() - 1, &func_label));
+ COMBINE_RESULT(result, PopAndCheckSignature(func_label->sig, "return"));
+ CHECK_RESULT(SetUnreachable());
return result;
}
-Result typechecker_on_select(TypeChecker* tc) {
+Result TypeChecker::OnSelect() {
Result result = Result::Ok;
- COMBINE_RESULT(result, pop_and_check_1_type(tc, Type::I32, "select"));
+ COMBINE_RESULT(result, PopAndCheck1Type(Type::I32, "select"));
Type type = Type::Any;
- COMBINE_RESULT(result, pop_and_check_2_types_are_equal(tc, &type, "select"));
- push_type(tc, type);
+ COMBINE_RESULT(result, PopAndCheck2TypesAreEqual(&type, "select"));
+ PushType(type);
return result;
}
-Result typechecker_on_set_global(TypeChecker* tc, Type type) {
- return pop_and_check_1_type(tc, type, "set_global");
+Result TypeChecker::OnSetGlobal(Type type) {
+ return PopAndCheck1Type(type, "set_global");
}
-Result typechecker_on_set_local(TypeChecker* tc, Type type) {
- return pop_and_check_1_type(tc, type, "set_local");
+Result TypeChecker::OnSetLocal(Type type) {
+ return PopAndCheck1Type(type, "set_local");
}
-Result typechecker_on_store(TypeChecker* tc, Opcode opcode) {
- return check_opcode2(tc, opcode);
+Result TypeChecker::OnStore(Opcode opcode) {
+ return CheckOpcode2(opcode);
}
-Result typechecker_on_tee_local(TypeChecker* tc, Type type) {
+Result TypeChecker::OnTeeLocal(Type type) {
Result result = Result::Ok;
Type value = Type::Any;
- COMBINE_RESULT(result, check_type_stack_limit(tc, 1, "tee_local"));
- COMBINE_RESULT(result, top_type(tc, &value));
- COMBINE_RESULT(result, check_type(tc, value, type, "tee_local"));
+ COMBINE_RESULT(result, CheckTypeStackLimit(1, "tee_local"));
+ COMBINE_RESULT(result, TopType(&value));
+ COMBINE_RESULT(result, CheckType(value, type, "tee_local"));
return result;
}
-Result typechecker_on_unary(TypeChecker* tc, Opcode opcode) {
- return check_opcode1(tc, opcode);
+Result TypeChecker::OnUnary(Opcode opcode) {
+ return CheckOpcode1(opcode);
}
-Result typechecker_on_unreachable(TypeChecker* tc) {
- return set_unreachable(tc);
+Result TypeChecker::OnUnreachable() {
+ return SetUnreachable();
}
-Result typechecker_end_function(TypeChecker* tc) {
+Result TypeChecker::EndFunction() {
Result result = Result::Ok;
- TypeCheckerLabel* label;
- CHECK_RESULT(top_label(tc, &label));
- COMBINE_RESULT(result, check_label_type(label, LabelType::Func));
- COMBINE_RESULT(result, on_end(tc, label, "implicit return", "function"));
+ Label* label;
+ CHECK_RESULT(TopLabel(&label));
+ COMBINE_RESULT(result, CheckLabelType(label, LabelType::Func));
+ COMBINE_RESULT(result, OnEnd(label, "implicit return", "function"));
return result;
}
diff --git a/src/type-checker.h b/src/type-checker.h
index 483293da..f7238365 100644
--- a/src/type-checker.h
+++ b/src/type-checker.h
@@ -17,6 +17,7 @@
#ifndef WABT_TYPE_CHECKER_H_
#define WABT_TYPE_CHECKER_H_
+#include <functional>
#include <vector>
#include "common.h"
@@ -24,72 +25,101 @@
namespace wabt {
-typedef void (*TypeCheckerErrorCallback)(const char* msg, void* user_data);
+class TypeChecker {
+ public:
+ typedef std::function<void(const char* msg)> ErrorCallback;
-struct TypeCheckerErrorHandler {
- TypeCheckerErrorCallback on_error;
- void* user_data;
-};
+ struct Label {
+ Label(LabelType, const TypeVector& sig, size_t limit);
-struct TypeCheckerLabel {
- TypeCheckerLabel(LabelType, const TypeVector& sig, size_t limit);
+ LabelType label_type;
+ TypeVector sig;
+ size_t type_stack_limit;
+ bool unreachable;
+ };
- LabelType label_type;
- TypeVector sig;
- size_t type_stack_limit;
- bool unreachable;
-};
+ TypeChecker() = default;
+ explicit TypeChecker(const ErrorCallback&);
-struct TypeChecker {
- TypeCheckerErrorHandler* error_handler = nullptr;
- TypeVector type_stack;
- std::vector<TypeCheckerLabel> label_stack;
- /* TODO(binji): will need to be complete signature when signatures with
- * multiple types are allowed. */
- Type br_table_sig;
-};
+ void set_error_callback(const ErrorCallback& error_callback) {
+ error_callback_ = error_callback;
+ }
+
+ size_t type_stack_size() const { return type_stack_.size(); }
-bool typechecker_is_unreachable(TypeChecker* tc);
-Result typechecker_get_label(TypeChecker* tc,
- Index depth,
- TypeCheckerLabel** out_label);
-
-Result typechecker_begin_function(TypeChecker*, const TypeVector* sig);
-Result typechecker_on_binary(TypeChecker*, Opcode);
-Result typechecker_on_block(TypeChecker*, const TypeVector* sig);
-Result typechecker_on_br(TypeChecker*, Index depth);
-Result typechecker_on_br_if(TypeChecker*, Index depth);
-Result typechecker_begin_br_table(TypeChecker*);
-Result typechecker_on_br_table_target(TypeChecker*, Index depth);
-Result typechecker_end_br_table(TypeChecker*);
-Result typechecker_on_call(TypeChecker*,
- const TypeVector* param_types,
- const TypeVector* result_types);
-Result typechecker_on_call_indirect(TypeChecker*,
- const TypeVector* param_types,
- const TypeVector* result_types);
-Result typechecker_on_compare(TypeChecker*, Opcode);
-Result typechecker_on_const(TypeChecker*, Type);
-Result typechecker_on_convert(TypeChecker*, Opcode);
-Result typechecker_on_current_memory(TypeChecker*);
-Result typechecker_on_drop(TypeChecker*);
-Result typechecker_on_else(TypeChecker*);
-Result typechecker_on_end(TypeChecker*);
-Result typechecker_on_get_global(TypeChecker*, Type);
-Result typechecker_on_get_local(TypeChecker*, Type);
-Result typechecker_on_grow_memory(TypeChecker*);
-Result typechecker_on_if(TypeChecker*, const TypeVector* sig);
-Result typechecker_on_load(TypeChecker*, Opcode);
-Result typechecker_on_loop(TypeChecker*, const TypeVector* sig);
-Result typechecker_on_return(TypeChecker*);
-Result typechecker_on_select(TypeChecker*);
-Result typechecker_on_set_global(TypeChecker*, Type);
-Result typechecker_on_set_local(TypeChecker*, Type);
-Result typechecker_on_store(TypeChecker*, Opcode);
-Result typechecker_on_tee_local(TypeChecker*, Type);
-Result typechecker_on_unary(TypeChecker*, Opcode);
-Result typechecker_on_unreachable(TypeChecker*);
-Result typechecker_end_function(TypeChecker*);
+ bool IsUnreachable();
+ Result GetLabel(Index depth, Label** out_label);
+
+ Result BeginFunction(const TypeVector* sig);
+ Result OnBinary(Opcode);
+ Result OnBlock(const TypeVector* sig);
+ Result OnBr(Index depth);
+ Result OnBrIf(Index depth);
+ Result BeginBrTable();
+ Result OnBrTableTarget(Index depth);
+ Result EndBrTable();
+ Result OnCall(const TypeVector* param_types, const TypeVector* result_types);
+ Result OnCallIndirect(const TypeVector* param_types,
+ const TypeVector* result_types);
+ Result OnCompare(Opcode);
+ Result OnConst(Type);
+ Result OnConvert(Opcode);
+ Result OnCurrentMemory();
+ Result OnDrop();
+ Result OnElse();
+ Result OnEnd();
+ Result OnGetGlobal(Type);
+ Result OnGetLocal(Type);
+ Result OnGrowMemory();
+ Result OnIf(const TypeVector* sig);
+ Result OnLoad(Opcode);
+ Result OnLoop(const TypeVector* sig);
+ Result OnReturn();
+ Result OnSelect();
+ Result OnSetGlobal(Type);
+ Result OnSetLocal(Type);
+ Result OnStore(Opcode);
+ Result OnTeeLocal(Type);
+ Result OnUnary(Opcode);
+ Result OnUnreachable();
+ Result EndFunction();
+
+ private:
+ void WABT_PRINTF_FORMAT(2, 3) PrintError(const char* fmt, ...);
+ Result TopLabel(Label** out_label);
+ void ResetTypeStackToLabel(Label* label);
+ Result SetUnreachable();
+ void PushLabel(LabelType label_type, const TypeVector& sig);
+ Result PopLabel();
+ Result CheckLabelType(Label* label, LabelType label_type);
+ Result PeekType(Index depth, Type* out_type);
+ Result TopType(Type* out_type);
+ Result PopType(Type* out_type);
+ Result DropTypes(size_t drop_count);
+ void PushType(Type type);
+ void PushTypes(const TypeVector& types);
+ Result CheckTypeStackLimit(size_t expected, const char* desc);
+ Result CheckTypeStackEnd(const char* desc);
+ Result CheckType(Type actual, Type expected, const char* desc);
+ Result CheckSignature(const TypeVector& sig, const char* desc);
+ Result PopAndCheckSignature(const TypeVector& sig, const char* desc);
+ Result PopAndCheckCall(const TypeVector& param_types,
+ const TypeVector& result_types,
+ const char* desc);
+ Result PopAndCheck1Type(Type expected, const char* desc);
+ Result PopAndCheck2Types(Type expected1, Type expected2, const char* desc);
+ Result PopAndCheck2TypesAreEqual(Type* out_type, const char* desc);
+ Result CheckOpcode1(Opcode opcode);
+ Result CheckOpcode2(Opcode opcode);
+ Result OnEnd(Label* label, const char* sig_desc, const char* end_desc);
+
+ ErrorCallback error_callback_;
+ TypeVector type_stack_;
+ std::vector<Label> label_stack_;
+ // TODO(binji): This will need to be complete signature when signatures with
+ // multiple types are allowed.
+ Type br_table_sig_ = Type::Void;
+};
} // namespace wabt
diff --git a/src/validator.cc b/src/validator.cc
index c69490a5..d9179ba5 100644
--- a/src/validator.cc
+++ b/src/validator.cc
@@ -48,6 +48,8 @@ struct Context {
WABT_DISALLOW_COPY_AND_ASSIGN(Context);
Context(SourceErrorHandler*, WastLexer*, const Script*);
+ void OnTypecheckerError(const char* msg);
+
SourceErrorHandler* error_handler = nullptr;
WastLexer* lexer = nullptr;
const Script* script = nullptr;
@@ -58,7 +60,7 @@ struct Context {
Index current_global_index = 0;
Index num_imported_globals = 0;
TypeChecker typechecker;
- /* Cached for access by on_typechecker_error */
+ // Cached for access by OnTypecheckerError.
const Location* expr_loc = nullptr;
Result result = Result::Ok;
};
@@ -66,7 +68,10 @@ struct Context {
Context::Context(SourceErrorHandler* error_handler,
WastLexer* lexer,
const Script* script)
- : error_handler(error_handler), lexer(lexer), script(script) {}
+ : error_handler(error_handler), lexer(lexer), script(script) {
+ typechecker.set_error_callback(
+ [this](const char* msg) { OnTypecheckerError(msg); });
+}
} // namespace
@@ -79,9 +84,8 @@ static void WABT_PRINTF_FORMAT(3, 4)
va_end(args);
}
-static void on_typechecker_error(const char* msg, void* user_data) {
- Context* ctx = static_cast<Context*>(user_data);
- print_error(ctx, ctx->expr_loc, "%s", msg);
+void Context::OnTypecheckerError(const char* msg) {
+ print_error(this, expr_loc, "%s", msg);
}
static bool is_power_of_two(uint32_t x) {
@@ -348,39 +352,38 @@ static void check_expr(Context* ctx, const Expr* expr) {
switch (expr->type) {
case ExprType::Binary:
- typechecker_on_binary(&ctx->typechecker, expr->binary.opcode);
+ ctx->typechecker.OnBinary(expr->binary.opcode);
break;
case ExprType::Block:
- typechecker_on_block(&ctx->typechecker, &expr->block->sig);
+ ctx->typechecker.OnBlock(&expr->block->sig);
check_expr_list(ctx, &expr->loc, expr->block->first);
- typechecker_on_end(&ctx->typechecker);
+ ctx->typechecker.OnEnd();
break;
case ExprType::Br:
- typechecker_on_br(&ctx->typechecker, expr->br.var.index);
+ ctx->typechecker.OnBr(expr->br.var.index);
break;
case ExprType::BrIf:
- typechecker_on_br_if(&ctx->typechecker, expr->br_if.var.index);
+ ctx->typechecker.OnBrIf(expr->br_if.var.index);
break;
case ExprType::BrTable: {
- typechecker_begin_br_table(&ctx->typechecker);
+ ctx->typechecker.BeginBrTable();
for (Var& var: *expr->br_table.targets) {
- typechecker_on_br_table_target(&ctx->typechecker, var.index);
+ ctx->typechecker.OnBrTableTarget(var.index);
}
- typechecker_on_br_table_target(&ctx->typechecker,
- expr->br_table.default_target.index);
- typechecker_end_br_table(&ctx->typechecker);
+ ctx->typechecker.OnBrTableTarget(expr->br_table.default_target.index);
+ ctx->typechecker.EndBrTable();
break;
}
case ExprType::Call: {
const Func* callee;
if (WABT_SUCCEEDED(check_func_var(ctx, &expr->call.var, &callee))) {
- typechecker_on_call(&ctx->typechecker, &callee->decl.sig.param_types,
- &callee->decl.sig.result_types);
+ ctx->typechecker.OnCall(&callee->decl.sig.param_types,
+ &callee->decl.sig.result_types);
}
break;
}
@@ -393,54 +396,51 @@ static void check_expr(Context* ctx, const Expr* expr) {
}
if (WABT_SUCCEEDED(
check_func_type_var(ctx, &expr->call_indirect.var, &func_type))) {
- typechecker_on_call_indirect(&ctx->typechecker,
- &func_type->sig.param_types,
- &func_type->sig.result_types);
+ ctx->typechecker.OnCallIndirect(&func_type->sig.param_types,
+ &func_type->sig.result_types);
}
break;
}
case ExprType::Compare:
- typechecker_on_compare(&ctx->typechecker, expr->compare.opcode);
+ ctx->typechecker.OnCompare(expr->compare.opcode);
break;
case ExprType::Const:
- typechecker_on_const(&ctx->typechecker, expr->const_.type);
+ ctx->typechecker.OnConst(expr->const_.type);
break;
case ExprType::Convert:
- typechecker_on_convert(&ctx->typechecker, expr->convert.opcode);
+ ctx->typechecker.OnConvert(expr->convert.opcode);
break;
case ExprType::Drop:
- typechecker_on_drop(&ctx->typechecker);
+ ctx->typechecker.OnDrop();
break;
case ExprType::GetGlobal:
- typechecker_on_get_global(
- &ctx->typechecker,
+ ctx->typechecker.OnGetGlobal(
get_global_var_type_or_any(ctx, &expr->get_global.var));
break;
case ExprType::GetLocal:
- typechecker_on_get_local(
- &ctx->typechecker,
+ ctx->typechecker.OnGetLocal(
get_local_var_type_or_any(ctx, &expr->get_local.var));
break;
case ExprType::GrowMemory:
check_has_memory(ctx, &expr->loc, Opcode::GrowMemory);
- typechecker_on_grow_memory(&ctx->typechecker);
+ ctx->typechecker.OnGrowMemory();
break;
case ExprType::If:
- typechecker_on_if(&ctx->typechecker, &expr->if_.true_->sig);
+ ctx->typechecker.OnIf(&expr->if_.true_->sig);
check_expr_list(ctx, &expr->loc, expr->if_.true_->first);
if (expr->if_.false_) {
- typechecker_on_else(&ctx->typechecker);
+ ctx->typechecker.OnElse();
check_expr_list(ctx, &expr->loc, expr->if_.false_);
}
- typechecker_on_end(&ctx->typechecker);
+ ctx->typechecker.OnEnd();
break;
case ExprType::Load:
@@ -448,40 +448,38 @@ static void check_expr(Context* ctx, const Expr* expr) {
check_align(ctx, &expr->loc, expr->load.align,
get_opcode_natural_alignment(expr->load.opcode));
check_offset(ctx, &expr->loc, expr->load.offset);
- typechecker_on_load(&ctx->typechecker, expr->load.opcode);
+ ctx->typechecker.OnLoad(expr->load.opcode);
break;
case ExprType::Loop:
- typechecker_on_loop(&ctx->typechecker, &expr->loop->sig);
+ ctx->typechecker.OnLoop(&expr->loop->sig);
check_expr_list(ctx, &expr->loc, expr->loop->first);
- typechecker_on_end(&ctx->typechecker);
+ ctx->typechecker.OnEnd();
break;
case ExprType::CurrentMemory:
check_has_memory(ctx, &expr->loc, Opcode::CurrentMemory);
- typechecker_on_current_memory(&ctx->typechecker);
+ ctx->typechecker.OnCurrentMemory();
break;
case ExprType::Nop:
break;
case ExprType::Return:
- typechecker_on_return(&ctx->typechecker);
+ ctx->typechecker.OnReturn();
break;
case ExprType::Select:
- typechecker_on_select(&ctx->typechecker);
+ ctx->typechecker.OnSelect();
break;
case ExprType::SetGlobal:
- typechecker_on_set_global(
- &ctx->typechecker,
+ ctx->typechecker.OnSetGlobal(
get_global_var_type_or_any(ctx, &expr->set_global.var));
break;
case ExprType::SetLocal:
- typechecker_on_set_local(
- &ctx->typechecker,
+ ctx->typechecker.OnSetLocal(
get_local_var_type_or_any(ctx, &expr->set_local.var));
break;
@@ -490,21 +488,20 @@ static void check_expr(Context* ctx, const Expr* expr) {
check_align(ctx, &expr->loc, expr->store.align,
get_opcode_natural_alignment(expr->store.opcode));
check_offset(ctx, &expr->loc, expr->store.offset);
- typechecker_on_store(&ctx->typechecker, expr->store.opcode);
+ ctx->typechecker.OnStore(expr->store.opcode);
break;
case ExprType::TeeLocal:
- typechecker_on_tee_local(
- &ctx->typechecker,
+ ctx->typechecker.OnTeeLocal(
get_local_var_type_or_any(ctx, &expr->tee_local.var));
break;
case ExprType::Unary:
- typechecker_on_unary(&ctx->typechecker, expr->unary.opcode);
+ ctx->typechecker.OnUnary(expr->unary.opcode);
break;
case ExprType::Unreachable:
- typechecker_on_unreachable(&ctx->typechecker);
+ ctx->typechecker.OnUnreachable();
break;
}
}
@@ -536,9 +533,9 @@ static void check_func(Context* ctx, const Location* loc, const Func* func) {
}
ctx->expr_loc = loc;
- typechecker_begin_function(&ctx->typechecker, &func->decl.sig.result_types);
+ ctx->typechecker.BeginFunction(&func->decl.sig.result_types);
check_expr_list(ctx, loc, func->first_expr);
- typechecker_end_function(&ctx->typechecker);
+ ctx->typechecker.EndFunction();
ctx->current_func = nullptr;
}
@@ -1007,11 +1004,6 @@ Result validate_script(WastLexer* lexer,
SourceErrorHandler* error_handler) {
Context ctx(error_handler, lexer, script);
- TypeCheckerErrorHandler tc_error_handler;
- tc_error_handler.on_error = on_typechecker_error;
- tc_error_handler.user_data = &ctx;
- ctx.typechecker.error_handler = &tc_error_handler;
-
for (const std::unique_ptr<Command>& command : script->commands)
check_command(&ctx, command.get());
return ctx.result;