summaryrefslogtreecommitdiff
path: root/src/ir/trapping.h
blob: 48f485faa87521fff60c84d551fc1911916b22ae (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
/*
 * 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 wasm_ir_trapping_h
#define wasm_ir_trapping_h

#include <exception>

#include "pass.h"

namespace wasm {

enum class TrapMode {
  Allow,
  Clamp,
  JS
};

inline void addTrapModePass(PassRunner& runner, TrapMode trapMode) {
  if (trapMode == TrapMode::Clamp) {
    runner.add("trap-mode-clamp");
  } else if (trapMode == TrapMode::JS) {
    runner.add("trap-mode-js");
  }
}

class TrappingFunctionContainer {
public:
  TrappingFunctionContainer(TrapMode mode, Module &wasm, bool immediate = false)
    : mode(mode),
      wasm(wasm),
      immediate(immediate) { }

  bool hasFunction(Name name) {
    return functions.find(name) != functions.end();
  }
  bool hasImport(Name name) {
    return imports.find(name) != imports.end();
  }

  void addFunction(Function* function) {
    functions[function->name] = function;
    if (immediate) {
      wasm.addFunction(function);
    }
  }
  void addImport(Function* import) {
    imports[import->name] = import;
    if (immediate) {
      wasm.addFunction(import);
    }
  }

  void addToModule() {
    if (!immediate) {
      for (auto &pair : functions) {
        wasm.addFunction(pair.second);
      }
      for (auto &pair : imports) {
        wasm.addFunction(pair.second);
      }
    }
    functions.clear();
    imports.clear();
  }

  TrapMode getMode() {
    return mode;
  }

  Module& getModule() {
    return wasm;
  }

  std::map<Name, Function*>& getFunctions() {
    return functions;
  }

private:
  std::map<Name, Function*> functions;
  std::map<Name, Function*> imports;

  TrapMode mode;
  Module& wasm;
  bool immediate;
};

Expression* makeTrappingBinary(Binary* curr, TrappingFunctionContainer &trappingFunctions);
Expression* makeTrappingUnary(Unary* curr, TrappingFunctionContainer &trappingFunctions);

inline TrapMode trapModeFromString(std::string const& str) {
  if (str == "allow") {
    return TrapMode::Allow;
  } else if (str == "clamp") {
    return TrapMode::Clamp;
  } else if (str == "js") {
    return TrapMode::JS;
  } else {
    throw std::invalid_argument(
      "Unsupported trap mode \"" + str + "\". "
      "Valid modes are \"allow\", \"js\", and \"clamp\"");
  }
}

} // wasm

#endif // wasm_ir_trapping_h