// Copyright 2019 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. import { assert } from "chai"; import Lexer from "./lexer"; import Parser from "./parser"; import grammar from "./spirv.data.js"; import Assembler from "./assembler"; describe("assembler", () => { it("generates SPIR-V magic number", () => { let input = `; SPIR-V ; Version: 1.0 ; Generator: Khronos Glslang Reference Front End; 7 ; Bound: 6 ; Schema: 0 OpCapability Shader %1 = OpExtInstImport "GLSL.std.450" OpMemoryModel Logical GLSL450 OpEntryPoint Fragment %main "main" OpExecutionMode %main OriginUpperLeft OpSource GLSL 440 OpName %main "main" %void = OpTypeVoid %3 = OpTypeFunction %void %main = OpFunction %void None %3 %5 = OpLabel OpReturn OpFunctionEnd`; let l = new Lexer(input); let p = new Parser(grammar, l); let ast = p.parse(); assert.exists(ast, p.error); let a = new Assembler(ast); let res = a.assemble(); assert.equal(res[0], 0x07230203); }); it("assembles enumerant params", () => { let input = "OpExecutionMode %main LocalSize 2 3 4"; let l = new Lexer(input); let p = new Parser(grammar, l); let ast = p.parse(); assert.exists(ast, p.error); let a = new Assembler(ast); let res = a.assemble(); assert.lengthOf(res, 11); assert.equal(res[5], (6 /* word count */ << 16) | 16 /* opcode */); assert.equal(res[6], 1 /* %main */); assert.equal(res[7], 17 /* LocalSize */); assert.equal(res[8], 2); assert.equal(res[9], 3); assert.equal(res[10], 4); }); it("assembles float 32 values", () => { let input = `%float = OpTypeFloat 32 %float1 = OpConstant %float 0.400000006`; let l = new Lexer(input); let p = new Parser(grammar, l); let ast = p.parse(); assert.exists(ast, p.error); let a = new Assembler(ast); let res = a.assemble(); assert.lengthOf(res, 12); assert.equal(res[8], (4 /* word count */ << 16) | 43 /* opcode */); assert.equal(res[9], 1 /* %float */); assert.equal(res[10], 2 /* %float */); assert.equal(res[11], 0x3ecccccd /* 0.400000006 */); }); describe("strings", () => { it("assembles 'abcd'", () => { let input = `OpName %mains "abcd"`; let l = new Lexer(input); let p = new Parser(grammar, l); let ast = p.parse(); assert.exists(ast, p.error); let a = new Assembler(ast); let res = a.assemble(); assert.lengthOf(res, 9); assert.equal(res[5], (4 /* word count */ << 16) | 5 /* opcode */); assert.equal(res[6], 1 /* %mains */); assert.equal(res[7], 0x64636261 /* food */); assert.equal(res[8], 0x00000000 /* null byte */); }); it("assembles 'abcde'", () => { let input = `OpName %mains "abcde"`; let l = new Lexer(input); let p = new Parser(grammar, l); let ast = p.parse(); assert.exists(ast, p.error); let a = new Assembler(ast); let res = a.assemble(); assert.lengthOf(res, 9); assert.equal(res[5], (4 /* word count */ << 16) | 5 /* opcode */); assert.equal(res[6], 1 /* %mains */); assert.equal(res[7], 0x64636261 /* abcd */); assert.equal(res[8], 0x00000065 /* e */); }); it("assembles 'abcdef'", () => { let input = `OpName %mains "abcdef"`; let l = new Lexer(input); let p = new Parser(grammar, l); let ast = p.parse(); assert.exists(ast, p.error); let a = new Assembler(ast); let res = a.assemble(); assert.lengthOf(res, 9); assert.equal(res[5], (4 /* word count */ << 16) | 5 /* opcode */); assert.equal(res[6], 1 /* %mains */); assert.equal(res[7], 0x64636261 /* abcd */); assert.equal(res[8], 0x00006665 /* ef */); }); it("assembles 'abcdefg'", () => { let input = `OpName %mains "abcdefg"`; let l = new Lexer(input); let p = new Parser(grammar, l); let ast = p.parse(); assert.exists(ast, p.error); let a = new Assembler(ast); let res = a.assemble(); assert.lengthOf(res, 9); assert.equal(res[5], (4 /* word count */ << 16) | 5 /* opcode */); assert.equal(res[6], 1 /* %mains */); assert.equal(res[7], 0x64636261 /* abcd */); assert.equal(res[8], 0x00676665 /* efg */); }); }); });