| // 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 */); | |
| }); | |
| }); | |
| }); |