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