# 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
    27x
    27x
    27x
    27x
    27x

    27x
    153x
    153x
    153x

    27x

    195x

    195x

    3938x

    3938x
    1x
    1x

    3938x
    2818x
    2818x

    2818x
    420x
    420x

    2398x

    4x
    4x
    4x

    24x
    24x
    24x

    1013x
    1013x
    1013x

    9x
    9x
    9x

    1348x

    2818x

    195x
    195x

    195x
    195x

    195x
    195x
    195x

    27x

    69x
    69x
    195x

    69x

     // @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;