• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1// Copyright 2019 Google LLC
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15export default class Assembler {
16  static get GENERATOR_ID() { return 0; }
17
18  /**
19   * @param {AST} the AST to build the SPIR-V from
20   */
21  constructor(ast) {
22    this.ast_ = ast;
23  }
24
25  /**
26   * Assembles the AST into binary SPIR-V.
27   * @return {Uint32Array} The SPIR-V binary data.
28   */
29  assemble() {
30    let total_size = 5;
31    for (const inst of this.ast_.instructions()) {
32      total_size += 1;
33      for (const op of inst.operands()) {
34        total_size += op.length();
35      }
36    }
37
38    let u = new Uint32Array(total_size);
39    u[0] = 0x07230203;  // Magic
40    u[1] = 0x00010500;  // Version 1.5
41    u[2] = Assembler.GENERATOR_ID;  // Generator magic number
42    u[3] = this.ast_.getIdBounds();  // ID bounds
43    u[4] = 0;  // Reserved
44
45    let idx = 5;
46    for (const inst of this.ast_.instructions()) {
47      let op_size = 1;
48      for (const op of inst.operands()) {
49        op_size += op.length();
50      }
51
52      u[idx++] = op_size << 16 | inst.opcode();
53      for (const op of inst.operands()) {
54        idx = this.processOp(u, idx, op);
55      }
56    }
57
58    return u;
59  }
60
61  processOp(u, idx, op) {
62    if (op.type() === "string") {
63      let len = 0;
64      let v = 0;
65      for (const ch of op.value()) {
66        v = v | (ch.charCodeAt(0) << (len * 8));
67        len += 1;
68
69        if (len === 4) {
70          u[idx++] = v;
71          len = 0;
72          v = 0;
73        }
74      }
75      // Make sure either the terminating 0 byte is written or the last
76      // partial word is written.
77      u[idx++] = v;
78
79    } else if (op.type() === "float") {
80      // TODO(dsinclair): Handle 64 bit floats ...
81      let b = new ArrayBuffer(4);
82      let f = new Float32Array(b);
83      f[0] = op.value();
84
85      let u2 = new Uint32Array(b);
86
87      u[idx++] = u2[0];
88    } else {
89      u[idx++] = op.value();
90    }
91
92    for (const param of op.params()) {
93      idx = this.processOp(u, idx, param);
94    }
95
96    return idx;
97  }
98}
99