summaryrefslogtreecommitdiffstats
path: root/third_party/wasm2c/include/wabt/type.h
blob: 96fcf94588fdca90003a50d3654523c4660516e4 (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
/*
 * Copyright 2020 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_H_
#define WABT_TYPE_H_

#include <cassert>
#include <cstdint>
#include <vector>

#include "wabt/config.h"
#include "wabt/base-types.h"
#include "wabt/string-format.h"

namespace wabt {

class Type;

using TypeVector = std::vector<Type>;

class Type {
 public:
  // Matches binary format, do not change.
  enum Enum : int32_t {
    I32 = -0x01,        // 0x7f
    I64 = -0x02,        // 0x7e
    F32 = -0x03,        // 0x7d
    F64 = -0x04,        // 0x7c
    V128 = -0x05,       // 0x7b
    I8 = -0x06,         // 0x7a  : packed-type only, used in gc and as v128 lane
    I16 = -0x07,        // 0x79  : packed-type only, used in gc and as v128 lane
    FuncRef = -0x10,    // 0x70
    ExternRef = -0x11,  // 0x6f
    Reference = -0x15,  // 0x6b
    Func = -0x20,       // 0x60
    Struct = -0x21,     // 0x5f
    Array = -0x22,      // 0x5e
    Void = -0x40,       // 0x40
    ___ = Void,         // Convenient for the opcode table in opcode.h

    Any = 0,   // Not actually specified, but useful for type-checking
    I8U = 4,   // Not actually specified, but used internally with load/store
    I16U = 6,  // Not actually specified, but used internally with load/store
    I32U = 7,  // Not actually specified, but used internally with load/store
  };

  Type() = default;  // Provided so Type can be member of a union.
  Type(int32_t code)
      : enum_(static_cast<Enum>(code)), type_index_(kInvalidIndex) {}
  Type(Enum e) : enum_(e), type_index_(kInvalidIndex) {}
  Type(Enum e, Index type_index) : enum_(e), type_index_(type_index) {
    assert(e == Enum::Reference);
  }
  constexpr operator Enum() const { return enum_; }

  bool IsRef() const {
    return enum_ == Type::ExternRef || enum_ == Type::FuncRef ||
           enum_ == Type::Reference;
  }

  bool IsReferenceWithIndex() const { return enum_ == Type::Reference; }

  bool IsNullableRef() const {
    // Currently all reftypes are nullable
    return IsRef();
  }

  std::string GetName() const {
    switch (enum_) {
      case Type::I32:       return "i32";
      case Type::I64:       return "i64";
      case Type::F32:       return "f32";
      case Type::F64:       return "f64";
      case Type::V128:      return "v128";
      case Type::I8:        return "i8";
      case Type::I16:       return "i16";
      case Type::FuncRef:   return "funcref";
      case Type::Func:      return "func";
      case Type::Void:      return "void";
      case Type::Any:       return "any";
      case Type::ExternRef: return "externref";
      case Type::Reference:
        return StringPrintf("(ref %d)", type_index_);
      default:
        return StringPrintf("<type_index[%d]>", enum_);
    }
  }

  const char* GetRefKindName() const {
    switch (enum_) {
      case Type::FuncRef:   return "func";
      case Type::ExternRef: return "extern";
      case Type::Struct:    return "struct";
      case Type::Array:     return "array";
      default:              return "<invalid>";
    }
  }

  // Functions for handling types that are an index into the type section.
  // These are always positive integers. They occur in the binary format in
  // block signatures, e.g.
  //
  //   (block (result i32 i64) ...)
  //
  // is encoded as
  //
  //   (type $T (func (result i32 i64)))
  //   ...
  //   (block (type $T) ...)
  //
  bool IsIndex() const { return static_cast<int32_t>(enum_) >= 0; }

  Index GetIndex() const {
    assert(IsIndex());
    return static_cast<Index>(enum_);
  }

  Index GetReferenceIndex() const {
    assert(enum_ == Enum::Reference);
    return type_index_;
  }

  TypeVector GetInlineVector() const {
    assert(!IsIndex());
    switch (enum_) {
      case Type::Void:
        return TypeVector();

      case Type::I32:
      case Type::I64:
      case Type::F32:
      case Type::F64:
      case Type::V128:
      case Type::FuncRef:
      case Type::ExternRef:
      case Type::Reference:
        return TypeVector(this, this + 1);

      default:
        WABT_UNREACHABLE;
    }
  }

 private:
  Enum enum_;
  Index type_index_;  // Only used for for Type::Reference
};

}  // namespace wabt

#endif  // WABT_TYPE_H_