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

    23x

    159x

    159x

    2574x

    2574x
    1x
    1x

    2574x
    1844x
    1844x

    1844x
    244x
    244x

    1600x

    4x
    4x
    4x

    24x
    24x
    24x

    693x
    693x
    693x

    9x
    9x
    9x

    870x

    1844x

    159x
    159x

    159x
    159x

    159x
    159x
    159x

    23x

    63x
    63x
    159x

    63x

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