# All files / src/emitter/section code.js

100% Statements 51/51
93.33% Branches 14/15
100% Functions 7/7
100% Lines 49/49

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    23x
    23x
    23x
    23x
    23x

    23x
    116x
    116x
    116x

    23x

    150x

    150x

    2435x

    2435x
    1x
    1x

    2435x
    1774x
    1774x

    1774x
    246x
    246x

    1528x

    4x
    4x
    4x

    24x
    24x
    24x

    665x
    665x
    665x

    9x
    9x
    9x

    826x

    1774x

    150x
    150x

    150x
    150x

    150x
    150x
    150x

    23x

    60x
    60x
    150x

    60x

     // @flow
    import { u8, i32, f32, f64, i64 } from "wasm-types";
    import { varint32, varuint32, varint7, varint64 } from "../numbers";
    import { getTypeString } from "../value_type";
    import OutputStream from "../../utils/output-stream";
    import opcode from "../opcode";

    const emitLocal = (stream, local) => {
      Eif (local.isParam == null) {
        stream.push(varuint32, 1, "number of locals of following type");
        stream.push(varint7, local.type, `${getTypeString(local.type)}`);
      }
    };

    const emitFunctionBody = (stream, { locals, code, debug: functionName }) => {
      // write bytecode into a clean buffer
      const body = new OutputStream();

      code.forEach(({ kind, params, valueType, debug }) => {
        // There is a much nicer way of doing this
        body.push(u8, kind.code, `${kind.text}  ${debug ? debug : ""}`);

        if (valueType) {
          body.push(u8, valueType.type, "result type");
          body.push(u8, valueType.mutable, "mutable");
        }

        // map over all params, if any and encode each on
        params.forEach(p => {
          let type = varuint32;
          let stringType = "i32.literal";

          // Memory opcode?
          if (kind.code >= 0x28 && kind.code <= 0x3e) {
            type = varuint32;
            stringType = "memory_immediate";
          } else {
            // either encode unsigned 32 bit values or floats
            switch (kind.result) {
              case f64:
                type = f64;
                stringType = "f64.literal";
                break;
              case f32:
                type = f32;
                stringType = "f32.literal";
                break;
              case i32:
                type = varint32;
                stringType = "i32.literal";
                break;
              case i64:
                type = varint64;
                stringType = "i64.literal";
                break;
              default:
                type = varuint32;
            }
          }
          body.push(type, p, `${stringType}`);
        });
      });

      // output locals to the stream
      const localsStream = new OutputStream();
      locals.forEach(local => emitLocal(localsStream, local));

      // body size is
      stream.push(varuint32, body.size + localsStream.size + 2, functionName);
      stream.push(varuint32, locals.length, "locals count");

      stream.write(localsStream);
      stream.write(body);
      stream.push(u8, opcode.End.code, "end");
    };

    const emit = (functions: any[]) => {
      // do stuff with ast
      const stream = new OutputStream();
      stream.push(varuint32, functions.length, "function count");
      functions.forEach(func => emitFunctionBody(stream, func));

      return stream;
    };

    export default emit;