Line data Source code
1 : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2 : * vim: set ts=8 sts=4 et sw=4 tw=99:
3 : *
4 : * Copyright 2015 Mozilla Foundation
5 : *
6 : * Licensed under the Apache License, Version 2.0 (the "License");
7 : * you may not use this file except in compliance with the License.
8 : * You may obtain a copy of the License at
9 : *
10 : * http://www.apache.org/licenses/LICENSE-2.0
11 : *
12 : * Unless required by applicable law or agreed to in writing, software
13 : * distributed under the License is distributed on an "AS IS" BASIS,
14 : * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 : * See the License for the specific language governing permissions and
16 : * limitations under the License.
17 : */
18 :
19 : #ifndef wasmast_h
20 : #define wasmast_h
21 :
22 : #include "ds/LifoAlloc.h"
23 : #include "js/HashTable.h"
24 : #include "js/Vector.h"
25 : #include "wasm/WasmTypes.h"
26 :
27 : namespace js {
28 : namespace wasm {
29 :
30 : const uint32_t AstNoIndex = UINT32_MAX;
31 : const unsigned AST_LIFO_DEFAULT_CHUNK_SIZE = 4096;
32 :
33 : /*****************************************************************************/
34 : // wasm AST
35 :
36 : class AstExpr;
37 :
38 : template <class T>
39 : using AstVector = mozilla::Vector<T, 0, LifoAllocPolicy<Fallible>>;
40 :
41 : template <class K, class V, class HP>
42 : using AstHashMap = HashMap<K, V, HP, LifoAllocPolicy<Fallible>>;
43 :
44 : class AstName
45 : {
46 : const char16_t* begin_;
47 : const char16_t* end_;
48 : public:
49 : template <size_t Length>
50 0 : explicit AstName(const char16_t (&str)[Length]) : begin_(str), end_(str + Length - 1) {
51 0 : MOZ_ASSERT(str[Length - 1] == u'\0');
52 0 : }
53 :
54 0 : AstName(const char16_t* begin, size_t length) : begin_(begin), end_(begin + length) {}
55 0 : AstName() : begin_(nullptr), end_(nullptr) {}
56 0 : const char16_t* begin() const { return begin_; }
57 0 : const char16_t* end() const { return end_; }
58 0 : size_t length() const { return end_ - begin_; }
59 0 : bool empty() const { return begin_ == nullptr; }
60 :
61 0 : bool operator==(AstName rhs) const {
62 0 : if (length() != rhs.length())
63 0 : return false;
64 0 : if (begin() == rhs.begin())
65 0 : return true;
66 0 : return EqualChars(begin(), rhs.begin(), length());
67 : }
68 0 : bool operator!=(AstName rhs) const {
69 0 : return !(*this == rhs);
70 : }
71 : };
72 :
73 : class AstRef
74 : {
75 : AstName name_;
76 : uint32_t index_;
77 :
78 : public:
79 0 : AstRef() : index_(AstNoIndex) {
80 0 : MOZ_ASSERT(isInvalid());
81 0 : }
82 0 : explicit AstRef(AstName name) : name_(name), index_(AstNoIndex) {
83 0 : MOZ_ASSERT(!isInvalid());
84 0 : }
85 0 : explicit AstRef(uint32_t index) : index_(index) {
86 0 : MOZ_ASSERT(!isInvalid());
87 0 : }
88 0 : bool isInvalid() const {
89 0 : return name_.empty() && index_ == AstNoIndex;
90 : }
91 0 : AstName name() const {
92 0 : return name_;
93 : }
94 0 : size_t index() const {
95 0 : MOZ_ASSERT(index_ != AstNoIndex);
96 0 : return index_;
97 : }
98 0 : void setIndex(uint32_t index) {
99 0 : MOZ_ASSERT(index_ == AstNoIndex);
100 0 : index_ = index;
101 0 : }
102 : };
103 :
104 : struct AstNameHasher
105 : {
106 : typedef const AstName Lookup;
107 0 : static js::HashNumber hash(Lookup l) {
108 0 : return mozilla::HashString(l.begin(), l.length());
109 : }
110 0 : static bool match(const AstName key, Lookup lookup) {
111 0 : return key == lookup;
112 : }
113 : };
114 :
115 : using AstNameMap = AstHashMap<AstName, uint32_t, AstNameHasher>;
116 :
117 : typedef AstVector<ValType> AstValTypeVector;
118 : typedef AstVector<AstExpr*> AstExprVector;
119 : typedef AstVector<AstName> AstNameVector;
120 : typedef AstVector<AstRef> AstRefVector;
121 :
122 0 : struct AstBase
123 : {
124 0 : void* operator new(size_t numBytes, LifoAlloc& astLifo) throw() {
125 0 : return astLifo.alloc(numBytes);
126 : }
127 : };
128 :
129 0 : class AstSig : public AstBase
130 : {
131 : AstName name_;
132 : AstValTypeVector args_;
133 : ExprType ret_;
134 :
135 : public:
136 0 : explicit AstSig(LifoAlloc& lifo)
137 0 : : args_(lifo),
138 0 : ret_(ExprType::Void)
139 0 : {}
140 0 : AstSig(AstValTypeVector&& args, ExprType ret)
141 0 : : args_(Move(args)),
142 0 : ret_(ret)
143 0 : {}
144 0 : AstSig(AstName name, AstSig&& rhs)
145 0 : : name_(name),
146 0 : args_(Move(rhs.args_)),
147 0 : ret_(rhs.ret_)
148 0 : {}
149 0 : const AstValTypeVector& args() const {
150 0 : return args_;
151 : }
152 0 : ExprType ret() const {
153 0 : return ret_;
154 : }
155 0 : AstName name() const {
156 0 : return name_;
157 : }
158 0 : bool operator==(const AstSig& rhs) const {
159 0 : return ret() == rhs.ret() && EqualContainers(args(), rhs.args());
160 : }
161 :
162 : typedef const AstSig& Lookup;
163 0 : static HashNumber hash(Lookup sig) {
164 0 : return AddContainerToHash(sig.args(), HashNumber(sig.ret()));
165 : }
166 0 : static bool match(const AstSig* lhs, Lookup rhs) {
167 0 : return *lhs == rhs;
168 : }
169 : };
170 :
171 : const uint32_t AstNodeUnknownOffset = 0;
172 :
173 : class AstNode : public AstBase
174 : {
175 : uint32_t offset_; // if applicable, offset in the binary format file
176 :
177 : public:
178 0 : AstNode() : offset_(AstNodeUnknownOffset) {}
179 :
180 0 : uint32_t offset() const { return offset_; }
181 0 : void setOffset(uint32_t offset) { offset_ = offset; }
182 : };
183 :
184 : enum class AstExprKind
185 : {
186 : BinaryOperator,
187 : Block,
188 : Branch,
189 : BranchTable,
190 : Call,
191 : CallIndirect,
192 : ComparisonOperator,
193 : Const,
194 : ConversionOperator,
195 : CurrentMemory,
196 : Drop,
197 : First,
198 : GetGlobal,
199 : GetLocal,
200 : GrowMemory,
201 : If,
202 : Load,
203 : Nop,
204 : Pop,
205 : Return,
206 : SetGlobal,
207 : SetLocal,
208 : TeeLocal,
209 : Store,
210 : TernaryOperator,
211 : UnaryOperator,
212 : Unreachable
213 : };
214 :
215 : class AstExpr : public AstNode
216 : {
217 : const AstExprKind kind_;
218 : ExprType type_;
219 :
220 : protected:
221 0 : AstExpr(AstExprKind kind, ExprType type)
222 0 : : kind_(kind), type_(type)
223 0 : {}
224 :
225 : public:
226 0 : AstExprKind kind() const { return kind_; }
227 :
228 0 : bool isVoid() const { return IsVoid(type_); }
229 :
230 : // Note that for nodes other than blocks and block-like things, this
231 : // may return ExprType::Limit for nodes with non-void types.
232 0 : ExprType type() const { return type_; }
233 :
234 : template <class T>
235 0 : T& as() {
236 0 : MOZ_ASSERT(kind() == T::Kind);
237 0 : return static_cast<T&>(*this);
238 : }
239 : };
240 :
241 : struct AstNop : AstExpr
242 : {
243 : static const AstExprKind Kind = AstExprKind::Nop;
244 0 : AstNop()
245 0 : : AstExpr(AstExprKind::Nop, ExprType::Void)
246 0 : {}
247 : };
248 :
249 : struct AstUnreachable : AstExpr
250 : {
251 : static const AstExprKind Kind = AstExprKind::Unreachable;
252 0 : AstUnreachable()
253 0 : : AstExpr(AstExprKind::Unreachable, ExprType::Void)
254 0 : {}
255 : };
256 :
257 : class AstDrop : public AstExpr
258 : {
259 : AstExpr& value_;
260 :
261 : public:
262 : static const AstExprKind Kind = AstExprKind::Drop;
263 0 : explicit AstDrop(AstExpr& value)
264 0 : : AstExpr(AstExprKind::Drop, ExprType::Void),
265 0 : value_(value)
266 0 : {}
267 0 : AstExpr& value() const {
268 0 : return value_;
269 : }
270 : };
271 :
272 : class AstConst : public AstExpr
273 : {
274 : const Val val_;
275 :
276 : public:
277 : static const AstExprKind Kind = AstExprKind::Const;
278 0 : explicit AstConst(Val val)
279 0 : : AstExpr(Kind, ExprType::Limit),
280 0 : val_(val)
281 0 : {}
282 0 : Val val() const { return val_; }
283 : };
284 :
285 : class AstGetLocal : public AstExpr
286 : {
287 : AstRef local_;
288 :
289 : public:
290 : static const AstExprKind Kind = AstExprKind::GetLocal;
291 0 : explicit AstGetLocal(AstRef local)
292 0 : : AstExpr(Kind, ExprType::Limit),
293 0 : local_(local)
294 0 : {}
295 0 : AstRef& local() {
296 0 : return local_;
297 : }
298 : };
299 :
300 : class AstSetLocal : public AstExpr
301 : {
302 : AstRef local_;
303 : AstExpr& value_;
304 :
305 : public:
306 : static const AstExprKind Kind = AstExprKind::SetLocal;
307 0 : AstSetLocal(AstRef local, AstExpr& value)
308 0 : : AstExpr(Kind, ExprType::Void),
309 : local_(local),
310 0 : value_(value)
311 0 : {}
312 0 : AstRef& local() {
313 0 : return local_;
314 : }
315 0 : AstExpr& value() const {
316 0 : return value_;
317 : }
318 : };
319 :
320 : class AstGetGlobal : public AstExpr
321 : {
322 : AstRef global_;
323 :
324 : public:
325 : static const AstExprKind Kind = AstExprKind::GetGlobal;
326 0 : explicit AstGetGlobal(AstRef global)
327 0 : : AstExpr(Kind, ExprType::Limit),
328 0 : global_(global)
329 0 : {}
330 0 : AstRef& global() {
331 0 : return global_;
332 : }
333 : };
334 :
335 : class AstSetGlobal : public AstExpr
336 : {
337 : AstRef global_;
338 : AstExpr& value_;
339 :
340 : public:
341 : static const AstExprKind Kind = AstExprKind::SetGlobal;
342 0 : AstSetGlobal(AstRef global, AstExpr& value)
343 0 : : AstExpr(Kind, ExprType::Void),
344 : global_(global),
345 0 : value_(value)
346 0 : {}
347 0 : AstRef& global() {
348 0 : return global_;
349 : }
350 0 : AstExpr& value() const {
351 0 : return value_;
352 : }
353 : };
354 :
355 : class AstTeeLocal : public AstExpr
356 : {
357 : AstRef local_;
358 : AstExpr& value_;
359 :
360 : public:
361 : static const AstExprKind Kind = AstExprKind::TeeLocal;
362 0 : AstTeeLocal(AstRef local, AstExpr& value)
363 0 : : AstExpr(Kind, ExprType::Limit),
364 : local_(local),
365 0 : value_(value)
366 0 : {}
367 0 : AstRef& local() {
368 0 : return local_;
369 : }
370 0 : AstExpr& value() const {
371 0 : return value_;
372 : }
373 : };
374 :
375 : class AstBlock : public AstExpr
376 : {
377 : Op op_;
378 : AstName name_;
379 : AstExprVector exprs_;
380 :
381 : public:
382 : static const AstExprKind Kind = AstExprKind::Block;
383 0 : explicit AstBlock(Op op, ExprType type, AstName name, AstExprVector&& exprs)
384 0 : : AstExpr(Kind, type),
385 : op_(op),
386 : name_(name),
387 0 : exprs_(Move(exprs))
388 0 : {}
389 :
390 0 : Op op() const { return op_; }
391 0 : AstName name() const { return name_; }
392 0 : const AstExprVector& exprs() const { return exprs_; }
393 : };
394 :
395 : class AstBranch : public AstExpr
396 : {
397 : Op op_;
398 : AstExpr* cond_;
399 : AstRef target_;
400 : AstExpr* value_;
401 :
402 : public:
403 : static const AstExprKind Kind = AstExprKind::Branch;
404 0 : explicit AstBranch(Op op, ExprType type,
405 : AstExpr* cond, AstRef target, AstExpr* value)
406 0 : : AstExpr(Kind, type),
407 : op_(op),
408 : cond_(cond),
409 : target_(target),
410 0 : value_(value)
411 0 : {}
412 :
413 0 : Op op() const { return op_; }
414 0 : AstRef& target() { return target_; }
415 0 : AstExpr& cond() const { MOZ_ASSERT(cond_); return *cond_; }
416 0 : AstExpr* maybeValue() const { return value_; }
417 : };
418 :
419 : class AstCall : public AstExpr
420 : {
421 : Op op_;
422 : AstRef func_;
423 : AstExprVector args_;
424 :
425 : public:
426 : static const AstExprKind Kind = AstExprKind::Call;
427 0 : AstCall(Op op, ExprType type, AstRef func, AstExprVector&& args)
428 0 : : AstExpr(Kind, type), op_(op), func_(func), args_(Move(args))
429 0 : {}
430 :
431 0 : Op op() const { return op_; }
432 0 : AstRef& func() { return func_; }
433 0 : const AstExprVector& args() const { return args_; }
434 : };
435 :
436 : class AstCallIndirect : public AstExpr
437 : {
438 : AstRef sig_;
439 : AstExprVector args_;
440 : AstExpr* index_;
441 :
442 : public:
443 : static const AstExprKind Kind = AstExprKind::CallIndirect;
444 0 : AstCallIndirect(AstRef sig, ExprType type, AstExprVector&& args, AstExpr* index)
445 0 : : AstExpr(Kind, type), sig_(sig), args_(Move(args)), index_(index)
446 0 : {}
447 0 : AstRef& sig() { return sig_; }
448 0 : const AstExprVector& args() const { return args_; }
449 0 : AstExpr* index() const { return index_; }
450 : };
451 :
452 : class AstReturn : public AstExpr
453 : {
454 : AstExpr* maybeExpr_;
455 :
456 : public:
457 : static const AstExprKind Kind = AstExprKind::Return;
458 0 : explicit AstReturn(AstExpr* maybeExpr)
459 0 : : AstExpr(Kind, ExprType::Void),
460 0 : maybeExpr_(maybeExpr)
461 0 : {}
462 0 : AstExpr* maybeExpr() const { return maybeExpr_; }
463 : };
464 :
465 : class AstIf : public AstExpr
466 : {
467 : AstExpr* cond_;
468 : AstName name_;
469 : AstExprVector thenExprs_;
470 : AstExprVector elseExprs_;
471 :
472 : public:
473 : static const AstExprKind Kind = AstExprKind::If;
474 0 : AstIf(ExprType type, AstExpr* cond, AstName name,
475 : AstExprVector&& thenExprs, AstExprVector&& elseExprs)
476 0 : : AstExpr(Kind, type),
477 : cond_(cond),
478 : name_(name),
479 0 : thenExprs_(Move(thenExprs)),
480 0 : elseExprs_(Move(elseExprs))
481 0 : {}
482 :
483 0 : AstExpr& cond() const { return *cond_; }
484 0 : const AstExprVector& thenExprs() const { return thenExprs_; }
485 0 : bool hasElse() const { return elseExprs_.length(); }
486 0 : const AstExprVector& elseExprs() const { MOZ_ASSERT(hasElse()); return elseExprs_; }
487 0 : AstName name() const { return name_; }
488 : };
489 :
490 : class AstLoadStoreAddress
491 : {
492 : AstExpr* base_;
493 : int32_t flags_;
494 : int32_t offset_;
495 :
496 : public:
497 0 : explicit AstLoadStoreAddress(AstExpr* base, int32_t flags, int32_t offset)
498 0 : : base_(base),
499 : flags_(flags),
500 0 : offset_(offset)
501 0 : {}
502 :
503 0 : AstExpr& base() const { return *base_; }
504 0 : int32_t flags() const { return flags_; }
505 0 : int32_t offset() const { return offset_; }
506 : };
507 :
508 : class AstLoad : public AstExpr
509 : {
510 : Op op_;
511 : AstLoadStoreAddress address_;
512 :
513 : public:
514 : static const AstExprKind Kind = AstExprKind::Load;
515 0 : explicit AstLoad(Op op, const AstLoadStoreAddress &address)
516 0 : : AstExpr(Kind, ExprType::Limit),
517 : op_(op),
518 0 : address_(address)
519 0 : {}
520 :
521 0 : Op op() const { return op_; }
522 0 : const AstLoadStoreAddress& address() const { return address_; }
523 : };
524 :
525 : class AstStore : public AstExpr
526 : {
527 : Op op_;
528 : AstLoadStoreAddress address_;
529 : AstExpr* value_;
530 :
531 : public:
532 : static const AstExprKind Kind = AstExprKind::Store;
533 0 : explicit AstStore(Op op, const AstLoadStoreAddress &address, AstExpr* value)
534 0 : : AstExpr(Kind, ExprType::Void),
535 : op_(op),
536 : address_(address),
537 0 : value_(value)
538 0 : {}
539 :
540 0 : Op op() const { return op_; }
541 0 : const AstLoadStoreAddress& address() const { return address_; }
542 0 : AstExpr& value() const { return *value_; }
543 : };
544 :
545 : class AstCurrentMemory final : public AstExpr
546 : {
547 : public:
548 : static const AstExprKind Kind = AstExprKind::CurrentMemory;
549 0 : explicit AstCurrentMemory()
550 0 : : AstExpr(Kind, ExprType::I32)
551 0 : {}
552 : };
553 :
554 : class AstGrowMemory final : public AstExpr
555 : {
556 : AstExpr* operand_;
557 :
558 : public:
559 : static const AstExprKind Kind = AstExprKind::GrowMemory;
560 0 : explicit AstGrowMemory(AstExpr* operand)
561 0 : : AstExpr(Kind, ExprType::I32), operand_(operand)
562 0 : {}
563 :
564 0 : AstExpr* operand() const { return operand_; }
565 : };
566 :
567 : class AstBranchTable : public AstExpr
568 : {
569 : AstExpr& index_;
570 : AstRef default_;
571 : AstRefVector table_;
572 : AstExpr* value_;
573 :
574 : public:
575 : static const AstExprKind Kind = AstExprKind::BranchTable;
576 0 : explicit AstBranchTable(AstExpr& index, AstRef def, AstRefVector&& table,
577 : AstExpr* maybeValue)
578 0 : : AstExpr(Kind, ExprType::Void),
579 : index_(index),
580 : default_(def),
581 0 : table_(Move(table)),
582 0 : value_(maybeValue)
583 0 : {}
584 0 : AstExpr& index() const { return index_; }
585 0 : AstRef& def() { return default_; }
586 0 : AstRefVector& table() { return table_; }
587 0 : AstExpr* maybeValue() { return value_; }
588 : };
589 :
590 : class AstFunc : public AstNode
591 : {
592 : AstName name_;
593 : AstRef sig_;
594 : AstValTypeVector vars_;
595 : AstNameVector localNames_;
596 : AstExprVector body_;
597 : uint32_t endOffset_; // if applicable, offset in the binary format file
598 :
599 : public:
600 0 : AstFunc(AstName name, AstRef sig, AstValTypeVector&& vars,
601 : AstNameVector&& locals, AstExprVector&& body)
602 0 : : name_(name),
603 : sig_(sig),
604 0 : vars_(Move(vars)),
605 0 : localNames_(Move(locals)),
606 0 : body_(Move(body)),
607 0 : endOffset_(AstNodeUnknownOffset)
608 0 : {}
609 0 : AstRef& sig() { return sig_; }
610 0 : const AstValTypeVector& vars() const { return vars_; }
611 0 : const AstNameVector& locals() const { return localNames_; }
612 0 : const AstExprVector& body() const { return body_; }
613 0 : AstName name() const { return name_; }
614 0 : uint32_t endOffset() const { return endOffset_; }
615 0 : void setEndOffset(uint32_t offset) { endOffset_ = offset; }
616 : };
617 :
618 0 : class AstGlobal : public AstNode
619 : {
620 : AstName name_;
621 : bool isMutable_;
622 : ValType type_;
623 : Maybe<AstExpr*> init_;
624 :
625 : public:
626 0 : AstGlobal() : isMutable_(false), type_(ValType(TypeCode::Limit))
627 0 : {}
628 :
629 0 : explicit AstGlobal(AstName name, ValType type, bool isMutable,
630 : const Maybe<AstExpr*>& init = Maybe<AstExpr*>())
631 0 : : name_(name), isMutable_(isMutable), type_(type), init_(init)
632 0 : {}
633 :
634 0 : AstName name() const { return name_; }
635 0 : bool isMutable() const { return isMutable_; }
636 0 : ValType type() const { return type_; }
637 :
638 0 : bool hasInit() const { return !!init_; }
639 0 : AstExpr& init() const { MOZ_ASSERT(hasInit()); return **init_; }
640 : };
641 :
642 : typedef AstVector<AstGlobal*> AstGlobalVector;
643 :
644 : class AstImport : public AstNode
645 : {
646 : AstName name_;
647 : AstName module_;
648 : AstName field_;
649 : DefinitionKind kind_;
650 :
651 : AstRef funcSig_;
652 : Limits limits_;
653 : AstGlobal global_;
654 :
655 : public:
656 0 : AstImport(AstName name, AstName module, AstName field, AstRef funcSig)
657 0 : : name_(name), module_(module), field_(field), kind_(DefinitionKind::Function), funcSig_(funcSig)
658 0 : {}
659 0 : AstImport(AstName name, AstName module, AstName field, DefinitionKind kind,
660 : const Limits& limits)
661 0 : : name_(name), module_(module), field_(field), kind_(kind), limits_(limits)
662 0 : {}
663 0 : AstImport(AstName name, AstName module, AstName field, const AstGlobal& global)
664 0 : : name_(name), module_(module), field_(field), kind_(DefinitionKind::Global), global_(global)
665 0 : {}
666 :
667 0 : AstName name() const { return name_; }
668 0 : AstName module() const { return module_; }
669 0 : AstName field() const { return field_; }
670 :
671 0 : DefinitionKind kind() const { return kind_; }
672 0 : AstRef& funcSig() {
673 0 : MOZ_ASSERT(kind_ == DefinitionKind::Function);
674 0 : return funcSig_;
675 : }
676 0 : Limits limits() const {
677 0 : MOZ_ASSERT(kind_ == DefinitionKind::Memory || kind_ == DefinitionKind::Table);
678 0 : return limits_;
679 : }
680 0 : const AstGlobal& global() const {
681 0 : MOZ_ASSERT(kind_ == DefinitionKind::Global);
682 0 : return global_;
683 : }
684 : };
685 :
686 : class AstExport : public AstNode
687 : {
688 : AstName name_;
689 : DefinitionKind kind_;
690 : AstRef ref_;
691 :
692 : public:
693 0 : AstExport(AstName name, DefinitionKind kind, AstRef ref)
694 0 : : name_(name), kind_(kind), ref_(ref)
695 0 : {}
696 : explicit AstExport(AstName name, DefinitionKind kind)
697 : : name_(name), kind_(kind)
698 : {}
699 0 : AstName name() const { return name_; }
700 0 : DefinitionKind kind() const { return kind_; }
701 0 : AstRef& ref() { return ref_; }
702 : };
703 :
704 : class AstDataSegment : public AstNode
705 : {
706 : AstExpr* offset_;
707 : AstNameVector fragments_;
708 :
709 : public:
710 0 : AstDataSegment(AstExpr* offset, AstNameVector&& fragments)
711 0 : : offset_(offset), fragments_(Move(fragments))
712 0 : {}
713 :
714 0 : AstExpr* offset() const { return offset_; }
715 0 : const AstNameVector& fragments() const { return fragments_; }
716 : };
717 :
718 : typedef AstVector<AstDataSegment*> AstDataSegmentVector;
719 :
720 : class AstElemSegment : public AstNode
721 : {
722 : AstExpr* offset_;
723 : AstRefVector elems_;
724 :
725 : public:
726 0 : AstElemSegment(AstExpr* offset, AstRefVector&& elems)
727 0 : : offset_(offset), elems_(Move(elems))
728 0 : {}
729 :
730 0 : AstExpr* offset() const { return offset_; }
731 0 : AstRefVector& elems() { return elems_; }
732 0 : const AstRefVector& elems() const { return elems_; }
733 : };
734 :
735 : typedef AstVector<AstElemSegment*> AstElemSegmentVector;
736 :
737 : class AstStartFunc : public AstNode
738 : {
739 : AstRef func_;
740 :
741 : public:
742 0 : explicit AstStartFunc(AstRef func)
743 0 : : func_(func)
744 0 : {}
745 :
746 0 : AstRef& func() {
747 0 : return func_;
748 : }
749 : };
750 :
751 0 : struct AstResizable
752 : {
753 : AstName name;
754 : Limits limits;
755 : bool imported;
756 :
757 0 : AstResizable(const Limits& limits, bool imported, AstName name = AstName())
758 0 : : name(name),
759 : limits(limits),
760 0 : imported(imported)
761 0 : {}
762 : };
763 :
764 : class AstModule : public AstNode
765 : {
766 : public:
767 : typedef AstVector<AstFunc*> FuncVector;
768 : typedef AstVector<AstImport*> ImportVector;
769 : typedef AstVector<AstExport*> ExportVector;
770 : typedef AstVector<AstSig*> SigVector;
771 : typedef AstVector<AstName> NameVector;
772 : typedef AstVector<AstResizable> AstResizableVector;
773 :
774 : private:
775 : typedef AstHashMap<AstSig*, uint32_t, AstSig> SigMap;
776 :
777 : LifoAlloc& lifo_;
778 : SigVector sigs_;
779 : SigMap sigMap_;
780 : ImportVector imports_;
781 : NameVector funcImportNames_;
782 : AstResizableVector tables_;
783 : AstResizableVector memories_;
784 : ExportVector exports_;
785 : Maybe<AstStartFunc> startFunc_;
786 : FuncVector funcs_;
787 : AstDataSegmentVector dataSegments_;
788 : AstElemSegmentVector elemSegments_;
789 : AstGlobalVector globals_;
790 :
791 : public:
792 0 : explicit AstModule(LifoAlloc& lifo)
793 0 : : lifo_(lifo),
794 : sigs_(lifo),
795 : sigMap_(lifo),
796 : imports_(lifo),
797 : funcImportNames_(lifo),
798 : tables_(lifo),
799 : memories_(lifo),
800 : exports_(lifo),
801 : funcs_(lifo),
802 : dataSegments_(lifo),
803 : elemSegments_(lifo),
804 0 : globals_(lifo)
805 0 : {}
806 0 : bool init() {
807 0 : return sigMap_.init();
808 : }
809 0 : bool addMemory(AstName name, const Limits& memory) {
810 0 : return memories_.append(AstResizable(memory, false, name));
811 : }
812 0 : bool hasMemory() const {
813 0 : return !!memories_.length();
814 : }
815 0 : const AstResizableVector& memories() const {
816 0 : return memories_;
817 : }
818 0 : bool addTable(AstName name, const Limits& table) {
819 0 : return tables_.append(AstResizable(table, false, name));
820 : }
821 0 : bool hasTable() const {
822 0 : return !!tables_.length();
823 : }
824 0 : const AstResizableVector& tables() const {
825 0 : return tables_;
826 : }
827 0 : bool append(AstDataSegment* seg) {
828 0 : return dataSegments_.append(seg);
829 : }
830 0 : const AstDataSegmentVector& dataSegments() const {
831 0 : return dataSegments_;
832 : }
833 0 : bool append(AstElemSegment* seg) {
834 0 : return elemSegments_.append(seg);
835 : }
836 0 : const AstElemSegmentVector& elemSegments() const {
837 0 : return elemSegments_;
838 : }
839 0 : bool hasStartFunc() const {
840 0 : return !!startFunc_;
841 : }
842 0 : bool setStartFunc(AstStartFunc startFunc) {
843 0 : if (startFunc_)
844 0 : return false;
845 0 : startFunc_.emplace(startFunc);
846 0 : return true;
847 : }
848 0 : AstStartFunc& startFunc() {
849 0 : return *startFunc_;
850 : }
851 0 : bool declare(AstSig&& sig, uint32_t* sigIndex) {
852 0 : SigMap::AddPtr p = sigMap_.lookupForAdd(sig);
853 0 : if (p) {
854 0 : *sigIndex = p->value();
855 0 : return true;
856 : }
857 0 : *sigIndex = sigs_.length();
858 0 : auto* lifoSig = new (lifo_) AstSig(AstName(), Move(sig));
859 0 : return lifoSig &&
860 0 : sigs_.append(lifoSig) &&
861 0 : sigMap_.add(p, sigs_.back(), *sigIndex);
862 : }
863 0 : bool append(AstSig* sig) {
864 0 : uint32_t sigIndex = sigs_.length();
865 0 : if (!sigs_.append(sig))
866 0 : return false;
867 0 : SigMap::AddPtr p = sigMap_.lookupForAdd(*sig);
868 0 : return p || sigMap_.add(p, sig, sigIndex);
869 : }
870 0 : const SigVector& sigs() const {
871 0 : return sigs_;
872 : }
873 0 : bool append(AstFunc* func) {
874 0 : return funcs_.append(func);
875 : }
876 0 : const FuncVector& funcs() const {
877 0 : return funcs_;
878 : }
879 0 : bool append(AstImport* imp) {
880 0 : switch (imp->kind()) {
881 : case DefinitionKind::Function:
882 0 : if (!funcImportNames_.append(imp->name()))
883 0 : return false;
884 0 : break;
885 : case DefinitionKind::Table:
886 0 : if (!tables_.append(AstResizable(imp->limits(), true)))
887 0 : return false;
888 0 : break;
889 : case DefinitionKind::Memory:
890 0 : if (!memories_.append(AstResizable(imp->limits(), true)))
891 0 : return false;
892 0 : break;
893 : case DefinitionKind::Global:
894 0 : break;
895 : }
896 :
897 0 : return imports_.append(imp);
898 : }
899 0 : const ImportVector& imports() const {
900 0 : return imports_;
901 : }
902 0 : const NameVector& funcImportNames() const {
903 0 : return funcImportNames_;
904 : }
905 0 : size_t numFuncImports() const {
906 0 : return funcImportNames_.length();
907 : }
908 0 : bool append(AstExport* exp) {
909 0 : return exports_.append(exp);
910 : }
911 0 : const ExportVector& exports() const {
912 0 : return exports_;
913 : }
914 0 : bool append(AstGlobal* glob) {
915 0 : return globals_.append(glob);
916 : }
917 0 : const AstGlobalVector& globals() const {
918 0 : return globals_;
919 : }
920 : };
921 :
922 : class AstUnaryOperator final : public AstExpr
923 : {
924 : Op op_;
925 : AstExpr* operand_;
926 :
927 : public:
928 : static const AstExprKind Kind = AstExprKind::UnaryOperator;
929 0 : explicit AstUnaryOperator(Op op, AstExpr* operand)
930 0 : : AstExpr(Kind, ExprType::Limit),
931 0 : op_(op), operand_(operand)
932 0 : {}
933 :
934 0 : Op op() const { return op_; }
935 0 : AstExpr* operand() const { return operand_; }
936 : };
937 :
938 : class AstBinaryOperator final : public AstExpr
939 : {
940 : Op op_;
941 : AstExpr* lhs_;
942 : AstExpr* rhs_;
943 :
944 : public:
945 : static const AstExprKind Kind = AstExprKind::BinaryOperator;
946 0 : explicit AstBinaryOperator(Op op, AstExpr* lhs, AstExpr* rhs)
947 0 : : AstExpr(Kind, ExprType::Limit),
948 0 : op_(op), lhs_(lhs), rhs_(rhs)
949 0 : {}
950 :
951 0 : Op op() const { return op_; }
952 0 : AstExpr* lhs() const { return lhs_; }
953 0 : AstExpr* rhs() const { return rhs_; }
954 : };
955 :
956 : class AstTernaryOperator : public AstExpr
957 : {
958 : Op op_;
959 : AstExpr* op0_;
960 : AstExpr* op1_;
961 : AstExpr* op2_;
962 :
963 : public:
964 : static const AstExprKind Kind = AstExprKind::TernaryOperator;
965 0 : AstTernaryOperator(Op op, AstExpr* op0, AstExpr* op1, AstExpr* op2)
966 0 : : AstExpr(Kind, ExprType::Limit),
967 0 : op_(op), op0_(op0), op1_(op1), op2_(op2)
968 0 : {}
969 :
970 0 : Op op() const { return op_; }
971 0 : AstExpr* op0() const { return op0_; }
972 0 : AstExpr* op1() const { return op1_; }
973 0 : AstExpr* op2() const { return op2_; }
974 : };
975 :
976 : class AstComparisonOperator final : public AstExpr
977 : {
978 : Op op_;
979 : AstExpr* lhs_;
980 : AstExpr* rhs_;
981 :
982 : public:
983 : static const AstExprKind Kind = AstExprKind::ComparisonOperator;
984 0 : explicit AstComparisonOperator(Op op, AstExpr* lhs, AstExpr* rhs)
985 0 : : AstExpr(Kind, ExprType::Limit),
986 0 : op_(op), lhs_(lhs), rhs_(rhs)
987 0 : {}
988 :
989 0 : Op op() const { return op_; }
990 0 : AstExpr* lhs() const { return lhs_; }
991 0 : AstExpr* rhs() const { return rhs_; }
992 : };
993 :
994 : class AstConversionOperator final : public AstExpr
995 : {
996 : Op op_;
997 : AstExpr* operand_;
998 :
999 : public:
1000 : static const AstExprKind Kind = AstExprKind::ConversionOperator;
1001 0 : explicit AstConversionOperator(Op op, AstExpr* operand)
1002 0 : : AstExpr(Kind, ExprType::Limit),
1003 0 : op_(op), operand_(operand)
1004 0 : {}
1005 :
1006 0 : Op op() const { return op_; }
1007 0 : AstExpr* operand() const { return operand_; }
1008 : };
1009 :
1010 : // This is an artificial AST node which can fill operand slots in an AST
1011 : // constructed from parsing or decoding stack-machine code that doesn't have
1012 : // an inherent AST structure.
1013 : class AstPop final : public AstExpr
1014 : {
1015 : public:
1016 : static const AstExprKind Kind = AstExprKind::Pop;
1017 0 : AstPop()
1018 0 : : AstExpr(Kind, ExprType::Void)
1019 0 : {}
1020 : };
1021 :
1022 : // This is an artificial AST node which can be used to represent some forms
1023 : // of stack-machine code in an AST form. It is similar to Block, but returns the
1024 : // value of its first operand, rather than the last.
1025 : class AstFirst : public AstExpr
1026 : {
1027 : AstExprVector exprs_;
1028 :
1029 : public:
1030 : static const AstExprKind Kind = AstExprKind::First;
1031 0 : explicit AstFirst(AstExprVector&& exprs)
1032 0 : : AstExpr(Kind, ExprType::Limit),
1033 0 : exprs_(Move(exprs))
1034 0 : {}
1035 :
1036 0 : AstExprVector& exprs() { return exprs_; }
1037 : const AstExprVector& exprs() const { return exprs_; }
1038 : };
1039 :
1040 : } // end wasm namespace
1041 : } // end js namespace
1042 :
1043 : #endif // namespace wasmast_h
|