index.js 8.4 KB

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