summaryrefslogtreecommitdiffstats
path: root/third_party/wasm2c/include/wabt/type-checker.h
blob: 2b0ec092fe5daf4999cd6323ebcb68c64df17cc0 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
/*
 * Copyright 2017 WebAssembly Community Group participants
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef WABT_TYPE_CHECKER_H_
#define WABT_TYPE_CHECKER_H_

#include <functional>
#include <vector>

#include "wabt/common.h"
#include "wabt/feature.h"
#include "wabt/opcode.h"

namespace wabt {

class TypeChecker {
 public:
  using ErrorCallback = std::function<void(const char* msg)>;

  struct Label {
    Label(LabelType,
          const TypeVector& param_types,
          const TypeVector& result_types,
          size_t limit);

    TypeVector& br_types() {
      return label_type == LabelType::Loop ? param_types : result_types;
    }

    LabelType label_type;
    TypeVector param_types;
    TypeVector result_types;
    size_t type_stack_limit;
    bool unreachable;
  };

  explicit TypeChecker(const Features& features) : features_(features) {}

  void set_error_callback(const ErrorCallback& error_callback) {
    error_callback_ = error_callback;
  }

  size_t type_stack_size() const { return type_stack_.size(); }

  bool IsUnreachable();
  Result GetLabel(Index depth, Label** out_label);
  Result GetRethrowLabel(Index depth, Label** out_label);
  Result GetCatchCount(Index depth, Index* out_depth);

  Result BeginFunction(const TypeVector& sig);
  Result OnAtomicFence(uint32_t consistency_model);
  Result OnAtomicLoad(Opcode, const Limits& limits);
  Result OnAtomicNotify(Opcode, const Limits& limits);
  Result OnAtomicStore(Opcode, const Limits& limits);
  Result OnAtomicRmw(Opcode, const Limits& limits);
  Result OnAtomicRmwCmpxchg(Opcode, const Limits& limits);
  Result OnAtomicWait(Opcode, const Limits& limits);
  Result OnBinary(Opcode);
  Result OnBlock(const TypeVector& param_types, const TypeVector& result_types);
  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 OnIndexedFuncRef(Index* out_index);
  Result OnReturnCall(const TypeVector& param_types,
                      const TypeVector& result_types);
  Result OnReturnCallIndirect(const TypeVector& param_types,
                              const TypeVector& result_types);
  Result OnCatch(const TypeVector& sig);
  Result OnCompare(Opcode);
  Result OnConst(Type);
  Result OnConvert(Opcode);
  Result OnDelegate(Index depth);
  Result OnDrop();
  Result OnElse();
  Result OnEnd();
  Result OnGlobalGet(Type);
  Result OnGlobalSet(Type);
  Result OnIf(const TypeVector& param_types, const TypeVector& result_types);
  Result OnLoad(Opcode, const Limits& limits);
  Result OnLocalGet(Type);
  Result OnLocalSet(Type);
  Result OnLocalTee(Type);
  Result OnLoop(const TypeVector& param_types, const TypeVector& result_types);
  Result OnMemoryCopy(const Limits& srclimits, const Limits& dstlimits);
  Result OnDataDrop(Index);
  Result OnMemoryFill(const Limits& limits);
  Result OnMemoryGrow(const Limits& limits);
  Result OnMemoryInit(Index, const Limits& limits);
  Result OnMemorySize(const Limits& limits);
  Result OnTableCopy();
  Result OnElemDrop(Index);
  Result OnTableInit(Index, Index);
  Result OnTableGet(Type elem_type);
  Result OnTableSet(Type elem_type);
  Result OnTableGrow(Type elem_type);
  Result OnTableSize();
  Result OnTableFill(Type elem_type);
  Result OnRefFuncExpr(Index func_type);
  Result OnRefNullExpr(Type type);
  Result OnRefIsNullExpr();
  Result OnRethrow(Index depth);
  Result OnReturn();
  Result OnSelect(const TypeVector& result_types);
  Result OnSimdLaneOp(Opcode, uint64_t);
  Result OnSimdLoadLane(Opcode, const Limits& limits, uint64_t);
  Result OnSimdStoreLane(Opcode, const Limits& limits, uint64_t);
  Result OnSimdShuffleOp(Opcode, v128);
  Result OnStore(Opcode, const Limits& limits);
  Result OnTernary(Opcode);
  Result OnThrow(const TypeVector& sig);
  Result OnTry(const TypeVector& param_types, const TypeVector& result_types);
  Result OnUnary(Opcode);
  Result OnUnreachable();
  Result EndFunction();

  Result BeginInitExpr(Type type);
  Result EndInitExpr();

  static Result CheckType(Type actual, Type expected);

 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& param_types,
                 const TypeVector& result_types);
  Result PopLabel();
  Result CheckLabelType(Label* label, LabelType label_type);
  Result Check2LabelTypes(Label* label,
                          LabelType label_type1,
                          LabelType label_type2);
  Result GetThisFunctionLabel(Label** label);
  Result PeekType(Index depth, Type* out_type);
  Result PeekAndCheckType(Index depth, Type expected);
  Result DropTypes(size_t drop_count);
  void PushType(Type type);
  void PushTypes(const TypeVector& types);
  Result CheckTypeStackEnd(const char* desc);
  Result CheckTypes(const TypeVector& actual, const TypeVector& expected);
  Result CheckSignature(const TypeVector& sig, const char* desc);
  Result CheckReturnSignature(const TypeVector& sig,
                              const TypeVector& expected,
                              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 PopAndCheck3Types(Type expected1,
                           Type expected2,
                           Type expected3,
                           const char* desc);
  Result CheckOpcode1(Opcode opcode, const Limits* limits = nullptr);
  Result CheckOpcode2(Opcode opcode, const Limits* limits = nullptr);
  Result CheckOpcode3(Opcode opcode,
                      const Limits* limits1 = nullptr,
                      const Limits* limits2 = nullptr,
                      const Limits* limits3 = nullptr);
  Result OnEnd(Label* label, const char* sig_desc, const char* end_desc);

  template <typename... Args>
  void PrintStackIfFailed(Result result, const char* desc, Args... args) {
    // Minor optimization, check result before constructing the vector to pass
    // to the other overload of PrintStackIfFailed.
    if (Failed(result)) {
      PrintStackIfFailedV(result, desc, {args...}, /*is_end=*/false);
    }
  }

  void PrintStackIfFailedV(Result,
                           const char* desc,
                           const TypeVector&,
                           bool is_end);

  ErrorCallback error_callback_;
  TypeVector type_stack_;
  std::vector<Label> label_stack_;
  // Cache the expected br_table signature. It will be initialized to `nullptr`
  // to represent "any".
  TypeVector* br_table_sig_ = nullptr;
  Features features_;
};

}  // namespace wabt

#endif /* WABT_TYPE_CHECKER_H_ */