Example #1
0
    function parseCallIndirect() {
      var typeRef;
      var params = [];
      var results = [];
      var instrs = [];

      while (token.type !== tokens.closeParen) {
        if (lookaheadAndCheck(tokens.openParen, keywords.type)) {
          eatToken(); // (

          eatToken(); // type

          typeRef = parseTypeReference();
        } else if (lookaheadAndCheck(tokens.openParen, keywords.param)) {
          eatToken(); // (

          eatToken(); // param

          /**
           * Params can be empty:
           * (params)`
           */

          if (token.type !== tokens.closeParen) {
            params.push.apply(params, _toConsumableArray(parseFuncParam()));
          }
        } else if (lookaheadAndCheck(tokens.openParen, keywords.result)) {
          eatToken(); // (

          eatToken(); // result

          /**
           * Results can be empty:
           * (result)`
           */

          if (token.type !== tokens.closeParen) {
            results.push.apply(results, _toConsumableArray(parseFuncResult()));
          }
        } else {
          eatTokenOfType(tokens.openParen);
          instrs.push(parseFuncInstr());
        }

        eatTokenOfType(tokens.closeParen);
      }

      if (typeRef !== undefined) {
        return t.callIndirectInstructionWithTypeRef(typeRef, instrs);
      } else {
        return t.callIndirectInstruction(params, results, instrs);
      }
    }
  function parseInstructionBlock(code) {
    while (true) {
      var startLoc = getPosition();
      var instructionAlreadyCreated = false;
      var instructionByte = readByte();
      eatBytes(1);

      if (instructionByte === 0xfe) {
        throw new _helperApiError.CompileError("Atomic instructions are not implemented");
      }

      var instruction = symbolsByByte[instructionByte];

      if (typeof instruction === "undefined") {
        throw new _helperApiError.CompileError("Unexpected instruction: " + toHex(instructionByte));
      }

      if (typeof instruction.object === "string") {
        dump([instructionByte], "".concat(instruction.object, ".").concat(instruction.name));
      } else {
        dump([instructionByte], instruction.name);
      }
      /**
       * End of the function
       */


      if (instruction.name === "end") {
        break;
      }

      var args = [];

      if (instruction.name === "loop") {
        var blocktypeByte = readByte();
        eatBytes(1);
        var blocktype = blockTypes[blocktypeByte];
        dump([blocktypeByte], "blocktype");

        if (typeof blocktype === "undefined") {
          throw new _helperApiError.CompileError("Unexpected blocktype: " + toHex(blocktypeByte));
        }

        var instr = [];
        parseInstructionBlock(instr); // preserve anonymous

        var label = t.withRaw(t.identifier(getUniqueName("loop")), "");
        var loopNode = t.loopInstruction(label, blocktype, instr);
        code.push(loopNode);
        instructionAlreadyCreated = true;
      } else if (instruction.name === "if") {
        var _blocktypeByte = readByte();

        eatBytes(1);
        var _blocktype = blockTypes[_blocktypeByte];
        dump([_blocktypeByte], "blocktype");

        if (typeof _blocktype === "undefined") {
          throw new _helperApiError.CompileError("Unexpected blocktype: " + toHex(_blocktypeByte));
        }

        var testIndex = t.withRaw(t.identifier(getUniqueName("if")), "");
        var ifBody = [];
        parseInstructionBlock(ifBody); // Defaults to no alternate

        var elseIndex = 0;

        for (elseIndex = 0; elseIndex < ifBody.length; ++elseIndex) {
          var _instr = ifBody[elseIndex];

          if (_instr.type === "Instr" && _instr.id === "else") {
            break;
          }
        }

        var consequentInstr = ifBody.slice(0, elseIndex);
        var alternate = ifBody.slice(elseIndex + 1); // wast sugar

        var testInstrs = [];
        var ifNode = t.ifInstruction(testIndex, testInstrs, _blocktype, consequentInstr, alternate);
        code.push(ifNode);
        instructionAlreadyCreated = true;
      } else if (instruction.name === "block") {
        var _blocktypeByte2 = readByte();

        eatBytes(1);
        var _blocktype2 = blockTypes[_blocktypeByte2];
        dump([_blocktypeByte2], "blocktype");

        if (typeof _blocktype2 === "undefined") {
          throw new _helperApiError.CompileError("Unexpected blocktype: " + toHex(_blocktypeByte2));
        }

        var _instr2 = [];
        parseInstructionBlock(_instr2); // preserve anonymous

        var _label = t.withRaw(t.identifier(getUniqueName("block")), "");

        var blockNode = t.blockInstruction(_label, _instr2, _blocktype2);
        code.push(blockNode);
        instructionAlreadyCreated = true;
      } else if (instruction.name === "call") {
        var indexu32 = readU32();
        var index = indexu32.value;
        eatBytes(indexu32.nextIndex);
        dump([index], "index");
        var callNode = t.callInstruction(t.indexLiteral(index));
        code.push(callNode);
        instructionAlreadyCreated = true;
      } else if (instruction.name === "call_indirect") {
        var indexU32 = readU32();
        var typeindex = indexU32.value;
        eatBytes(indexU32.nextIndex);
        dump([typeindex], "type index");
        var signature = state.typesInModule[typeindex];

        if (typeof signature === "undefined") {
          throw new _helperApiError.CompileError("call_indirect signature not found (".concat(typeindex, ")"));
        }

        var _callNode = t.callIndirectInstruction(t.signature(signature.params, signature.result), []);

        var flagU32 = readU32();
        var flag = flagU32.value; // 0x00 - reserved byte

        eatBytes(flagU32.nextIndex);

        if (flag !== 0) {
          throw new _helperApiError.CompileError("zero flag expected");
        }

        code.push(_callNode);
        instructionAlreadyCreated = true;
      } else if (instruction.name === "br_table") {
        var indicesu32 = readU32();
        var indices = indicesu32.value;
        eatBytes(indicesu32.nextIndex);
        dump([indices], "num indices");

        for (var i = 0; i <= indices; i++) {
          var _indexu = readU32();

          var _index = _indexu.value;
          eatBytes(_indexu.nextIndex);
          dump([_index], "index");
          args.push(t.numberLiteralFromRaw(_indexu.value.toString(), "u32"));
        }
      } else if (instructionByte >= 0x28 && instructionByte <= 0x40) {
        /**
         * Memory instructions
         */
        if (instruction.name === "grow_memory" || instruction.name === "current_memory") {
          var _indexU = readU32();

          var _index2 = _indexU.value;
          eatBytes(_indexU.nextIndex);

          if (_index2 !== 0) {
            throw new Error("zero flag expected");
          }

          dump([_index2], "index");
        } else {
          var aligun32 = readU32();
          var align = aligun32.value;
          eatBytes(aligun32.nextIndex);
          dump([align], "align");
          var offsetu32 = readU32();
          var _offset = offsetu32.value;
          eatBytes(offsetu32.nextIndex);
          dump([_offset], "offset");
        }
      } else if (instructionByte >= 0x41 && instructionByte <= 0x44) {
        /**
         * Numeric instructions
         */
        if (instruction.object === "i32") {
          var value32 = read32();
          var value = value32.value;
          eatBytes(value32.nextIndex);
          dump([value], "i32 value");
          args.push(t.numberLiteralFromRaw(value));
        }

        if (instruction.object === "u32") {
          var valueu32 = readU32();
          var _value = valueu32.value;
          eatBytes(valueu32.nextIndex);
          dump([_value], "u32 value");
          args.push(t.numberLiteralFromRaw(_value));
        }

        if (instruction.object === "i64") {
          var value64 = read64();
          var _value2 = value64.value;
          eatBytes(value64.nextIndex);
          dump([Number(_value2.toString())], "i64 value");
          var high = _value2.high,
              low = _value2.low;
          var node = {
            type: "LongNumberLiteral",
            value: {
              high: high,
              low: low
            }
          };
          args.push(node);
        }

        if (instruction.object === "u64") {
          var valueu64 = readU64();
          var _value3 = valueu64.value;
          eatBytes(valueu64.nextIndex);
          dump([Number(_value3.toString())], "u64 value");
          var _high = _value3.high,
              _low = _value3.low;
          var _node = {
            type: "LongNumberLiteral",
            value: {
              high: _high,
              low: _low
            }
          };
          args.push(_node);
        }

        if (instruction.object === "f32") {
          var valuef32 = readF32();
          var _value4 = valuef32.value;
          eatBytes(valuef32.nextIndex);
          dump([_value4], "f32 value");
          args.push( // $FlowIgnore
          t.floatLiteral(_value4, valuef32.nan, valuef32.inf, String(_value4)));
        }

        if (instruction.object === "f64") {
          var valuef64 = readF64();
          var _value5 = valuef64.value;
          eatBytes(valuef64.nextIndex);
          dump([_value5], "f64 value");
          args.push( // $FlowIgnore
          t.floatLiteral(_value5, valuef64.nan, valuef64.inf, String(_value5)));
        }
      } else {
        for (var _i2 = 0; _i2 < instruction.numberOfArgs; _i2++) {
          var u32 = readU32();
          eatBytes(u32.nextIndex);
          dump([u32.value], "argument " + _i2);
          args.push(t.numberLiteralFromRaw(u32.value));
        }
      }

      if (instructionAlreadyCreated === false) {
        if (typeof instruction.object === "string") {
          code.push(t.objectInstruction(instruction.name, instruction.object, args));
        } else {
          var endLoc = getPosition();

          var _node2 = t.withLoc(t.instruction(instruction.name, args), endLoc, startLoc);

          code.push(_node2);
        }
      }
    }
  } // https://webassembly.github.io/spec/core/binary/types.html#limits