You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

388 lines
9.5 KiB

4 years ago
  1. "use strict";
  2. Object.defineProperty(exports, "__esModule", {
  3. value: true
  4. });
  5. exports.moduleContextFromModuleAST = moduleContextFromModuleAST;
  6. exports.ModuleContext = void 0;
  7. var _ast = require("@webassemblyjs/ast");
  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 =
  79. /*#__PURE__*/
  80. function () {
  81. function ModuleContext() {
  82. _classCallCheck(this, ModuleContext);
  83. this.funcs = [];
  84. this.funcsOffsetByIdentifier = [];
  85. this.types = [];
  86. this.globals = [];
  87. this.globalsOffsetByIdentifier = [];
  88. this.mems = []; // Current stack frame
  89. this.locals = [];
  90. this.labels = [];
  91. this.return = [];
  92. this.debugName = "unknown";
  93. this.start = null;
  94. }
  95. /**
  96. * Set start segment
  97. */
  98. _createClass(ModuleContext, [{
  99. key: "setStart",
  100. value: function setStart(index) {
  101. this.start = index.value;
  102. }
  103. /**
  104. * Get start function
  105. */
  106. }, {
  107. key: "getStart",
  108. value: function getStart() {
  109. return this.start;
  110. }
  111. /**
  112. * Reset the active stack frame
  113. */
  114. }, {
  115. key: "newContext",
  116. value: function newContext(debugName, expectedResult) {
  117. this.locals = [];
  118. this.labels = [expectedResult];
  119. this.return = expectedResult;
  120. this.debugName = debugName;
  121. }
  122. /**
  123. * Functions
  124. */
  125. }, {
  126. key: "addFunction",
  127. value: function addFunction(func
  128. /*: Func*/
  129. ) {
  130. // eslint-disable-next-line prefer-const
  131. var _ref = func.signature || {},
  132. _ref$params = _ref.params,
  133. args = _ref$params === void 0 ? [] : _ref$params,
  134. _ref$results = _ref.results,
  135. result = _ref$results === void 0 ? [] : _ref$results;
  136. args = args.map(function (arg) {
  137. return arg.valtype;
  138. });
  139. this.funcs.push({
  140. args: args,
  141. result: result
  142. });
  143. if (typeof func.name !== "undefined") {
  144. this.funcsOffsetByIdentifier[func.name.value] = this.funcs.length - 1;
  145. }
  146. }
  147. }, {
  148. key: "importFunction",
  149. value: function importFunction(funcimport) {
  150. if ((0, _ast.isSignature)(funcimport.signature)) {
  151. // eslint-disable-next-line prefer-const
  152. var _funcimport$signature = funcimport.signature,
  153. args = _funcimport$signature.params,
  154. result = _funcimport$signature.results;
  155. args = args.map(function (arg) {
  156. return arg.valtype;
  157. });
  158. this.funcs.push({
  159. args: args,
  160. result: result
  161. });
  162. } else {
  163. if (!(0, _ast.isNumberLiteral)(funcimport.signature)) {
  164. throw new Error('isNumberLiteral(funcimport.signature)' + " error: " + (undefined || "unknown"));
  165. }
  166. var typeId = funcimport.signature.value;
  167. if (!this.hasType(typeId)) {
  168. throw new Error('this.hasType(typeId)' + " error: " + (undefined || "unknown"));
  169. }
  170. var signature = this.getType(typeId);
  171. this.funcs.push({
  172. args: signature.params.map(function (arg) {
  173. return arg.valtype;
  174. }),
  175. result: signature.results
  176. });
  177. }
  178. if (typeof funcimport.id !== "undefined") {
  179. // imports are first, we can assume their index in the array
  180. this.funcsOffsetByIdentifier[funcimport.id.value] = this.funcs.length - 1;
  181. }
  182. }
  183. }, {
  184. key: "hasFunction",
  185. value: function hasFunction(index) {
  186. return typeof this.getFunction(index) !== "undefined";
  187. }
  188. }, {
  189. key: "getFunction",
  190. value: function getFunction(index) {
  191. if (typeof index !== "number") {
  192. throw new Error("getFunction only supported for number index");
  193. }
  194. return this.funcs[index];
  195. }
  196. }, {
  197. key: "getFunctionOffsetByIdentifier",
  198. value: function getFunctionOffsetByIdentifier(name) {
  199. if (!(typeof name === "string")) {
  200. throw new Error('typeof name === "string"' + " error: " + (undefined || "unknown"));
  201. }
  202. return this.funcsOffsetByIdentifier[name];
  203. }
  204. /**
  205. * Labels
  206. */
  207. }, {
  208. key: "addLabel",
  209. value: function addLabel(result) {
  210. this.labels.unshift(result);
  211. }
  212. }, {
  213. key: "hasLabel",
  214. value: function hasLabel(index) {
  215. return this.labels.length > index && index >= 0;
  216. }
  217. }, {
  218. key: "getLabel",
  219. value: function getLabel(index) {
  220. return this.labels[index];
  221. }
  222. }, {
  223. key: "popLabel",
  224. value: function popLabel() {
  225. this.labels.shift();
  226. }
  227. /**
  228. * Locals
  229. */
  230. }, {
  231. key: "hasLocal",
  232. value: function hasLocal(index) {
  233. return typeof this.getLocal(index) !== "undefined";
  234. }
  235. }, {
  236. key: "getLocal",
  237. value: function getLocal(index) {
  238. return this.locals[index];
  239. }
  240. }, {
  241. key: "addLocal",
  242. value: function addLocal(type) {
  243. this.locals.push(type);
  244. }
  245. /**
  246. * Types
  247. */
  248. }, {
  249. key: "addType",
  250. value: function addType(type) {
  251. if (!(type.functype.type === "Signature")) {
  252. throw new Error('type.functype.type === "Signature"' + " error: " + (undefined || "unknown"));
  253. }
  254. this.types.push(type.functype);
  255. }
  256. }, {
  257. key: "hasType",
  258. value: function hasType(index) {
  259. return this.types[index] !== undefined;
  260. }
  261. }, {
  262. key: "getType",
  263. value: function getType(index) {
  264. return this.types[index];
  265. }
  266. /**
  267. * Globals
  268. */
  269. }, {
  270. key: "hasGlobal",
  271. value: function hasGlobal(index) {
  272. return this.globals.length > index && index >= 0;
  273. }
  274. }, {
  275. key: "getGlobal",
  276. value: function getGlobal(index) {
  277. return this.globals[index].type;
  278. }
  279. }, {
  280. key: "getGlobalOffsetByIdentifier",
  281. value: function getGlobalOffsetByIdentifier(name) {
  282. if (!(typeof name === "string")) {
  283. throw new Error('typeof name === "string"' + " error: " + (undefined || "unknown"));
  284. }
  285. return this.globalsOffsetByIdentifier[name];
  286. }
  287. }, {
  288. key: "defineGlobal",
  289. value: function defineGlobal(global
  290. /*: Global*/
  291. ) {
  292. var type = global.globalType.valtype;
  293. var mutability = global.globalType.mutability;
  294. this.globals.push({
  295. type: type,
  296. mutability: mutability
  297. });
  298. if (typeof global.name !== "undefined") {
  299. this.globalsOffsetByIdentifier[global.name.value] = this.globals.length - 1;
  300. }
  301. }
  302. }, {
  303. key: "importGlobal",
  304. value: function importGlobal(type, mutability) {
  305. this.globals.push({
  306. type: type,
  307. mutability: mutability
  308. });
  309. }
  310. }, {
  311. key: "isMutableGlobal",
  312. value: function isMutableGlobal(index) {
  313. return this.globals[index].mutability === "var";
  314. }
  315. }, {
  316. key: "isImmutableGlobal",
  317. value: function isImmutableGlobal(index) {
  318. return this.globals[index].mutability === "const";
  319. }
  320. /**
  321. * Memories
  322. */
  323. }, {
  324. key: "hasMemory",
  325. value: function hasMemory(index) {
  326. return this.mems.length > index && index >= 0;
  327. }
  328. }, {
  329. key: "addMemory",
  330. value: function addMemory(min, max) {
  331. this.mems.push({
  332. min: min,
  333. max: max
  334. });
  335. }
  336. }, {
  337. key: "getMemory",
  338. value: function getMemory(index) {
  339. return this.mems[index];
  340. }
  341. }]);
  342. return ModuleContext;
  343. }();
  344. exports.ModuleContext = ModuleContext;