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

96.23% Statements 51/53
83.33% Branches 15/18
100% Functions 7/7
96.08% Lines 49/51

    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
    88
    89
    90
    21x
    21x
    21x
    21x
    21x

    21x
    83x
    83x
    83x

    21x

    131x

    131x

    1658x

    1658x
    1x
    1x

    1658x
    1065x
    1065x

    1065x
    112x
    112x

    953x

    4x
    4x
    4x

    14x
    14x
    14x

    423x
    423x
    423x

    9x
    9x
    9x

    503x

    1065x

    131x
    131x

    131x
    131x

    131x
    131x
    131x

    21x

    64x
    64x
    131x

    64x

     // @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 one
        (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 u8:
                type = u8;
                break;
              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;