index.js 9.6 KB

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