File: type-builder.cpp

package info (click to toggle)
binaryen 99-3
  • links: PTS, VCS
  • area: main
  • in suites: bullseye
  • size: 31,352 kB
  • sloc: cpp: 134,831; javascript: 61,839; ansic: 12,369; python: 4,620; pascal: 441; sh: 72; asm: 27; makefile: 6
file content (142 lines) | stat: -rw-r--r-- 5,007 bytes parent folder | download
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
#include <cassert>
#include <iostream>

#include "wasm-type.h"

using namespace wasm;

// Construct Signature, Struct, and Array heap types using undefined types.
void test_builder() {
  std::cout << ";; Test TypeBuilder\n";

  // (type $sig (func (param (ref $struct)) (result (ref $array) i32)))
  // (type $struct (struct (field (ref null $array) (mut rtt 0 $array))))
  // (type $array (array (mut externref)))

  TypeBuilder builder(3);

  Type refSig = builder.getTempRefType(0, NonNullable);
  Type refStruct = builder.getTempRefType(1, NonNullable);
  Type refArray = builder.getTempRefType(2, NonNullable);
  Type refNullArray = builder.getTempRefType(2, Nullable);
  Type rttArray = builder.getTempRttType(2, 0);
  Type refNullExt(HeapType::ext, Nullable);

  Signature sig(refStruct, builder.getTempTupleType({refArray, Type::i32}));
  Struct struct_({Field(refNullArray, Immutable), Field(rttArray, Mutable)});
  Array array(Field(refNullExt, Mutable));

  std::cout << "Before setting heap types:\n";
  std::cout << "(ref $sig) => " << refSig << "\n";
  std::cout << "(ref $struct) => " << refStruct << "\n";
  std::cout << "(ref $array) => " << refArray << "\n";
  std::cout << "(ref null $array) => " << refNullArray << "\n";
  std::cout << "(rtt 0 $array) => " << rttArray << "\n\n";

  builder.setHeapType(0, sig);
  builder.setHeapType(1, struct_);
  builder.setHeapType(2, array);

  std::cout << "After setting heap types:\n";
  std::cout << "(ref $sig) => " << refSig << "\n";
  std::cout << "(ref $struct) => " << refStruct << "\n";
  std::cout << "(ref $array) => " << refArray << "\n";
  std::cout << "(ref null $array) => " << refNullArray << "\n";
  std::cout << "(rtt 0 $array) => " << rttArray << "\n\n";

  std::vector<HeapType> built = builder.build();

  Type newRefSig = Type(built[0], NonNullable);
  Type newRefStruct = Type(built[1], NonNullable);
  Type newRefArray = Type(built[2], NonNullable);
  Type newRefNullArray = Type(built[2], Nullable);
  Type newRttArray = Type(Rtt(0, built[2]));

  assert(refSig != newRefSig);
  assert(refStruct != newRefStruct);
  assert(refArray != newRefArray);
  assert(refNullArray != newRefNullArray);
  assert(rttArray != newRttArray);

  std::cout << "After building types:\n";
  std::cout << "(ref $sig) => " << newRefSig << "\n";
  std::cout << "(ref $struct) => " << newRefStruct << "\n";
  std::cout << "(ref $array) => " << newRefArray << "\n";
  std::cout << "(ref null $array) => " << newRefNullArray << "\n";
  std::cout << "(rtt 0 $array) => " << newRttArray << "\n\n";
}

// Check that the builder works when there are duplicate definitions
void test_canonicalization() {
  std::cout << ";; Test canonicalization\n";

  // (type $struct (struct (field (ref null $sig))))
  // (type $sig (func))
  HeapType sig = Signature(Type::none, Type::none);
  HeapType struct_ = Struct({Field(Type(sig, Nullable), Immutable)});

  TypeBuilder builder(4);

  Type tempSigRef1 = builder.getTempRefType(2, Nullable);
  Type tempSigRef2 = builder.getTempRefType(3, Nullable);

  assert(tempSigRef1 != tempSigRef2);
  assert(tempSigRef1 != Type(sig, Nullable));
  assert(tempSigRef2 != Type(sig, Nullable));

  builder.setHeapType(0, Struct({Field(tempSigRef1, Immutable)}));
  builder.setHeapType(1, Struct({Field(tempSigRef2, Immutable)}));
  builder.setHeapType(2, Signature(Type::none, Type::none));
  builder.setHeapType(3, Signature(Type::none, Type::none));

  std::vector<HeapType> built = builder.build();

  assert(built[0] == struct_);
  assert(built[1] == struct_);
  assert(built[2] == sig);
  assert(built[3] == sig);
}

void test_recursive() {
  std::cout << ";; Test recursive types\n";

  {
    // Trivial recursion
    TypeBuilder builder(1);
    Type temp = builder.getTempRefType(0, Nullable);
    builder.setHeapType(0, Signature(Type::none, temp));
    // std::vector<HeapType> built = builder.build();
  }

  {
    // Mutual recursion
    TypeBuilder builder(2);
    Type temp0 = builder.getTempRefType(0, Nullable);
    Type temp1 = builder.getTempRefType(1, Nullable);
    builder.setHeapType(0, Signature(Type::none, temp1));
    builder.setHeapType(1, Signature(Type::none, temp0));
    // std::vector<HeapType> built = builder.build();
  }

  {
    // A longer chain of recursion
    TypeBuilder builder(5);
    Type temp0 = builder.getTempRefType(0, Nullable);
    Type temp1 = builder.getTempRefType(1, Nullable);
    Type temp2 = builder.getTempRefType(2, Nullable);
    Type temp3 = builder.getTempRefType(3, Nullable);
    Type temp4 = builder.getTempRefType(4, Nullable);
    builder.setHeapType(0, Signature(Type::none, temp1));
    builder.setHeapType(1, Signature(Type::none, temp2));
    builder.setHeapType(2, Signature(Type::none, temp3));
    builder.setHeapType(3, Signature(Type::none, temp4));
    builder.setHeapType(4, Signature(Type::none, temp0));
    // std::vector<HeapType> built = builder.build();
  }
}

int main() {
  test_builder();
  test_canonicalization();
  test_recursive();
}