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