index.js 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377
  1. function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
  2. function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }
  3. function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }
  4. import { isSignature, isNumberLiteral } from "../../nodes.js";
  5. export function moduleContextFromModuleAST(m) {
  6. var moduleContext = new ModuleContext();
  7. if (!(m.type === "Module")) {
  8. throw new Error('m.type === "Module"' + " error: " + (undefined || "unknown"));
  9. }
  10. m.fields.forEach(function (field) {
  11. switch (field.type) {
  12. case "Start":
  13. {
  14. moduleContext.setStart(field.index);
  15. break;
  16. }
  17. case "TypeInstruction":
  18. {
  19. moduleContext.addType(field);
  20. break;
  21. }
  22. case "Func":
  23. {
  24. moduleContext.addFunction(field);
  25. break;
  26. }
  27. case "Global":
  28. {
  29. moduleContext.defineGlobal(field);
  30. break;
  31. }
  32. case "ModuleImport":
  33. {
  34. switch (field.descr.type) {
  35. case "GlobalType":
  36. {
  37. moduleContext.importGlobal(field.descr.valtype, field.descr.mutability);
  38. break;
  39. }
  40. case "Memory":
  41. {
  42. moduleContext.addMemory(field.descr.limits.min, field.descr.limits.max);
  43. break;
  44. }
  45. case "FuncImportDescr":
  46. {
  47. moduleContext.importFunction(field.descr);
  48. break;
  49. }
  50. case "Table":
  51. {
  52. // FIXME(sven): not implemented yet
  53. break;
  54. }
  55. default:
  56. throw new Error("Unsupported ModuleImport of type " + JSON.stringify(field.descr.type));
  57. }
  58. break;
  59. }
  60. case "Memory":
  61. {
  62. moduleContext.addMemory(field.limits.min, field.limits.max);
  63. break;
  64. }
  65. }
  66. });
  67. return moduleContext;
  68. }
  69. /**
  70. * Module context for type checking
  71. */
  72. export var ModuleContext = /*#__PURE__*/function () {
  73. function ModuleContext() {
  74. _classCallCheck(this, ModuleContext);
  75. this.funcs = [];
  76. this.funcsOffsetByIdentifier = [];
  77. this.types = [];
  78. this.globals = [];
  79. this.globalsOffsetByIdentifier = [];
  80. this.mems = []; // Current stack frame
  81. this.locals = [];
  82. this.labels = [];
  83. this["return"] = [];
  84. this.debugName = "unknown";
  85. this.start = null;
  86. }
  87. /**
  88. * Set start segment
  89. */
  90. _createClass(ModuleContext, [{
  91. key: "setStart",
  92. value: function setStart(index) {
  93. this.start = index.value;
  94. }
  95. /**
  96. * Get start function
  97. */
  98. }, {
  99. key: "getStart",
  100. value: function getStart() {
  101. return this.start;
  102. }
  103. /**
  104. * Reset the active stack frame
  105. */
  106. }, {
  107. key: "newContext",
  108. value: function newContext(debugName, expectedResult) {
  109. this.locals = [];
  110. this.labels = [expectedResult];
  111. this["return"] = expectedResult;
  112. this.debugName = debugName;
  113. }
  114. /**
  115. * Functions
  116. */
  117. }, {
  118. key: "addFunction",
  119. value: function addFunction(func) {
  120. /* eslint-disable */
  121. // $FlowIgnore
  122. var _ref = func.signature || {},
  123. _ref$params = _ref.params,
  124. args = _ref$params === void 0 ? [] : _ref$params,
  125. _ref$results = _ref.results,
  126. result = _ref$results === void 0 ? [] : _ref$results;
  127. /* eslint-enable */
  128. args = args.map(function (arg) {
  129. return arg.valtype;
  130. });
  131. this.funcs.push({
  132. args: args,
  133. result: result
  134. });
  135. if (typeof func.name !== "undefined") {
  136. // $FlowIgnore
  137. this.funcsOffsetByIdentifier[func.name.value] = this.funcs.length - 1;
  138. }
  139. }
  140. }, {
  141. key: "importFunction",
  142. value: function importFunction(funcimport) {
  143. if (isSignature(funcimport.signature)) {
  144. // eslint-disable-next-line prefer-const
  145. var _funcimport$signature = funcimport.signature,
  146. args = _funcimport$signature.params,
  147. result = _funcimport$signature.results;
  148. args = args.map(function (arg) {
  149. return arg.valtype;
  150. });
  151. this.funcs.push({
  152. args: args,
  153. result: result
  154. });
  155. } else {
  156. if (!isNumberLiteral(funcimport.signature)) {
  157. throw new Error('isNumberLiteral(funcimport.signature)' + " error: " + (undefined || "unknown"));
  158. }
  159. var typeId = funcimport.signature.value;
  160. if (!this.hasType(typeId)) {
  161. throw new Error('this.hasType(typeId)' + " error: " + (undefined || "unknown"));
  162. }
  163. var signature = this.getType(typeId);
  164. this.funcs.push({
  165. args: signature.params.map(function (arg) {
  166. return arg.valtype;
  167. }),
  168. result: signature.results
  169. });
  170. }
  171. if (typeof funcimport.id !== "undefined") {
  172. // imports are first, we can assume their index in the array
  173. this.funcsOffsetByIdentifier[funcimport.id.value] = this.funcs.length - 1;
  174. }
  175. }
  176. }, {
  177. key: "hasFunction",
  178. value: function hasFunction(index) {
  179. return typeof this.getFunction(index) !== "undefined";
  180. }
  181. }, {
  182. key: "getFunction",
  183. value: function getFunction(index) {
  184. if (typeof index !== "number") {
  185. throw new Error("getFunction only supported for number index");
  186. }
  187. return this.funcs[index];
  188. }
  189. }, {
  190. key: "getFunctionOffsetByIdentifier",
  191. value: function getFunctionOffsetByIdentifier(name) {
  192. if (!(typeof name === "string")) {
  193. throw new Error('typeof name === "string"' + " error: " + (undefined || "unknown"));
  194. }
  195. return this.funcsOffsetByIdentifier[name];
  196. }
  197. /**
  198. * Labels
  199. */
  200. }, {
  201. key: "addLabel",
  202. value: function addLabel(result) {
  203. this.labels.unshift(result);
  204. }
  205. }, {
  206. key: "hasLabel",
  207. value: function hasLabel(index) {
  208. return this.labels.length > index && index >= 0;
  209. }
  210. }, {
  211. key: "getLabel",
  212. value: function getLabel(index) {
  213. return this.labels[index];
  214. }
  215. }, {
  216. key: "popLabel",
  217. value: function popLabel() {
  218. this.labels.shift();
  219. }
  220. /**
  221. * Locals
  222. */
  223. }, {
  224. key: "hasLocal",
  225. value: function hasLocal(index) {
  226. return typeof this.getLocal(index) !== "undefined";
  227. }
  228. }, {
  229. key: "getLocal",
  230. value: function getLocal(index) {
  231. return this.locals[index];
  232. }
  233. }, {
  234. key: "addLocal",
  235. value: function addLocal(type) {
  236. this.locals.push(type);
  237. }
  238. /**
  239. * Types
  240. */
  241. }, {
  242. key: "addType",
  243. value: function addType(type) {
  244. if (!(type.functype.type === "Signature")) {
  245. throw new Error('type.functype.type === "Signature"' + " error: " + (undefined || "unknown"));
  246. }
  247. this.types.push(type.functype);
  248. }
  249. }, {
  250. key: "hasType",
  251. value: function hasType(index) {
  252. return this.types[index] !== undefined;
  253. }
  254. }, {
  255. key: "getType",
  256. value: function getType(index) {
  257. return this.types[index];
  258. }
  259. /**
  260. * Globals
  261. */
  262. }, {
  263. key: "hasGlobal",
  264. value: function hasGlobal(index) {
  265. return this.globals.length > index && index >= 0;
  266. }
  267. }, {
  268. key: "getGlobal",
  269. value: function getGlobal(index) {
  270. return this.globals[index].type;
  271. }
  272. }, {
  273. key: "getGlobalOffsetByIdentifier",
  274. value: function getGlobalOffsetByIdentifier(name) {
  275. if (!(typeof name === "string")) {
  276. throw new Error('typeof name === "string"' + " error: " + (undefined || "unknown"));
  277. }
  278. // $FlowIgnore
  279. return this.globalsOffsetByIdentifier[name];
  280. }
  281. }, {
  282. key: "defineGlobal",
  283. value: function defineGlobal(global) {
  284. var type = global.globalType.valtype;
  285. var mutability = global.globalType.mutability;
  286. this.globals.push({
  287. type: type,
  288. mutability: mutability
  289. });
  290. if (typeof global.name !== "undefined") {
  291. // $FlowIgnore
  292. this.globalsOffsetByIdentifier[global.name.value] = this.globals.length - 1;
  293. }
  294. }
  295. }, {
  296. key: "importGlobal",
  297. value: function importGlobal(type, mutability) {
  298. this.globals.push({
  299. type: type,
  300. mutability: mutability
  301. });
  302. }
  303. }, {
  304. key: "isMutableGlobal",
  305. value: function isMutableGlobal(index) {
  306. return this.globals[index].mutability === "var";
  307. }
  308. }, {
  309. key: "isImmutableGlobal",
  310. value: function isImmutableGlobal(index) {
  311. return this.globals[index].mutability === "const";
  312. }
  313. /**
  314. * Memories
  315. */
  316. }, {
  317. key: "hasMemory",
  318. value: function hasMemory(index) {
  319. return this.mems.length > index && index >= 0;
  320. }
  321. }, {
  322. key: "addMemory",
  323. value: function addMemory(min, max) {
  324. this.mems.push({
  325. min: min,
  326. max: max
  327. });
  328. }
  329. }, {
  330. key: "getMemory",
  331. value: function getMemory(index) {
  332. return this.mems[index];
  333. }
  334. }]);
  335. return ModuleContext;
  336. }();