├── .travis.yml ├── Cargo.toml ├── README.md ├── LICENSE └── src ├── main.rs └── hir.rs /.travis.yml: -------------------------------------------------------------------------------- 1 | language: rust 2 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "glsl-to-spirv" 3 | version = "0.1.0" 4 | authors = ["Jeff Muizelaar "] 5 | edition = "2018" 6 | 7 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 8 | 9 | [dependencies] 10 | glsl = "3.0" 11 | rspirv = "0.5.4" 12 | spirv_headers = "1.3.4" 13 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | This is a really messy exploration into compiling GLSL to SPIRV. 2 | 3 | It currently only supports compiling programs of the form: 4 | ```glsl 5 | void main() 6 | { 7 | float x = 0.1; 8 | x = x + 0.1; 9 | gl_FragColor = vec4(x, 0.4, 0.8, 1.0); 10 | } 11 | ``` 12 | 13 | The overall approach is to parse the glsl using https://github.com/phaazon/glsl, 14 | convert it to higher level 'hir' representation that does some rudimentary type 15 | checking and manages a symbol table. We then walk over the 'hir' representation 16 | and build the SPIRV. The translator is currently intermingled with a pretty printer 17 | because of another project that I'm working on but the intent is for that code 18 | to go away. 19 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | BSD 3-Clause License 2 | 3 | Copyright (c) 2019, Jeff Muizelaar 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions are met: 8 | 9 | 1. Redistributions of source code must retain the above copyright notice, this 10 | list of conditions and the following disclaimer. 11 | 12 | 2. Redistributions in binary form must reproduce the above copyright notice, 13 | this list of conditions and the following disclaimer in the documentation 14 | and/or other materials provided with the distribution. 15 | 16 | 3. Neither the name of the copyright holder nor the names of its 17 | contributors may be used to endorse or promote products derived from 18 | this software without specific prior written permission. 19 | 20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 21 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 23 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 24 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 26 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 27 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 28 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | -------------------------------------------------------------------------------- /src/main.rs: -------------------------------------------------------------------------------- 1 | extern crate glsl; 2 | 3 | extern crate rspirv; 4 | extern crate spirv_headers as spirv; 5 | 6 | use rspirv::binary::Assemble; 7 | use rspirv::binary::Disassemble; 8 | 9 | use glsl::parser::Parse; 10 | use glsl::syntax::TranslationUnit; 11 | use rspirv::mr::{Builder, Operand}; 12 | use spirv::Word; 13 | use std::collections::HashMap; 14 | 15 | mod hir; 16 | 17 | use hir::State; 18 | use hir::Type; 19 | 20 | use std::io::Write as IoWrite; 21 | 22 | pub fn glsl_to_spirv(input: &str) -> String { 23 | let ast = TranslationUnit::parse(input).unwrap(); 24 | let mut state = hir::State::new(); 25 | let hir = hir::ast_to_hir(&mut state, &ast); 26 | let mut b = rspirv::mr::Builder::new(); 27 | b.capability(spirv::Capability::Shader); 28 | b.memory_model(spirv::AddressingModel::Logical, spirv::MemoryModel::GLSL450); 29 | 30 | 31 | let mut state = OutputState { 32 | hir: state, 33 | model: spirv::ExecutionModel::Fragment, 34 | return_type: None, 35 | return_declared: false, 36 | builder: b, 37 | emitted_types: HashMap::new(), 38 | emitted_syms: HashMap::new(), 39 | }; 40 | 41 | translate_translation_unit(&mut state, &hir); 42 | 43 | let b = state.builder; 44 | 45 | let module = b.module(); 46 | 47 | // Assembling 48 | let code = module.assemble(); 49 | assert!(code.len() > 20); // Module header contains 5 words 50 | assert_eq!(spirv::MAGIC_NUMBER, code[0]); 51 | 52 | // Parsing 53 | let mut loader = rspirv::mr::Loader::new(); 54 | rspirv::binary::parse_words(&code, &mut loader).unwrap(); 55 | let module = loader.module(); 56 | 57 | // Disassembling 58 | module.disassemble() 59 | } 60 | 61 | fn main() { 62 | let r = TranslationUnit::parse("layout(location = 0) out vec4 outColor; 63 | 64 | void main() { 65 | outColor = vec4(1.0, 0.0, 0.0, 1.0); 66 | }"); 67 | 68 | /*void main() { 69 | vec3 p = vec3(0, 1, 4); 70 | float x = 1. * .5 + p.r; 71 | }"); 72 | 73 | */ 74 | let r = r.unwrap(); 75 | println!("{:?}", r); 76 | 77 | let mut state = hir::State::new(); 78 | //println!("{:#?}", r); 79 | let hir = hir::ast_to_hir(&mut state, &r); 80 | //println!("{:#?}", hir); 81 | // Building 82 | let mut b = rspirv::mr::Builder::new(); 83 | b.capability(spirv::Capability::Shader); 84 | b.memory_model(spirv::AddressingModel::Logical, spirv::MemoryModel::GLSL450); 85 | 86 | 87 | let mut state = OutputState { 88 | hir: state, 89 | model: spirv::ExecutionModel::Fragment, 90 | return_type: None, 91 | return_declared: false, 92 | builder: b, 93 | emitted_types: HashMap::new(), 94 | emitted_syms: HashMap::new(), 95 | }; 96 | 97 | translate_translation_unit(&mut state, &hir); 98 | 99 | let b = state.builder; 100 | 101 | let module = b.module(); 102 | 103 | // Assembling 104 | let code = module.assemble(); 105 | assert!(code.len() > 20); // Module header contains 5 words 106 | assert_eq!(spirv::MAGIC_NUMBER, code[0]); 107 | let mut f = std::fs::File::create("out.frag").unwrap(); 108 | let len = code[..].len() * 4; 109 | let buf = unsafe { std::slice::from_raw_parts(code[..].as_ptr() as *const u8, len) }; 110 | f.write(buf); 111 | 112 | // Parsing 113 | let mut loader = rspirv::mr::Loader::new(); 114 | rspirv::binary::parse_words(&code, &mut loader).unwrap(); 115 | let module = loader.module(); 116 | 117 | // Disassembling 118 | println!("{}", module.disassemble()); 119 | } 120 | 121 | pub struct Variable { 122 | location: Word, 123 | ty: Word, 124 | } 125 | 126 | pub struct OutputState { 127 | builder: rspirv::mr::Builder, 128 | model: spirv::ExecutionModel, 129 | hir: hir::State, 130 | return_type: Option>, 131 | return_declared: bool, 132 | //XXX: we can probably hash on something better than String 133 | emitted_types: HashMap, 134 | emitted_syms: HashMap, 135 | } 136 | 137 | use std::fmt::Write; 138 | 139 | use glsl::syntax; 140 | 141 | pub fn show_identifier(f: &mut F, i: &syntax::Identifier) where F: Write { 142 | let _ = f.write_str(&i.0); 143 | } 144 | 145 | pub fn show_sym(f: &mut F, state: &mut OutputState, i: &hir::SymRef) where F: Write { 146 | let sym = state.hir.sym(*i); 147 | let _ = f.write_str(&sym.name); 148 | } 149 | 150 | pub fn show_type_name(f: &mut F, t: &syntax::TypeName) where F: Write { 151 | let _ = f.write_str(&t.0); 152 | } 153 | 154 | pub fn show_type_kind(f: &mut F, state: &mut OutputState, t: &hir::TypeKind) where F: Write { 155 | match *t { 156 | hir::TypeKind::Void => { let _ = f.write_str("void"); } 157 | hir::TypeKind::Bool => { let _ = f.write_str("bool"); } 158 | hir::TypeKind::Int => { let _ = f.write_str("int"); } 159 | hir::TypeKind::UInt => { let _ = f.write_str("uint"); } 160 | hir::TypeKind::Float => { let _ = f.write_str("float"); } 161 | hir::TypeKind::Double => { let _ = f.write_str("double"); } 162 | hir::TypeKind::Vec2 => { let _ = f.write_str("vec2"); } 163 | hir::TypeKind::Vec3 => { let _ = f.write_str("vec3"); } 164 | hir::TypeKind::Vec4 => { let _ = f.write_str("vec4"); } 165 | hir::TypeKind::DVec2 => { let _ = f.write_str("dvec2"); } 166 | hir::TypeKind::DVec3 => { let _ = f.write_str("dvec3"); } 167 | hir::TypeKind::DVec4 => { let _ = f.write_str("dvec4"); } 168 | hir::TypeKind::BVec2 => { let _ = f.write_str("bvec2"); } 169 | hir::TypeKind::BVec3 => { let _ = f.write_str("bvec3"); } 170 | hir::TypeKind::BVec4 => { let _ = f.write_str("bvec4"); } 171 | hir::TypeKind::IVec2 => { let _ = f.write_str("ivec2"); } 172 | hir::TypeKind::IVec3 => { let _ = f.write_str("ivec3"); } 173 | hir::TypeKind::IVec4 => { let _ = f.write_str("ivec4"); } 174 | hir::TypeKind::UVec2 => { let _ = f.write_str("uvec2"); } 175 | hir::TypeKind::UVec3 => { let _ = f.write_str("uvec3"); } 176 | hir::TypeKind::UVec4 => { let _ = f.write_str("uvec4"); } 177 | hir::TypeKind::Mat2 => { let _ = f.write_str("mat2"); } 178 | hir::TypeKind::Mat3 => { let _ = f.write_str("mat3"); } 179 | hir::TypeKind::Mat4 => { let _ = f.write_str("mat4"); } 180 | hir::TypeKind::Mat23 => { let _ = f.write_str("mat23"); } 181 | hir::TypeKind::Mat24 => { let _ = f.write_str("mat24"); } 182 | hir::TypeKind::Mat32 => { let _ = f.write_str("mat32"); } 183 | hir::TypeKind::Mat34 => { let _ = f.write_str("mat34"); } 184 | hir::TypeKind::Mat42 => { let _ = f.write_str("mat42"); } 185 | hir::TypeKind::Mat43 => { let _ = f.write_str("mat43"); } 186 | hir::TypeKind::DMat2 => { let _ = f.write_str("dmat2"); } 187 | hir::TypeKind::DMat3 => { let _ = f.write_str("dmat3"); } 188 | hir::TypeKind::DMat4 => { let _ = f.write_str("dmat4"); } 189 | hir::TypeKind::DMat23 => { let _ = f.write_str("dmat23"); } 190 | hir::TypeKind::DMat24 => { let _ = f.write_str("dmat24"); } 191 | hir::TypeKind::DMat32 => { let _ = f.write_str("dmat32"); } 192 | hir::TypeKind::DMat34 => { let _ = f.write_str("dmat34"); } 193 | hir::TypeKind::DMat42 => { let _ = f.write_str("dmat42"); } 194 | hir::TypeKind::DMat43 => { let _ = f.write_str("dmat43"); } 195 | hir::TypeKind::Sampler1D => { let _ = f.write_str("sampler1D"); } 196 | hir::TypeKind::Image1D => { let _ = f.write_str("image1D"); } 197 | hir::TypeKind::Sampler2D => { let _ = f.write_str("sampler2D"); } 198 | hir::TypeKind::Image2D => { let _ = f.write_str("image2D"); } 199 | hir::TypeKind::Sampler3D => { let _ = f.write_str("sampler3D"); } 200 | hir::TypeKind::Image3D => { let _ = f.write_str("image3D"); } 201 | hir::TypeKind::SamplerCube => { let _ = f.write_str("samplerCube"); } 202 | hir::TypeKind::ImageCube => { let _ = f.write_str("imageCube"); } 203 | hir::TypeKind::Sampler2DRect => { let _ = f.write_str("sampler2DRect"); } 204 | hir::TypeKind::Image2DRect => { let _ = f.write_str("image2DRect"); } 205 | hir::TypeKind::Sampler1DArray => { let _ = f.write_str("sampler1DArray"); } 206 | hir::TypeKind::Image1DArray => { let _ = f.write_str("image1DArray"); } 207 | hir::TypeKind::Sampler2DArray => { let _ = f.write_str("sampler2DArray"); } 208 | hir::TypeKind::Image2DArray => { let _ = f.write_str("image2DArray"); } 209 | hir::TypeKind::SamplerBuffer => { let _ = f.write_str("samplerBuffer"); } 210 | hir::TypeKind::ImageBuffer => { let _ = f.write_str("imageBuffer"); } 211 | hir::TypeKind::Sampler2DMS => { let _ = f.write_str("sampler2DMS"); } 212 | hir::TypeKind::Image2DMS => { let _ = f.write_str("image2DMS"); } 213 | hir::TypeKind::Sampler2DMSArray => { let _ = f.write_str("sampler2DMSArray"); } 214 | hir::TypeKind::Image2DMSArray => { let _ = f.write_str("image2DMSArray"); } 215 | hir::TypeKind::SamplerCubeArray => { let _ = f.write_str("samplerCubeArray"); } 216 | hir::TypeKind::ImageCubeArray => { let _ = f.write_str("imageCubeArray"); } 217 | hir::TypeKind::Sampler1DShadow => { let _ = f.write_str("sampler1DShadow"); } 218 | hir::TypeKind::Sampler2DShadow => { let _ = f.write_str("sampler2DShadow"); } 219 | hir::TypeKind::Sampler2DRectShadow => { let _ = f.write_str("sampler2DRectShadow"); } 220 | hir::TypeKind::Sampler1DArrayShadow => { let _ = f.write_str("sampler1DArrayShadow"); } 221 | hir::TypeKind::Sampler2DArrayShadow => { let _ = f.write_str("sampler2DArrayShadow"); } 222 | hir::TypeKind::SamplerCubeShadow => { let _ = f.write_str("samplerCubeShadow"); } 223 | hir::TypeKind::SamplerCubeArrayShadow => { let _ = f.write_str("samplerCubeArrayShadow"); } 224 | hir::TypeKind::ISampler1D => { let _ = f.write_str("isampler1D"); } 225 | hir::TypeKind::IImage1D => { let _ = f.write_str("iimage1D"); } 226 | hir::TypeKind::ISampler2D => { let _ = f.write_str("isampler2D"); } 227 | hir::TypeKind::IImage2D => { let _ = f.write_str("iimage2D"); } 228 | hir::TypeKind::ISampler3D => { let _ = f.write_str("isampler3D"); } 229 | hir::TypeKind::IImage3D => { let _ = f.write_str("iimage3D"); } 230 | hir::TypeKind::ISamplerCube => { let _ = f.write_str("isamplerCube"); } 231 | hir::TypeKind::IImageCube => { let _ = f.write_str("iimageCube"); } 232 | hir::TypeKind::ISampler2DRect => { let _ = f.write_str("isampler2DRect"); } 233 | hir::TypeKind::IImage2DRect => { let _ = f.write_str("iimage2DRect"); } 234 | hir::TypeKind::ISampler1DArray => { let _ = f.write_str("isampler1DArray"); } 235 | hir::TypeKind::IImage1DArray => { let _ = f.write_str("iimage1DArray"); } 236 | hir::TypeKind::ISampler2DArray => { let _ = f.write_str("isampler2DArray"); } 237 | hir::TypeKind::IImage2DArray => { let _ = f.write_str("iimage2DArray"); } 238 | hir::TypeKind::ISamplerBuffer => { let _ = f.write_str("isamplerBuffer"); } 239 | hir::TypeKind::IImageBuffer => { let _ = f.write_str("iimageBuffer"); } 240 | hir::TypeKind::ISampler2DMS => { let _ = f.write_str("isampler2MS"); } 241 | hir::TypeKind::IImage2DMS => { let _ = f.write_str("iimage2DMS"); } 242 | hir::TypeKind::ISampler2DMSArray => { let _ = f.write_str("isampler2DMSArray"); } 243 | hir::TypeKind::IImage2DMSArray => { let _ = f.write_str("iimage2DMSArray"); } 244 | hir::TypeKind::ISamplerCubeArray => { let _ = f.write_str("isamplerCubeArray"); } 245 | hir::TypeKind::IImageCubeArray => { let _ = f.write_str("iimageCubeArray"); } 246 | hir::TypeKind::AtomicUInt => { let _ = f.write_str("atomic_uint"); } 247 | hir::TypeKind::USampler1D => { let _ = f.write_str("usampler1D"); } 248 | hir::TypeKind::UImage1D => { let _ = f.write_str("uimage1D"); } 249 | hir::TypeKind::USampler2D => { let _ = f.write_str("usampler2D"); } 250 | hir::TypeKind::UImage2D => { let _ = f.write_str("uimage2D"); } 251 | hir::TypeKind::USampler3D => { let _ = f.write_str("usampler3D"); } 252 | hir::TypeKind::UImage3D => { let _ = f.write_str("uimage3D"); } 253 | hir::TypeKind::USamplerCube => { let _ = f.write_str("usamplerCube"); } 254 | hir::TypeKind::UImageCube => { let _ = f.write_str("uimageCube"); } 255 | hir::TypeKind::USampler2DRect => { let _ = f.write_str("usampler2DRect"); } 256 | hir::TypeKind::UImage2DRect => { let _ = f.write_str("uimage2DRect"); } 257 | hir::TypeKind::USampler1DArray => { let _ = f.write_str("usampler1DArray"); } 258 | hir::TypeKind::UImage1DArray => { let _ = f.write_str("uimage1DArray"); } 259 | hir::TypeKind::USampler2DArray => { let _ = f.write_str("usampler2DArray"); } 260 | hir::TypeKind::UImage2DArray => { let _ = f.write_str("uimage2DArray"); } 261 | hir::TypeKind::USamplerBuffer => { let _ = f.write_str("usamplerBuffer"); } 262 | hir::TypeKind::UImageBuffer => { let _ = f.write_str("uimageBuffer"); } 263 | hir::TypeKind::USampler2DMS => { let _ = f.write_str("usampler2DMS"); } 264 | hir::TypeKind::UImage2DMS => { let _ = f.write_str("uimage2DMS"); } 265 | hir::TypeKind::USampler2DMSArray => { let _ = f.write_str("usamplerDMSArray"); } 266 | hir::TypeKind::UImage2DMSArray => { let _ = f.write_str("uimage2DMSArray"); } 267 | hir::TypeKind::USamplerCubeArray => { let _ = f.write_str("usamplerCubeArray"); } 268 | hir::TypeKind::UImageCubeArray => { let _ = f.write_str("uimageCubeArray"); } 269 | hir::TypeKind::Struct(ref s) => panic!(), 270 | } 271 | } 272 | 273 | pub fn show_type_specifier(f: &mut F, state: &mut OutputState, t: &syntax::TypeSpecifier) where F: Write { 274 | /*show_type_specifier_non_array(f, state, &t.ty); 275 | 276 | if let Some(ref arr_spec) = t.array_specifier { 277 | show_array_spec(f, arr_spec); 278 | }*/ 279 | } 280 | 281 | pub fn show_type(f: &mut F, state: &mut OutputState, t: &Type) where F: Write { 282 | 283 | if let Some(ref precision) = t.precision { 284 | show_precision_qualifier(f, precision); 285 | let _ = f.write_str(" "); 286 | } 287 | 288 | show_type_kind(f, state, &t.kind); 289 | 290 | if let Some(ref arr_spec) = t.array_sizes { 291 | panic!(); 292 | } 293 | } 294 | 295 | pub fn show_struct_non_declaration(f: &mut F, state: &mut OutputState, s: &syntax::StructSpecifier) where F: Write { 296 | let _ = f.write_str("struct "); 297 | 298 | if let Some(ref name) = s.name { 299 | let _ = write!(f, "{} ", name); 300 | } 301 | 302 | let _ = f.write_str("{\n"); 303 | 304 | for field in &s.fields.0 { 305 | show_struct_field(f, state, field); 306 | } 307 | 308 | let _ = f.write_str("}"); 309 | } 310 | 311 | pub fn show_struct(f: &mut F, state: &mut OutputState, s: &syntax::StructSpecifier) where F: Write { 312 | show_struct_non_declaration(f, state, s); 313 | let _ = f.write_str(";\n"); 314 | } 315 | 316 | 317 | pub fn show_struct_field(f: &mut F, state: &mut OutputState, field: &syntax::StructFieldSpecifier) where F: Write { 318 | /*if let Some(ref qual) = field.qualifier { 319 | show_type_qualifier(f, &qual); 320 | let _ = f.write_str(" "); 321 | } 322 | 323 | show_type_specifier(f, state, &field.ty); 324 | let _ = f.write_str(" "); 325 | 326 | // there’s at least one identifier 327 | let mut identifiers = field.identifiers.0.iter(); 328 | let identifier = identifiers.next().unwrap(); 329 | 330 | show_arrayed_identifier(f, identifier); 331 | 332 | // write the rest of the identifiers 333 | for identifier in identifiers { 334 | let _ = f.write_str(", "); 335 | show_arrayed_identifier(f, identifier); 336 | } 337 | 338 | let _ = f.write_str(";\n");*/ 339 | } 340 | 341 | pub fn show_array_sizes(f: &mut F, a: &hir::ArraySizes) where F: Write { 342 | panic!() 343 | /* 344 | match *a { 345 | syntax::ArraySpecifier::Unsized => { let _ = f.write_str("[]"); } 346 | syntax::ArraySpecifier::ExplicitlySized(ref e) => { 347 | let _ = f.write_str("["); 348 | show_expr(f, &e); 349 | let _ = f.write_str("]"); 350 | } 351 | }*/ 352 | } 353 | 354 | pub fn show_arrayed_identifier(f: &mut F, ident: &syntax::Identifier, ty: &hir::Type) where F: Write { 355 | let _ = write!(f, "{}", ident); 356 | 357 | if let Some(ref arr_spec) = ty.array_sizes { 358 | show_array_sizes(f, &arr_spec); 359 | } 360 | } 361 | 362 | pub fn show_type_qualifier(f: &mut F, q: &hir::TypeQualifier) where F: Write { 363 | let mut qualifiers = q.qualifiers.0.iter(); 364 | let first = qualifiers.next().unwrap(); 365 | 366 | show_type_qualifier_spec(f, first); 367 | 368 | for qual_spec in qualifiers { 369 | let _ = f.write_str(" "); 370 | show_type_qualifier_spec(f, qual_spec) 371 | } 372 | } 373 | 374 | pub fn show_type_qualifier_spec(f: &mut F, q: &hir::TypeQualifierSpec) where F: Write { 375 | match *q { 376 | hir::TypeQualifierSpec::Layout(ref l) => show_layout_qualifier(f, &l), 377 | hir::TypeQualifierSpec::Invariant => { let _ = f.write_str("invariant"); }, 378 | hir::TypeQualifierSpec::Precise => { let _ = f.write_str("precise"); } 379 | hir::TypeQualifierSpec::Memory(_) => { panic!() } 380 | hir::TypeQualifierSpec::Parameter(_) => { panic!() } 381 | } 382 | } 383 | 384 | pub fn show_storage_qualifier(f: &mut F, q: &syntax::StorageQualifier) where F: Write { 385 | match *q { 386 | syntax::StorageQualifier::Const => { let _ = f.write_str("const"); } 387 | syntax::StorageQualifier::InOut => { let _ = f.write_str("inout"); } 388 | syntax::StorageQualifier::In => { let _ = f.write_str("in"); } 389 | syntax::StorageQualifier::Out => { let _ = f.write_str("out"); } 390 | syntax::StorageQualifier::Centroid => { let _ = f.write_str("centroid"); } 391 | syntax::StorageQualifier::Patch => { let _ = f.write_str("patch"); } 392 | syntax::StorageQualifier::Sample => { let _ = f.write_str("sample"); } 393 | syntax::StorageQualifier::Uniform => { let _ = f.write_str("uniform"); } 394 | syntax::StorageQualifier::Buffer => { let _ = f.write_str("buffer"); } 395 | syntax::StorageQualifier::Shared => { let _ = f.write_str("shared"); } 396 | syntax::StorageQualifier::Coherent => { let _ = f.write_str("coherent"); } 397 | syntax::StorageQualifier::Volatile => { let _ = f.write_str("volatile"); } 398 | syntax::StorageQualifier::Restrict => { let _ = f.write_str("restrict"); } 399 | syntax::StorageQualifier::ReadOnly => { let _ = f.write_str("readonly"); } 400 | syntax::StorageQualifier::WriteOnly => { let _ = f.write_str("writeonly"); } 401 | syntax::StorageQualifier::Subroutine(ref n) => show_subroutine(f, &n) 402 | } 403 | } 404 | 405 | pub fn show_subroutine(f: &mut F, types: &Vec) where F: Write { 406 | let _ = f.write_str("subroutine"); 407 | 408 | if !types.is_empty() { 409 | let _ = f.write_str("("); 410 | 411 | let mut types_iter = types.iter(); 412 | let first = types_iter.next().unwrap(); 413 | 414 | show_type_name(f, first); 415 | 416 | for type_name in types_iter { 417 | let _ = f.write_str(", "); 418 | show_type_name(f, type_name); 419 | } 420 | 421 | let _ = f.write_str(")"); 422 | } 423 | } 424 | 425 | pub fn show_layout_qualifier(f: &mut F, l: &syntax::LayoutQualifier) where F: Write { 426 | let mut qualifiers = l.ids.0.iter(); 427 | let first = qualifiers.next().unwrap(); 428 | 429 | let _ = f.write_str("layout ("); 430 | show_layout_qualifier_spec(f, first); 431 | 432 | for qual_spec in qualifiers { 433 | let _ = f.write_str(", "); 434 | show_layout_qualifier_spec(f, qual_spec); 435 | } 436 | 437 | let _ = f.write_str(")"); 438 | } 439 | 440 | pub fn show_layout_qualifier_spec(f: &mut F, l: &syntax::LayoutQualifierSpec) where F: Write { 441 | match *l { 442 | syntax::LayoutQualifierSpec::Identifier(ref i, Some(ref e)) => { 443 | let _ = write!(f, "{} = ", i); 444 | show_expr(f, &e); 445 | } 446 | syntax::LayoutQualifierSpec::Identifier(ref i, None) => show_identifier(f, &i), 447 | syntax::LayoutQualifierSpec::Shared => { let _ = f.write_str("shared"); } 448 | } 449 | } 450 | 451 | pub fn show_precision_qualifier(f: &mut F, p: &syntax::PrecisionQualifier) where F: Write { 452 | match *p { 453 | syntax::PrecisionQualifier::High => { let _ = f.write_str("highp"); } 454 | syntax::PrecisionQualifier::Medium => { let _ = f.write_str("mediump"); } 455 | syntax::PrecisionQualifier::Low => { let _ = f.write_str("low"); } 456 | } 457 | } 458 | 459 | pub fn show_interpolation_qualifier(f: &mut F, i: &syntax::InterpolationQualifier) where F: Write { 460 | match *i { 461 | syntax::InterpolationQualifier::Smooth => { let _ = f.write_str("smooth"); } 462 | syntax::InterpolationQualifier::Flat => { let _ = f.write_str("flat"); } 463 | syntax::InterpolationQualifier::NoPerspective => { let _ = f.write_str("noperspective"); } 464 | } 465 | } 466 | 467 | pub fn show_float(f: &mut F, x: f32) where F: Write { 468 | if x.fract() == 0. { 469 | let _ = write!(f, "{}.", x); 470 | } else { 471 | let _ = write!(f, "{}", x); 472 | } 473 | } 474 | 475 | pub fn show_double(f: &mut F, x: f64) where F: Write { 476 | if x.fract() == 0. { 477 | let _ = write!(f, "{}.", x); 478 | } else { 479 | let _ = write!(f, "{}", x); 480 | } 481 | } 482 | 483 | pub fn emit_float(state: &mut OutputState) -> Word { 484 | match state.emitted_types.get("float") { 485 | Some(t) => *t, 486 | None => { 487 | let float = state.builder.type_float(32); 488 | state.emitted_types.insert("float".to_string(), float); 489 | float 490 | } 491 | } 492 | } 493 | 494 | pub fn emit_type(state: &mut OutputState, ty: &hir::Type) -> Word { 495 | if ty.precision.is_some() { 496 | panic!() 497 | } 498 | if ty.array_sizes.is_some() { 499 | panic!() 500 | } 501 | match ty.kind { 502 | hir::TypeKind::Float => { 503 | emit_float(state) 504 | } 505 | hir::TypeKind::Double => { 506 | //XXX: actually use double here 507 | emit_float(state) 508 | } 509 | hir::TypeKind::Vec4 => { 510 | emit_vec4(state) 511 | } 512 | _ => panic!("{:?}", ty.kind) 513 | } 514 | } 515 | 516 | pub fn emit_vec4(state: &mut OutputState) -> Word { 517 | match state.emitted_types.get("vec4") { 518 | Some(t) => *t, 519 | None => { 520 | let float = emit_float(state); 521 | let float_vec4 = state.builder.type_vector(float, 4); 522 | state.emitted_types.insert("vec4".to_string(), float_vec4); 523 | float_vec4 524 | } 525 | } 526 | } 527 | 528 | pub fn emit_void(state: &mut OutputState) -> Word { 529 | match state.emitted_types.get("void") { 530 | Some(t) => *t, 531 | None => { 532 | let void = state.builder.type_void(); 533 | state.emitted_types.insert("void".to_string(), void); 534 | void 535 | } 536 | } 537 | } 538 | 539 | pub fn emit_sym(state: &mut OutputState, s: hir::SymRef) -> Word { 540 | match state.emitted_syms.get(&s) { 541 | Some(s) => s.location, 542 | None => { 543 | let name = state.hir.sym(s).name.clone(); 544 | match name.as_ref() { 545 | "gl_FragColor" => { 546 | // XXX: we emit these special variables lazily 547 | // we should do better than matching by name 548 | let float_vec4 = emit_vec4(state); 549 | let b = &mut state.builder; 550 | let output = b.type_pointer(None, spirv::StorageClass::Output, float_vec4); 551 | let output_var = b.variable(output, None, spirv::StorageClass::Output, None); 552 | b.decorate(output_var, spirv::Decoration::Location, [Operand::LiteralInt32(0)]); 553 | state.emitted_syms.insert(s, Variable { location: output_var, ty: output}); 554 | output_var 555 | } 556 | _ => panic!("undeclared sym {}", name) 557 | } 558 | } 559 | } 560 | } 561 | 562 | pub fn translate_lvalue_expr(state: &mut OutputState, expr: &hir::Expr) -> Word { 563 | match expr.kind { 564 | hir::ExprKind::Variable(s) => { 565 | emit_sym(state, s) 566 | } 567 | _ => panic!() 568 | } 569 | } 570 | 571 | pub fn translate_const(state: &mut OutputState, c: &hir::Expr) -> Word { 572 | match c.kind { 573 | 574 | _ => panic!(), 575 | } 576 | } 577 | 578 | pub fn translate_vec4(state: &mut OutputState, x: &hir::Expr, y: &hir::Expr, z: &hir::Expr, w: &hir::Expr) -> Word { 579 | let float_vec4 = emit_vec4(state); 580 | let args = [ 581 | translate_r_val(state, x), 582 | translate_r_val(state, y), 583 | translate_r_val(state, w), 584 | translate_r_val(state, z)]; 585 | 586 | state.builder.composite_construct(float_vec4, None, args).unwrap() 587 | } 588 | 589 | pub fn translate_r_val(state: &mut OutputState, expr: &hir::Expr) -> Word { 590 | match expr.kind { 591 | hir::ExprKind::FunCall(ref fun, ref args) => { 592 | match fun { 593 | hir::FunIdentifier::Identifier(ref sym) => { 594 | let name = state.hir.sym(*sym).name.as_str().to_owned(); 595 | match name.as_ref() { 596 | "vec4" => { 597 | match args[..] { 598 | [ref x, ref y, ref w, ref z] => translate_vec4(state, x, y, w, z), 599 | [ref x] => translate_vec4(state, x, x, x, x), 600 | _ => panic!(), 601 | } 602 | } 603 | _ => { panic!() } 604 | } 605 | } 606 | _ => panic!(), 607 | } 608 | } 609 | hir::ExprKind::DoubleConst(f) => { 610 | // XXX: we need to do something better about the types of literals 611 | // We could constant pool these things 612 | let float = emit_float(state); 613 | let b = &mut state.builder; 614 | b.constant_f32(float, f as f32) 615 | } 616 | hir::ExprKind::Variable(sym) => { 617 | let v = &state.emitted_syms[&sym]; 618 | state.builder.load(v.ty, None, v.location, None, []).unwrap() 619 | } 620 | hir::ExprKind::Binary(ref op, ref l, ref r) => { 621 | let l = translate_r_val(state, l); 622 | let r = translate_r_val(state, r); 623 | match op { 624 | syntax::BinaryOp::Add => { 625 | let ty = emit_type(state, &expr.ty); 626 | state.builder.fadd(ty, None, l, r).unwrap() 627 | } 628 | _ => panic!("Unhandled op {:?}", op) 629 | } 630 | } 631 | _ => panic!("Unhandled {:?}", expr) 632 | } 633 | } 634 | 635 | pub fn translate_hir_expr(state: &mut OutputState, expr: &hir::Expr) { 636 | match expr.kind { 637 | 638 | hir::ExprKind::Assignment(ref v, ref op, ref e) => { 639 | let output_var = translate_lvalue_expr(state, v); 640 | let result = translate_r_val(state, e); 641 | let _ = state.builder.store(output_var, result, None, []); 642 | } 643 | _ => {} 644 | } 645 | } 646 | 647 | pub fn show_hir_expr(f: &mut F, state: &mut OutputState, expr: &hir::Expr) where F: Write { 648 | match expr.kind { 649 | hir::ExprKind::Variable(ref i) => show_sym(f, state, i), 650 | hir::ExprKind::IntConst(ref x) => { let _ = write!(f, "{}", x); } 651 | hir::ExprKind::UIntConst(ref x) => { let _ = write!(f, "{}u", x); } 652 | hir::ExprKind::BoolConst(ref x) => { let _ = write!(f, "{}", x); } 653 | hir::ExprKind::FloatConst(ref x) => show_float(f, *x), 654 | hir::ExprKind::DoubleConst(ref x) => show_double(f, *x), 655 | hir::ExprKind::Unary(ref op, ref e) => { 656 | show_unary_op(f, &op); 657 | let _ = f.write_str("("); 658 | show_hir_expr(f, state, &e); 659 | let _ = f.write_str(")"); 660 | } 661 | hir::ExprKind::Binary(ref op, ref l, ref r) => { 662 | let _ = f.write_str("("); 663 | show_hir_expr(f, state, &l); 664 | let _ = f.write_str(")"); 665 | show_binary_op(f, &op); 666 | let _ = f.write_str("("); 667 | show_hir_expr(f, state, &r); 668 | let _ = f.write_str(")"); 669 | } 670 | hir::ExprKind::Ternary(ref c, ref s, ref e) => { 671 | show_hir_expr(f, state, &c); 672 | let _ = f.write_str(" ? "); 673 | show_hir_expr(f, state, &s); 674 | let _ = f.write_str(" : "); 675 | show_hir_expr(f, state, &e); 676 | } 677 | hir::ExprKind::Assignment(ref v, ref op, ref e) => { 678 | show_hir_expr(f, state, &v); 679 | let _ = f.write_str(" "); 680 | show_assignment_op(f, &op); 681 | let _ = f.write_str(" "); 682 | show_hir_expr(f, state, &e); 683 | } 684 | hir::ExprKind::Bracket(ref e, ref indx) => { 685 | show_hir_expr(f, state, &e); 686 | let _ = f.write_str("["); 687 | show_hir_expr(f, state, &indx); 688 | let _ = f.write_str("]"); 689 | } 690 | hir::ExprKind::FunCall(ref fun, ref args) => { 691 | show_hir_function_identifier(f, state, &fun); 692 | let _ = f.write_str("("); 693 | 694 | if !args.is_empty() { 695 | let mut args_iter = args.iter(); 696 | let first = args_iter.next().unwrap(); 697 | show_hir_expr(f, state, first); 698 | 699 | for e in args_iter { 700 | let _ = f.write_str(", "); 701 | show_hir_expr(f, state, e); 702 | } 703 | } 704 | 705 | let _ = f.write_str(")"); 706 | } 707 | hir::ExprKind::Dot(ref e, ref i) => { 708 | let _ = f.write_str("("); 709 | show_hir_expr(f, state, &e); 710 | let _ = f.write_str(")"); 711 | let _ = f.write_str("."); 712 | show_identifier(f, i); 713 | } 714 | hir::ExprKind::SwizzleSelector(ref e, ref s) => { 715 | let _ = f.write_str("("); 716 | show_hir_expr(f, state, &e); 717 | let _ = f.write_str(")"); 718 | let _ = f.write_str("."); 719 | let _ = f.write_str(&s.to_string()); 720 | } 721 | hir::ExprKind::PostInc(ref e) => { 722 | show_hir_expr(f, state, &e); 723 | let _ = f.write_str("++"); 724 | } 725 | hir::ExprKind::PostDec(ref e) => { 726 | show_hir_expr(f, state, &e); 727 | let _ = f.write_str("--"); 728 | } 729 | hir::ExprKind::Comma(ref a, ref b) => { 730 | show_hir_expr(f, state, &a); 731 | let _ = f.write_str(", "); 732 | show_hir_expr(f, state, &b); 733 | } 734 | hir::ExprKind::CondMask | hir::ExprKind::Cond(..) => { panic!() } 735 | } 736 | } 737 | 738 | pub fn show_expr(f: &mut F, expr: &syntax::Expr) where F: Write { 739 | match *expr { 740 | syntax::Expr::Variable(ref i) => show_identifier(f, &i), 741 | syntax::Expr::IntConst(ref x) => { let _ = write!(f, "{}", x); } 742 | syntax::Expr::UIntConst(ref x) => { let _ = write!(f, "{}u", x); } 743 | syntax::Expr::BoolConst(ref x) => { let _ = write!(f, "{}", x); } 744 | syntax::Expr::FloatConst(ref x) => show_float(f, *x), 745 | syntax::Expr::DoubleConst(ref x) => show_double(f, *x), 746 | syntax::Expr::Unary(ref op, ref e) => { 747 | show_unary_op(f, &op); 748 | let _ = f.write_str("("); 749 | show_expr(f, &e); 750 | let _ = f.write_str(")"); 751 | } 752 | syntax::Expr::Binary(ref op, ref l, ref r) => { 753 | let _ = f.write_str("("); 754 | show_expr(f, &l); 755 | let _ = f.write_str(")"); 756 | show_binary_op(f, &op); 757 | let _ = f.write_str("("); 758 | show_expr(f, &r); 759 | let _ = f.write_str(")"); 760 | } 761 | syntax::Expr::Ternary(ref c, ref s, ref e) => { 762 | show_expr(f, &c); 763 | let _ = f.write_str(" ? "); 764 | show_expr(f, &s); 765 | let _ = f.write_str(" : "); 766 | show_expr(f, &e); 767 | } 768 | syntax::Expr::Assignment(ref v, ref op, ref e) => { 769 | show_expr(f, &v); 770 | let _ = f.write_str(" "); 771 | show_assignment_op(f, &op); 772 | let _ = f.write_str(" "); 773 | show_expr(f, &e); 774 | } 775 | syntax::Expr::Bracket(ref e, ref a) => { 776 | show_expr(f, &e); 777 | //show_array_spec(f, &a); 778 | } 779 | syntax::Expr::FunCall(ref fun, ref args) => { 780 | show_function_identifier(f, &fun); 781 | let _ = f.write_str("("); 782 | 783 | if !args.is_empty() { 784 | let mut args_iter = args.iter(); 785 | let first = args_iter.next().unwrap(); 786 | show_expr(f, first); 787 | 788 | for e in args_iter { 789 | let _ = f.write_str(", "); 790 | show_expr(f, e); 791 | } 792 | } 793 | 794 | let _ = f.write_str(")"); 795 | } 796 | syntax::Expr::Dot(ref e, ref i) => { 797 | let _ = f.write_str("("); 798 | show_expr(f, &e); 799 | let _ = f.write_str(")"); 800 | let _ = f.write_str("."); 801 | show_identifier(f, &i); 802 | } 803 | syntax::Expr::PostInc(ref e) => { 804 | show_expr(f, &e); 805 | let _ = f.write_str("++"); 806 | } 807 | syntax::Expr::PostDec(ref e) => { 808 | show_expr(f, &e); 809 | let _ = f.write_str("--"); 810 | } 811 | syntax::Expr::Comma(ref a, ref b) => { 812 | show_expr(f, &a); 813 | let _ = f.write_str(", "); 814 | show_expr(f, &b); 815 | } 816 | } 817 | } 818 | 819 | pub fn show_unary_op(f: &mut F, op: &syntax::UnaryOp) where F: Write { 820 | match *op { 821 | syntax::UnaryOp::Inc => { let _ = f.write_str("++"); } 822 | syntax::UnaryOp::Dec => { let _ = f.write_str("--"); } 823 | syntax::UnaryOp::Add => { let _ = f.write_str("+"); } 824 | syntax::UnaryOp::Minus => { let _ = f.write_str("-"); } 825 | syntax::UnaryOp::Not => { let _ = f.write_str("!"); } 826 | syntax::UnaryOp::Complement => { let _ = f.write_str("~"); } 827 | } 828 | } 829 | 830 | pub fn show_binary_op(f: &mut F, op: &syntax::BinaryOp) where F: Write { 831 | match *op { 832 | syntax::BinaryOp::Or => { let _ = f.write_str("||"); } 833 | syntax::BinaryOp::Xor => { let _ = f.write_str("^^"); } 834 | syntax::BinaryOp::And => { let _ = f.write_str("&&"); } 835 | syntax::BinaryOp::BitOr => { let _ = f.write_str("|"); } 836 | syntax::BinaryOp::BitXor => { let _ = f.write_str("^"); } 837 | syntax::BinaryOp::BitAnd => { let _ = f.write_str("&"); } 838 | syntax::BinaryOp::Equal => { let _ = f.write_str("=="); } 839 | syntax::BinaryOp::NonEqual => { let _ = f.write_str("!="); } 840 | syntax::BinaryOp::LT => { let _ = f.write_str("<"); } 841 | syntax::BinaryOp::GT => { let _ = f.write_str(">"); } 842 | syntax::BinaryOp::LTE => { let _ = f.write_str("<="); } 843 | syntax::BinaryOp::GTE => { let _ = f.write_str(">="); } 844 | syntax::BinaryOp::LShift => { let _ = f.write_str("<<"); } 845 | syntax::BinaryOp::RShift => { let _ = f.write_str(">>"); } 846 | syntax::BinaryOp::Add => { let _ = f.write_str("+"); } 847 | syntax::BinaryOp::Sub => { let _ = f.write_str("-"); } 848 | syntax::BinaryOp::Mult => { let _ = f.write_str("*"); } 849 | syntax::BinaryOp::Div => { let _ = f.write_str("/"); } 850 | syntax::BinaryOp::Mod => { let _ = f.write_str("%"); } 851 | } 852 | } 853 | 854 | pub fn show_assignment_op(f: &mut F, op: &syntax::AssignmentOp) where F: Write { 855 | match *op { 856 | syntax::AssignmentOp::Equal => { let _ = f.write_str("="); } 857 | syntax::AssignmentOp::Mult => { let _ = f.write_str("*="); } 858 | syntax::AssignmentOp::Div => { let _ = f.write_str("/="); } 859 | syntax::AssignmentOp::Mod => { let _ = f.write_str("%="); } 860 | syntax::AssignmentOp::Add => { let _ = f.write_str("+="); } 861 | syntax::AssignmentOp::Sub => { let _ = f.write_str("-="); } 862 | syntax::AssignmentOp::LShift => { let _ = f.write_str("<<="); } 863 | syntax::AssignmentOp::RShift => { let _ = f.write_str(">>="); } 864 | syntax::AssignmentOp::And => { let _ = f.write_str("&="); } 865 | syntax::AssignmentOp::Xor => { let _ = f.write_str("^="); } 866 | syntax::AssignmentOp::Or => { let _ = f.write_str("|="); } 867 | } 868 | } 869 | 870 | pub fn show_function_identifier(f: &mut F, i: &syntax::FunIdentifier) where F: Write { 871 | match *i { 872 | syntax::FunIdentifier::Identifier(ref n) => show_identifier(f, &n), 873 | syntax::FunIdentifier::Expr(ref e) => show_expr(f, &*e) 874 | } 875 | } 876 | 877 | pub fn show_hir_function_identifier(f: &mut F, state: &mut OutputState, i: &hir::FunIdentifier) where F: Write { 878 | match *i { 879 | hir::FunIdentifier::Identifier(ref n) => show_sym(f, state, n), 880 | hir::FunIdentifier::Constructor(ref t) => show_type(f, state, t) 881 | } 882 | } 883 | 884 | pub fn translate_declaration(state: &mut OutputState, d: &hir::Declaration) { 885 | match *d { 886 | hir::Declaration::InitDeclaratorList(ref list) => { 887 | 888 | translate_init_declarator_list(state, &list); 889 | } 890 | _ => panic!() 891 | } 892 | } 893 | 894 | pub fn show_declaration(f: &mut F, state: &mut OutputState, d: &hir::Declaration) where F: Write { 895 | match *d { 896 | hir::Declaration::FunctionPrototype(ref proto) => { 897 | show_function_prototype(f, state, &proto); 898 | let _ = f.write_str(";\n"); 899 | } 900 | hir::Declaration::InitDeclaratorList(ref list) => { 901 | show_init_declarator_list(f, state, &list); 902 | let _ = f.write_str(";\n"); 903 | } 904 | hir::Declaration::Precision(ref qual, ref ty) => { 905 | show_precision_qualifier(f, &qual); 906 | show_type_specifier(f, state, &ty); 907 | let _ = f.write_str(";\n"); 908 | } 909 | hir::Declaration::Block(ref block) => { 910 | show_block(f, state, &block); 911 | let _ = f.write_str(";\n"); 912 | } 913 | hir::Declaration::Global(ref qual, ref identifiers) => { 914 | show_type_qualifier(f, &qual); 915 | 916 | if !identifiers.is_empty() { 917 | let mut iter = identifiers.iter(); 918 | let first = iter.next().unwrap(); 919 | show_identifier(f, first); 920 | 921 | for identifier in iter { 922 | let _ = write!(f, ", {}", identifier); 923 | } 924 | } 925 | 926 | let _ = f.write_str(";\n"); 927 | } 928 | hir::Declaration::StructDefinition(sym) => { 929 | panic!() 930 | } 931 | } 932 | } 933 | 934 | pub fn show_function_prototype(f: &mut F, state: &mut OutputState, fp: &hir::FunctionPrototype) where F: Write { 935 | show_type(f, state, &fp.ty); 936 | let _ = f.write_str(" "); 937 | show_identifier(f, &fp.name); 938 | 939 | let _ = f.write_str("("); 940 | 941 | if !fp.parameters.is_empty() { 942 | let mut iter = fp.parameters.iter(); 943 | let first = iter.next().unwrap(); 944 | show_function_parameter_declaration(f, state, first); 945 | 946 | for param in iter { 947 | let _ = f.write_str(", "); 948 | show_function_parameter_declaration(f, state, param); 949 | } 950 | } 951 | 952 | let _ = f.write_str(")"); 953 | } 954 | 955 | pub fn show_parameter_qualifier(f: &mut F, i: &hir::ParameterQualifier) where F: Write { 956 | match *i { 957 | hir::ParameterQualifier::Const => { let _ = f.write_str("const"); } 958 | hir::ParameterQualifier::In => { let _ = f.write_str("in"); } 959 | hir::ParameterQualifier::Out => { let _ = f.write_str("out"); } 960 | hir::ParameterQualifier::InOut => { let _ = f.write_str("inout"); } 961 | } 962 | } 963 | 964 | pub fn show_function_parameter_declaration(f: &mut F, state: &mut OutputState, p: &hir::FunctionParameterDeclaration) where F: Write { 965 | match *p { 966 | hir::FunctionParameterDeclaration::Named(ref qual, ref fpd) => { 967 | if let Some(ref q) = *qual { 968 | show_parameter_qualifier(f, q); 969 | let _ = f.write_str(" "); 970 | } 971 | 972 | show_function_parameter_declarator(f, state, fpd); 973 | } 974 | hir::FunctionParameterDeclaration::Unnamed(ref qual, ref ty) => { 975 | if let Some(ref q) = *qual { 976 | show_parameter_qualifier(f, q); 977 | let _ = f.write_str(" "); 978 | } 979 | 980 | show_type_specifier(f, state, ty); 981 | } 982 | } 983 | } 984 | 985 | pub fn show_function_parameter_declarator(f: &mut F, state: &mut OutputState, p: &hir::FunctionParameterDeclarator) where F: Write { 986 | show_type(f, state, &p.ty); 987 | let _ = f.write_str(" "); 988 | show_arrayed_identifier(f, &p.name, &p.ty); 989 | } 990 | 991 | pub fn show_init_declarator_list(f: &mut F, state: &mut OutputState, i: &hir::InitDeclaratorList) where F: Write { 992 | show_single_declaration(f, state, &i.head); 993 | 994 | for decl in &i.tail { 995 | let _ = f.write_str(", "); 996 | show_single_declaration_no_type(f, state, decl); 997 | } 998 | } 999 | 1000 | pub fn translate_initializer(state: &mut OutputState, i: &hir::Initializer) -> Word { 1001 | match *i { 1002 | hir::Initializer::Simple(ref e) => translate_r_val(state, e), 1003 | _ => panic!(), 1004 | } 1005 | } 1006 | 1007 | pub fn translate_single_declaration(state: &mut OutputState, d: &hir::SingleDeclaration) { 1008 | 1009 | let ty = emit_type(state, &d.ty); 1010 | 1011 | let storage = match &state.hir.sym(d.name).decl { 1012 | hir::SymDecl::Global(storage, ..) => { 1013 | match storage { 1014 | hir::StorageClass::Const => spirv::StorageClass::UniformConstant, 1015 | hir::StorageClass::Out => spirv::StorageClass::Output, 1016 | hir::StorageClass::In => spirv::StorageClass::Input, 1017 | hir::StorageClass::Uniform => spirv::StorageClass::Uniform, 1018 | hir::StorageClass::None => spirv::StorageClass::Function 1019 | } 1020 | } 1021 | hir::SymDecl::Local(storage, _, _) => { 1022 | match storage { 1023 | hir::StorageClass::Const => spirv::StorageClass::UniformConstant, 1024 | hir::StorageClass::Out => spirv::StorageClass::Output, 1025 | hir::StorageClass::In => spirv::StorageClass::Input, 1026 | hir::StorageClass::Uniform => spirv::StorageClass::Uniform, 1027 | hir::StorageClass::None => spirv::StorageClass::Function 1028 | } 1029 | } 1030 | _ => panic!(), 1031 | }; 1032 | 1033 | let output_var = state.builder.variable(ty, None, storage, None); 1034 | state.emitted_syms.insert(d.name, Variable{ location: output_var, ty }); 1035 | 1036 | if let Some(ref initializer) = d.initializer { 1037 | let init_val = translate_initializer(state, initializer); 1038 | state.builder.store(output_var, init_val, None, []); 1039 | } 1040 | } 1041 | 1042 | pub fn translate_init_declarator_list(state: &mut OutputState, i: &hir::InitDeclaratorList) { 1043 | translate_single_declaration(state, &i.head); 1044 | 1045 | for decl in &i.tail { 1046 | panic!() 1047 | } 1048 | } 1049 | 1050 | pub fn show_single_declaration(f: &mut F, state: &mut OutputState, d: &hir::SingleDeclaration) where F: Write { 1051 | //show_fully_specified_type(f, state, &d.ty); 1052 | 1053 | let _ = f.write_str(" "); 1054 | show_sym(f, state, &d.name); 1055 | 1056 | /*if let Some(ref arr_spec) = d.array_specifier { 1057 | show_array_spec(f, arr_spec); 1058 | }*/ 1059 | 1060 | if let Some(ref initializer) = d.initializer { 1061 | let _ = f.write_str(" = "); 1062 | show_initializer(f, state, initializer); 1063 | } 1064 | } 1065 | 1066 | pub fn show_single_declaration_no_type(f: &mut F, state: &mut OutputState, d: &hir::SingleDeclarationNoType) where F: Write { 1067 | /*show_arrayed_identifier(f, &d.ident); 1068 | 1069 | if let Some(ref initializer) = d.initializer { 1070 | let _ = f.write_str(" = "); 1071 | show_initializer(f, state, initializer); 1072 | }*/ 1073 | } 1074 | 1075 | pub fn show_initializer(f: &mut F, state: &mut OutputState, i: &hir::Initializer) where F: Write { 1076 | match *i { 1077 | hir::Initializer::Simple(ref e) => show_hir_expr(f, state, e), 1078 | hir::Initializer::List(ref list) => { 1079 | let mut iter = list.0.iter(); 1080 | let first = iter.next().unwrap(); 1081 | 1082 | let _ = f.write_str("{ "); 1083 | show_initializer(f, state, first); 1084 | 1085 | for ini in iter { 1086 | let _ = f.write_str(", "); 1087 | show_initializer(f, state, ini); 1088 | } 1089 | 1090 | let _ = f.write_str(" }"); 1091 | } 1092 | } 1093 | } 1094 | 1095 | pub fn show_block(f: &mut F, state: &mut OutputState, b: &hir::Block) where F: Write { 1096 | show_type_qualifier(f, &b.qualifier); 1097 | let _ = f.write_str(" "); 1098 | show_identifier(f, &b.name); 1099 | let _ = f.write_str(" {"); 1100 | 1101 | for field in &b.fields { 1102 | show_struct_field(f, state, field); 1103 | let _ = f.write_str("\n"); 1104 | } 1105 | let _ = f.write_str("}"); 1106 | 1107 | if let Some(ref ident) = b.identifier { 1108 | //show_arrayed_identifier(f, ident); 1109 | } 1110 | } 1111 | 1112 | pub fn translate_type(state: &mut OutputState, ty: &hir::Type) -> spirv::Word { 1113 | emit_void(state) 1114 | } 1115 | 1116 | pub fn translate_function_definition(state: &mut OutputState, fd: &hir::FunctionDefinition) { 1117 | state.return_type = Some(Box::new(fd.prototype.ty.clone())); 1118 | 1119 | 1120 | let ret_type = translate_type(state, &fd.prototype.ty); 1121 | { 1122 | let void = emit_void(state); 1123 | let b = &mut state.builder; 1124 | let voidf = b.type_function(void, vec![]); 1125 | 1126 | let fun = b.begin_function(ret_type, 1127 | None, 1128 | (spirv::FunctionControl::DONT_INLINE | 1129 | spirv::FunctionControl::CONST), 1130 | voidf) 1131 | .unwrap(); 1132 | b.execution_mode(fun, spirv::ExecutionMode::OriginUpperLeft, []); 1133 | b.entry_point(state.model, fun, "main", []); 1134 | 1135 | b.begin_basic_block(None).unwrap(); 1136 | } 1137 | translate_compound_statement(state, &fd.body); 1138 | 1139 | let b = &mut state.builder; 1140 | b.ret().unwrap(); 1141 | b.end_function().unwrap(); 1142 | state.return_type = None; 1143 | state.return_declared = false; 1144 | } 1145 | 1146 | pub fn show_compound_statement(f: &mut F, state: &mut OutputState, cst: &hir::CompoundStatement) where F: Write { 1147 | let _ = f.write_str("{\n"); 1148 | 1149 | for st in &cst.statement_list { 1150 | show_statement(f, state, st); 1151 | } 1152 | 1153 | let _ = f.write_str("}\n"); 1154 | } 1155 | 1156 | pub fn translate_compound_statement(state: &mut OutputState, cst: &hir::CompoundStatement) { 1157 | for st in &cst.statement_list { 1158 | translate_statement(state, st); 1159 | } 1160 | } 1161 | 1162 | 1163 | pub fn translate_statement(state: &mut OutputState, st: &hir::Statement) { 1164 | match *st { 1165 | hir::Statement::Compound(ref cst) => translate_compound_statement(state, cst), 1166 | hir::Statement::Simple(ref sst) => translate_simple_statement(state, sst) 1167 | } 1168 | } 1169 | 1170 | pub fn show_statement(f: &mut F, state: &mut OutputState, st: &hir::Statement) where F: Write { 1171 | match *st { 1172 | hir::Statement::Compound(ref cst) => show_compound_statement(f, state, cst), 1173 | hir::Statement::Simple(ref sst) => show_simple_statement(f, state, sst) 1174 | } 1175 | } 1176 | 1177 | pub fn show_simple_statement(f: &mut F, state: &mut OutputState, sst: &hir::SimpleStatement) where F: Write { 1178 | match *sst { 1179 | hir::SimpleStatement::Declaration(ref d) => show_declaration(f, state, d), 1180 | hir::SimpleStatement::Expression(ref e) => show_expression_statement(f, state, e), 1181 | hir::SimpleStatement::Selection(ref s) => show_selection_statement(f, state, s), 1182 | hir::SimpleStatement::Switch(ref s) => show_switch_statement(f, state, s), 1183 | hir::SimpleStatement::Iteration(ref i) => show_iteration_statement(f, state, i), 1184 | hir::SimpleStatement::Jump(ref j) => show_jump_statement(f, state, j) 1185 | } 1186 | } 1187 | 1188 | pub fn translate_simple_statement(state: &mut OutputState, sst: &hir::SimpleStatement) { 1189 | match *sst { 1190 | hir::SimpleStatement::Declaration(ref d) => translate_declaration(state, d), 1191 | hir::SimpleStatement::Expression(ref e) => translate_expression_statement(state, e), 1192 | hir::SimpleStatement::Selection(ref s) => panic!(), //show_selection_statement(f, state, s), 1193 | hir::SimpleStatement::Switch(ref s) => panic!(), //show_switch_statement(f, state, s), 1194 | hir::SimpleStatement::Iteration(ref i) => panic!(), //show_iteration_statement(f, state, i), 1195 | hir::SimpleStatement::Jump(ref j) => panic!(), //show_jump_statement(f, state, j) 1196 | } 1197 | } 1198 | 1199 | pub fn show_expression_statement(f: &mut F, state: &mut OutputState, est: &hir::ExprStatement) where F: Write { 1200 | if let Some(ref e) = *est { 1201 | show_hir_expr(f, state, e); 1202 | } 1203 | 1204 | let _ = f.write_str(";\n"); 1205 | } 1206 | 1207 | 1208 | pub fn translate_expression_statement(state: &mut OutputState, est: &hir::ExprStatement) { 1209 | if let Some(ref e) = *est { 1210 | translate_hir_expr(state, e); 1211 | } 1212 | } 1213 | 1214 | pub fn show_selection_statement(f: &mut F, state: &mut OutputState, sst: &hir::SelectionStatement) where F: Write { 1215 | let _ = f.write_str("if ("); 1216 | show_hir_expr(f, state, &sst.cond); 1217 | let _ = f.write_str(") {\n"); 1218 | show_selection_rest_statement(f, state, &sst.rest); 1219 | } 1220 | 1221 | pub fn show_selection_rest_statement(f: &mut F, state: &mut OutputState, sst: &hir::SelectionRestStatement) where F: Write { 1222 | match *sst { 1223 | hir::SelectionRestStatement::Statement(ref if_st) => { 1224 | show_statement(f, state, if_st); 1225 | let _ = f.write_str("}\n"); 1226 | } 1227 | hir::SelectionRestStatement::Else(ref if_st, ref else_st) => { 1228 | show_statement(f, state, if_st); 1229 | let _ = f.write_str("} else "); 1230 | show_statement(f, state, else_st); 1231 | } 1232 | } 1233 | } 1234 | 1235 | pub fn show_switch_statement(f: &mut F, state: &mut OutputState, sst: &hir::SwitchStatement) where F: Write { 1236 | let _ = f.write_str("switch ("); 1237 | show_hir_expr(f, state, &sst.head); 1238 | let _ = f.write_str(") {\n"); 1239 | 1240 | for case in &sst.cases { 1241 | show_case_label(f, state, &case.label); 1242 | for st in &case.stmts { 1243 | show_statement(f, state, st); 1244 | } 1245 | } 1246 | let _ = f.write_str("}\n"); 1247 | 1248 | } 1249 | 1250 | pub fn show_case_label(f: &mut F, state: &mut OutputState, cl: &hir::CaseLabel) where F: Write { 1251 | match *cl { 1252 | hir::CaseLabel::Case(ref e) => { 1253 | let _ = f.write_str("case "); 1254 | show_hir_expr(f, state, e); 1255 | let _ = f.write_str(":\n"); 1256 | } 1257 | hir::CaseLabel::Def => { let _ = f.write_str("default:\n"); } 1258 | } 1259 | } 1260 | 1261 | pub fn show_iteration_statement(f: &mut F, state: &mut OutputState, ist: &hir::IterationStatement) where F: Write { 1262 | match *ist { 1263 | hir::IterationStatement::While(ref cond, ref body) => { 1264 | let _ = f.write_str("while ("); 1265 | show_condition(f, state, cond); 1266 | let _ = f.write_str(") "); 1267 | show_statement(f, state, body); 1268 | } 1269 | hir::IterationStatement::DoWhile(ref body, ref cond) => { 1270 | let _ = f.write_str("do "); 1271 | show_statement(f, state, body); 1272 | let _ = f.write_str(" while ("); 1273 | show_hir_expr(f, state, cond); 1274 | let _ = f.write_str(")\n"); 1275 | } 1276 | hir::IterationStatement::For(ref init, ref rest, ref body) => { 1277 | let _ = f.write_str("for ("); 1278 | show_for_init_statement(f, state, init); 1279 | show_for_rest_statement(f, state, rest); 1280 | let _ = f.write_str(") "); 1281 | show_statement(f, state, body); 1282 | } 1283 | } 1284 | } 1285 | 1286 | pub fn show_condition(f: &mut F, state: &mut OutputState, c: &hir::Condition) where F: Write { 1287 | match *c { 1288 | hir::Condition::Expr(ref e) => show_hir_expr(f, state, e), 1289 | /*hir::Condition::Assignment(ref ty, ref name, ref initializer) => { 1290 | show_type(f, state, ty); 1291 | let _ = f.write_str(" "); 1292 | show_identifier(f, name); 1293 | let _ = f.write_str(" = "); 1294 | show_initializer(f, state, initializer); 1295 | }*/ 1296 | } 1297 | } 1298 | 1299 | pub fn show_for_init_statement(f: &mut F, state: &mut OutputState, i: &hir::ForInitStatement) where F: Write { 1300 | match *i { 1301 | hir::ForInitStatement::Expression(ref expr) => { 1302 | if let Some(ref e) = *expr { 1303 | show_hir_expr(f, state, e); 1304 | } 1305 | } 1306 | hir::ForInitStatement::Declaration(ref d) => { 1307 | show_declaration(f, state, d); 1308 | } 1309 | } 1310 | } 1311 | 1312 | pub fn show_for_rest_statement(f: &mut F, state: &mut OutputState, r: &hir::ForRestStatement) where F: Write { 1313 | if let Some(ref cond) = r.condition { 1314 | show_condition(f, state, cond); 1315 | } 1316 | 1317 | let _ = f.write_str("; "); 1318 | 1319 | if let Some(ref e) = r.post_expr { 1320 | show_hir_expr(f, state, e); 1321 | } 1322 | } 1323 | 1324 | pub fn show_jump_statement(f: &mut F, state: &mut OutputState, j: &hir::JumpStatement) where F: Write { 1325 | match *j { 1326 | hir::JumpStatement::Continue => { let _ = f.write_str("continue;\n"); } 1327 | hir::JumpStatement::Break => { let _ = f.write_str("break;\n"); } 1328 | hir::JumpStatement::Discard => { let _ = f.write_str("discard;\n"); } 1329 | hir::JumpStatement::Return(ref e) => { 1330 | if let Some(e) = e { 1331 | let _ = f.write_str("return "); 1332 | show_hir_expr(f, state, e); 1333 | let _ = f.write_str(";\n"); 1334 | } else { 1335 | let _ = f.write_str("return;"); 1336 | } 1337 | } 1338 | } 1339 | } 1340 | 1341 | pub fn translate_external_declaration(state: &mut OutputState, ed: &hir::ExternalDeclaration) { 1342 | match *ed { 1343 | hir::ExternalDeclaration::Preprocessor(ref pp) => panic!("Preprocessor unsupported"), 1344 | hir::ExternalDeclaration::FunctionDefinition(ref fd) => translate_function_definition(state, fd), 1345 | hir::ExternalDeclaration::Declaration(ref d) => translate_declaration(state, d), 1346 | } 1347 | } 1348 | 1349 | pub fn translate_translation_unit(state: &mut OutputState, tu: &hir::TranslationUnit) { 1350 | for ed in &(tu.0).0 { 1351 | translate_external_declaration(state, ed); 1352 | } 1353 | } 1354 | 1355 | #[test] 1356 | fn basic() { 1357 | let s= glsl_to_spirv(" 1358 | 1359 | void main() 1360 | { 1361 | float x = 0.1; 1362 | x = x + 0.1; 1363 | gl_FragColor = vec4(x, 0.4, 0.8, 1.0); 1364 | }"); 1365 | assert_eq!(s, r#"; SPIR-V 1366 | ; Version: 1.3 1367 | ; Generator: rspirv 1368 | ; Bound: 19 1369 | OpCapability Shader 1370 | OpMemoryModel Logical GLSL450 1371 | OpEntryPoint Fragment %3 "main" 1372 | OpExecutionMode %3 OriginUpperLeft 1373 | OpDecorate %13 Location 0 1374 | %1 = OpTypeVoid 1375 | %2 = OpTypeFunction %1 1376 | %5 = OpTypeFloat 32 1377 | %7 = OpConstant %5 0.1 1378 | %9 = OpConstant %5 0.1 1379 | %11 = OpTypeVector %5 4 1380 | %12 = OpTypePointer Output %11 1381 | %15 = OpConstant %5 0.4 1382 | %16 = OpConstant %5 1.0 1383 | %17 = OpConstant %5 0.8 1384 | %3 = OpFunction %1 DontInline|Const %2 1385 | %4 = OpLabel 1386 | %6 = OpVariable %5 Function 1387 | OpStore %6 %7 1388 | %8 = OpLoad %5 %6 1389 | %10 = OpFAdd %5 %8 %9 1390 | OpStore %6 %10 1391 | %13 = OpVariable %12 Output 1392 | %14 = OpLoad %5 %6 1393 | %18 = OpCompositeConstruct %11 %14 %15 %16 %17 1394 | OpStore %13 %18 1395 | OpReturn 1396 | OpFunctionEnd"#) 1397 | } 1398 | 1399 | 1400 | #[test] 1401 | fn vec_addition() { 1402 | let s= glsl_to_spirv("void main() { 1403 | vec4 p = vec4(1.); 1404 | gl_FragColor = vec4(0.4, 0.4, 0.8, 1.0) + p; 1405 | }"); 1406 | let reference = r#"; SPIR-V 1407 | ; Version: 1.3 1408 | ; Generator: rspirv 1409 | ; Bound: 22 1410 | OpCapability Shader 1411 | OpMemoryModel Logical GLSL450 1412 | OpEntryPoint Fragment %3 "main" 1413 | OpExecutionMode %3 OriginUpperLeft 1414 | OpDecorate %14 Location 0 1415 | %1 = OpTypeVoid 1416 | %2 = OpTypeFunction %1 1417 | %5 = OpTypeFloat 32 1418 | %6 = OpTypeVector %5 4 1419 | %8 = OpConstant %5 1.0 1420 | %9 = OpConstant %5 1.0 1421 | %10 = OpConstant %5 1.0 1422 | %11 = OpConstant %5 1.0 1423 | %13 = OpTypePointer Output %6 1424 | %15 = OpConstant %5 0.4 1425 | %16 = OpConstant %5 0.4 1426 | %17 = OpConstant %5 1.0 1427 | %18 = OpConstant %5 0.8 1428 | %3 = OpFunction %1 DontInline|Const %2 1429 | %4 = OpLabel 1430 | %7 = OpVariable %6 Function 1431 | %12 = OpCompositeConstruct %6 %8 %9 %10 %11 1432 | OpStore %7 %12 1433 | %14 = OpVariable %13 Output 1434 | %19 = OpCompositeConstruct %6 %15 %16 %17 %18 1435 | %20 = OpLoad %6 %7 1436 | %21 = OpFAdd %6 %19 %20 1437 | OpStore %14 %21 1438 | OpReturn 1439 | OpFunctionEnd"#; 1440 | 1441 | if s != reference { 1442 | println!("{}", s); 1443 | println!("{}", reference); 1444 | panic!() 1445 | } 1446 | } 1447 | -------------------------------------------------------------------------------- /src/hir.rs: -------------------------------------------------------------------------------- 1 | use std::iter::{FromIterator, once}; 2 | use std::ops::{Deref, DerefMut}; 3 | use std::collections::HashMap; 4 | use std::cell::{Cell, Ref, RefCell}; 5 | use std::rc::Rc; 6 | use std::mem; 7 | 8 | use glsl::syntax::{NonEmpty, TypeSpecifier, TypeSpecifierNonArray, InterpolationQualifier}; 9 | use glsl::syntax; 10 | use glsl::syntax::StructFieldSpecifier; 11 | use glsl::syntax::PrecisionQualifier; 12 | use glsl::syntax::ArrayedIdentifier; 13 | use glsl::syntax::ArraySpecifier; 14 | use glsl::syntax::TypeName; 15 | use glsl::syntax::StructSpecifier; 16 | use glsl::syntax::UnaryOp; 17 | use glsl::syntax::BinaryOp; 18 | use glsl::syntax::AssignmentOp; 19 | use glsl::syntax::Identifier; 20 | 21 | trait LiftFrom { 22 | fn lift(state: &mut State, s: S) -> Self; 23 | } 24 | 25 | fn lift>(state: &mut State, s: S) -> T { 26 | LiftFrom::lift(state, s) 27 | } 28 | 29 | #[derive(Debug)] 30 | pub struct Symbol { 31 | pub name: String, 32 | pub decl: SymDecl 33 | } 34 | 35 | #[derive(Debug, Clone, PartialEq)] 36 | pub struct FunctionSignature { 37 | ret: Type, 38 | params: Vec, 39 | } 40 | 41 | #[derive(Debug, Clone, PartialEq)] 42 | pub struct FunctionType { 43 | signatures: NonEmpty 44 | } 45 | 46 | #[derive(Clone, Copy, Debug, PartialEq)] 47 | pub enum StorageClass { 48 | None, 49 | Const, 50 | In, 51 | Out, 52 | Uniform, 53 | } 54 | 55 | #[derive(Clone, Debug, PartialEq)] 56 | pub struct ArraySizes { 57 | pub sizes: Vec 58 | } 59 | 60 | impl LiftFrom<&ArraySpecifier> for ArraySizes { 61 | fn lift(state: &mut State, a: &ArraySpecifier) -> Self { 62 | ArraySizes{ sizes: vec![match a { 63 | ArraySpecifier::Unsized=> panic!(), 64 | ArraySpecifier::ExplicitlySized(expr) => translate_expression(state, expr) 65 | }]} 66 | } 67 | } 68 | 69 | #[derive(Clone, Debug, PartialEq)] 70 | pub enum TypeKind { 71 | Void, 72 | Bool, 73 | Int, 74 | UInt, 75 | Float, 76 | Double, 77 | Vec2, 78 | Vec3, 79 | Vec4, 80 | DVec2, 81 | DVec3, 82 | DVec4, 83 | BVec2, 84 | BVec3, 85 | BVec4, 86 | IVec2, 87 | IVec3, 88 | IVec4, 89 | UVec2, 90 | UVec3, 91 | UVec4, 92 | Mat2, 93 | Mat3, 94 | Mat4, 95 | Mat23, 96 | Mat24, 97 | Mat32, 98 | Mat34, 99 | Mat42, 100 | Mat43, 101 | DMat2, 102 | DMat3, 103 | DMat4, 104 | DMat23, 105 | DMat24, 106 | DMat32, 107 | DMat34, 108 | DMat42, 109 | DMat43, 110 | // floating point opaque types 111 | Sampler1D, 112 | Image1D, 113 | Sampler2D, 114 | Image2D, 115 | Sampler3D, 116 | Image3D, 117 | SamplerCube, 118 | ImageCube, 119 | Sampler2DRect, 120 | Image2DRect, 121 | Sampler1DArray, 122 | Image1DArray, 123 | Sampler2DArray, 124 | Image2DArray, 125 | SamplerBuffer, 126 | ImageBuffer, 127 | Sampler2DMS, 128 | Image2DMS, 129 | Sampler2DMSArray, 130 | Image2DMSArray, 131 | SamplerCubeArray, 132 | ImageCubeArray, 133 | Sampler1DShadow, 134 | Sampler2DShadow, 135 | Sampler2DRectShadow, 136 | Sampler1DArrayShadow, 137 | Sampler2DArrayShadow, 138 | SamplerCubeShadow, 139 | SamplerCubeArrayShadow, 140 | // signed integer opaque types 141 | ISampler1D, 142 | IImage1D, 143 | ISampler2D, 144 | IImage2D, 145 | ISampler3D, 146 | IImage3D, 147 | ISamplerCube, 148 | IImageCube, 149 | ISampler2DRect, 150 | IImage2DRect, 151 | ISampler1DArray, 152 | IImage1DArray, 153 | ISampler2DArray, 154 | IImage2DArray, 155 | ISamplerBuffer, 156 | IImageBuffer, 157 | ISampler2DMS, 158 | IImage2DMS, 159 | ISampler2DMSArray, 160 | IImage2DMSArray, 161 | ISamplerCubeArray, 162 | IImageCubeArray, 163 | // unsigned integer opaque types 164 | AtomicUInt, 165 | USampler1D, 166 | UImage1D, 167 | USampler2D, 168 | UImage2D, 169 | USampler3D, 170 | UImage3D, 171 | USamplerCube, 172 | UImageCube, 173 | USampler2DRect, 174 | UImage2DRect, 175 | USampler1DArray, 176 | UImage1DArray, 177 | USampler2DArray, 178 | UImage2DArray, 179 | USamplerBuffer, 180 | UImageBuffer, 181 | USampler2DMS, 182 | UImage2DMS, 183 | USampler2DMSArray, 184 | UImage2DMSArray, 185 | USamplerCubeArray, 186 | UImageCubeArray, 187 | Struct(SymRef) 188 | } 189 | 190 | impl TypeKind { 191 | pub fn is_sampler(&self) -> bool { 192 | use TypeKind::*; 193 | match self { 194 | Sampler1D | 195 | Image1D | 196 | Sampler2D | 197 | Image2D | 198 | Sampler3D | 199 | Image3D | 200 | SamplerCube | 201 | ImageCube | 202 | Sampler2DRect | 203 | Image2DRect | 204 | Sampler1DArray | 205 | Image1DArray | 206 | Sampler2DArray | 207 | Image2DArray | 208 | SamplerBuffer | 209 | ImageBuffer | 210 | Sampler2DMS | 211 | Image2DMS | 212 | Sampler2DMSArray | 213 | Image2DMSArray | 214 | SamplerCubeArray | 215 | ImageCubeArray | 216 | Sampler1DShadow | 217 | Sampler2DShadow | 218 | Sampler2DRectShadow | 219 | Sampler1DArrayShadow | 220 | Sampler2DArrayShadow | 221 | SamplerCubeShadow | 222 | SamplerCubeArrayShadow | 223 | ISampler1D | 224 | IImage1D | 225 | ISampler2D | 226 | IImage2D | 227 | ISampler3D | 228 | IImage3D | 229 | ISamplerCube | 230 | IImageCube | 231 | ISampler2DRect | 232 | IImage2DRect | 233 | ISampler1DArray | 234 | IImage1DArray | 235 | ISampler2DArray | 236 | IImage2DArray | 237 | ISamplerBuffer | 238 | IImageBuffer | 239 | ISampler2DMS | 240 | IImage2DMS | 241 | ISampler2DMSArray | 242 | IImage2DMSArray | 243 | ISamplerCubeArray | 244 | IImageCubeArray | 245 | USampler1D | 246 | UImage1D | 247 | USampler2D | 248 | UImage2D | 249 | USampler3D | 250 | UImage3D | 251 | USamplerCube | 252 | UImageCube | 253 | USampler2DRect | 254 | UImage2DRect | 255 | USampler1DArray | 256 | UImage1DArray | 257 | USampler2DArray | 258 | UImage2DArray | 259 | USamplerBuffer | 260 | UImageBuffer | 261 | USampler2DMS | 262 | UImage2DMS | 263 | USampler2DMSArray | 264 | UImage2DMSArray | 265 | USamplerCubeArray | 266 | UImageCubeArray => true, 267 | _ => false, 268 | } 269 | } 270 | 271 | pub fn glsl_primitive_type_name(&self) -> Option<&'static str> { 272 | use TypeKind::*; 273 | Some(match self { 274 | Void => "void", 275 | Bool => "bool", 276 | Int => "int", 277 | UInt => "uint", 278 | Float => "float", 279 | Double => "double", 280 | Vec2 => "vec2", 281 | Vec3 => "vec3", 282 | Vec4 => "vec4", 283 | DVec2 => "dvec2", 284 | DVec3 => "dvec3", 285 | DVec4 => "dvec4", 286 | BVec2 => "bvec2", 287 | BVec3 => "bvec3", 288 | BVec4 => "bvec4", 289 | IVec2 => "ivec2", 290 | IVec3 => "ivec3", 291 | IVec4 => "ivec4", 292 | UVec2 => "uvec2", 293 | UVec3 => "uvec3", 294 | UVec4 => "uvec4", 295 | Mat2 => "mat2", 296 | Mat3 => "mat3", 297 | Mat4 => "mat4", 298 | Mat23 => "mat23", 299 | Mat24 => "mat24", 300 | Mat32 => "mat32", 301 | Mat34 => "mat34", 302 | Mat42 => "mat42", 303 | Mat43 => "mat43", 304 | DMat2 => "dmat2", 305 | DMat3 => "dmat3", 306 | DMat4 => "dmat4", 307 | DMat23 => "dmat23", 308 | DMat24 => "dmat24", 309 | DMat32 => "dmat32", 310 | DMat34 => "dmat34", 311 | DMat42 => "dmat42", 312 | DMat43 => "dmat43", 313 | Sampler1D => "sampler1D", 314 | Image1D => "image1D", 315 | Sampler2D => "sampler2D", 316 | Image2D => "image2D", 317 | Sampler3D => "sampler3D", 318 | Image3D => "image3D", 319 | SamplerCube => "samplerCube", 320 | ImageCube => "imageCube", 321 | Sampler2DRect => "sampler2DRect", 322 | Image2DRect => "image2DRect", 323 | Sampler1DArray => "sampler1DArray", 324 | Image1DArray => "image1DArray", 325 | Sampler2DArray => "sampler2DArray", 326 | Image2DArray => "image2DArray", 327 | SamplerBuffer => "samplerBuffer", 328 | ImageBuffer => "imageBuffer", 329 | Sampler2DMS => "sampler2DMS", 330 | Image2DMS => "image2DMS", 331 | Sampler2DMSArray => "sampler2DMSArray", 332 | Image2DMSArray => "image2DMSArray", 333 | SamplerCubeArray => "samplerCubeArray", 334 | ImageCubeArray => "imageCubeArray", 335 | Sampler1DShadow => "sampler1DShadow", 336 | Sampler2DShadow => "sampler2DShadow", 337 | Sampler2DRectShadow => "sampler2DRectShadow", 338 | Sampler1DArrayShadow => "sampler1DArrayShadow", 339 | Sampler2DArrayShadow => "sampler2DArrayShadow", 340 | SamplerCubeShadow => "samplerCubeShadow", 341 | SamplerCubeArrayShadow => "samplerCubeArrayShadow", 342 | ISampler1D => "isampler1D", 343 | IImage1D => "iimage1D", 344 | ISampler2D => "isampler2D", 345 | IImage2D => "iimage2D", 346 | ISampler3D => "isampler3D", 347 | IImage3D => "iimage3D", 348 | ISamplerCube => "isamplerCube", 349 | IImageCube => "iimageCube", 350 | ISampler2DRect => "isampler2DRect", 351 | IImage2DRect => "iimage2DRect", 352 | ISampler1DArray => "isampler1DArray", 353 | IImage1DArray => "iimage1DArray", 354 | ISampler2DArray => "isampler2DArray", 355 | IImage2DArray => "iimage2DArray", 356 | ISamplerBuffer => "isamplerBuffer", 357 | IImageBuffer => "iimageBuffer", 358 | ISampler2DMS => "isampler2MS", 359 | IImage2DMS => "iimage2DMS", 360 | ISampler2DMSArray => "isampler2DMSArray", 361 | IImage2DMSArray => "iimage2DMSArray", 362 | ISamplerCubeArray => "isamplerCubeArray", 363 | IImageCubeArray => "iimageCubeArray", 364 | AtomicUInt => "atomic_uint", 365 | USampler1D => "usampler1D", 366 | UImage1D => "uimage1D", 367 | USampler2D => "usampler2D", 368 | UImage2D => "uimage2D", 369 | USampler3D => "usampler3D", 370 | UImage3D => "uimage3D", 371 | USamplerCube => "usamplerCube", 372 | UImageCube => "uimageCube", 373 | USampler2DRect => "usampler2DRect", 374 | UImage2DRect => "uimage2DRect", 375 | USampler1DArray => "usampler1DArray", 376 | UImage1DArray => "uimage1DArray", 377 | USampler2DArray => "usampler2DArray", 378 | UImage2DArray => "uimage2DArray", 379 | USamplerBuffer => "usamplerBuffer", 380 | UImageBuffer => "uimageBuffer", 381 | USampler2DMS => "usampler2DMS", 382 | UImage2DMS => "uimage2DMS", 383 | USampler2DMSArray => "usamplerDMSArray", 384 | UImage2DMSArray => "uimage2DMSArray", 385 | USamplerCubeArray => "usamplerCubeArray", 386 | UImageCubeArray => "uimageCubeArray", 387 | Struct(..) => return None, 388 | }) 389 | } 390 | 391 | pub fn cxx_primitive_type_name(&self) -> Option<&'static str> { 392 | use TypeKind::*; 393 | match self { 394 | Bool => Some("Bool"), 395 | Int => Some("I32"), 396 | UInt => Some("U32"), 397 | Float => Some("Float"), 398 | Double => Some("Double"), 399 | _ => self.glsl_primitive_type_name(), 400 | } 401 | } 402 | 403 | pub fn cxx_primitive_scalar_type_name(&self) -> Option<&'static str> { 404 | use TypeKind::*; 405 | match self { 406 | Void => Some("void"), 407 | Bool => Some("bool"), 408 | Int => Some("int32_t"), 409 | UInt => Some("uint32_t"), 410 | Float => Some("float"), 411 | Double => Some("double"), 412 | _ => if self.is_sampler() { self.cxx_primitive_type_name() } else { None }, 413 | } 414 | } 415 | 416 | pub fn from_glsl_primitive_type_name(name: &str) -> Option { 417 | use TypeKind::*; 418 | Some(match name { 419 | "void" => Void, 420 | "bool" => Bool, 421 | "int" => Int, 422 | "uint" => UInt, 423 | "float" => Float, 424 | "double" => Double, 425 | "vec2" => Vec2, 426 | "vec3" => Vec3, 427 | "vec4" => Vec4, 428 | "dvec2" => DVec2, 429 | "dvec3" => DVec3, 430 | "dvec4" => DVec4, 431 | "bvec2" => BVec2, 432 | "bvec3" => BVec3, 433 | "bvec4" => BVec4, 434 | "ivec2" => IVec2, 435 | "ivec3" => IVec3, 436 | "ivec4" => IVec4, 437 | "uvec2" => UVec2, 438 | "uvec3" => UVec3, 439 | "uvec4" => UVec4, 440 | "mat2" => Mat2, 441 | "mat3" => Mat3, 442 | "mat4" => Mat4, 443 | "mat23" => Mat23, 444 | "mat24" => Mat24, 445 | "mat32" => Mat32, 446 | "mat34" => Mat34, 447 | "mat42" => Mat42, 448 | "mat43" => Mat43, 449 | "dmat2" => DMat2, 450 | "dmat3" => DMat3, 451 | "dmat4" => DMat4, 452 | "dmat23" => DMat23, 453 | "dmat24" => DMat24, 454 | "dmat32" => DMat32, 455 | "dmat34" => DMat34, 456 | "dmat42" => DMat42, 457 | "dmat43" => DMat43, 458 | "sampler1D" => Sampler1D, 459 | "image1D" => Image1D, 460 | "sampler2D" => Sampler2D, 461 | "image2D" => Image2D, 462 | "sampler3D" => Sampler3D, 463 | "image3D" => Image3D, 464 | "samplerCube" => SamplerCube, 465 | "imageCube" => ImageCube, 466 | "sampler2DRect" => Sampler2DRect, 467 | "image2DRect" => Image2DRect, 468 | "sampler1DArray" => Sampler1DArray, 469 | "image1DArray" => Image1DArray, 470 | "sampler2DArray" => Sampler2DArray, 471 | "image2DArray" => Image2DArray, 472 | "samplerBuffer" => SamplerBuffer, 473 | "imageBuffer" => ImageBuffer, 474 | "sampler2DMS" => Sampler2DMS, 475 | "image2DMS" => Image2DMS, 476 | "sampler2DMSArray" => Sampler2DMSArray, 477 | "image2DMSArray" => Image2DMSArray, 478 | "samplerCubeArray" => SamplerCubeArray, 479 | "imageCubeArray" => ImageCubeArray, 480 | "sampler1DShadow" => Sampler1DShadow, 481 | "sampler2DShadow" => Sampler2DShadow, 482 | "sampler2DRectShadow" => Sampler2DRectShadow, 483 | "sampler1DArrayShadow" => Sampler1DArrayShadow, 484 | "sampler2DArrayShadow" => Sampler2DArrayShadow, 485 | "samplerCubeShadow" => SamplerCubeShadow, 486 | "samplerCubeArrayShadow" => SamplerCubeArrayShadow, 487 | "isampler1D" => ISampler1D, 488 | "iimage1D" => IImage1D, 489 | "isampler2D" => ISampler2D, 490 | "iimage2D" => IImage2D, 491 | "isampler3D" => ISampler3D, 492 | "iimage3D" => IImage3D, 493 | "isamplerCube" => ISamplerCube, 494 | "iimageCube" => IImageCube, 495 | "isampler2DRect" => ISampler2DRect, 496 | "iimage2DRect" => IImage2DRect, 497 | "isampler1DArray" => ISampler1DArray, 498 | "iimage1DArray" => IImage1DArray, 499 | "isampler2DArray" => ISampler2DArray, 500 | "iimage2DArray" => IImage2DArray, 501 | "isamplerBuffer" => ISamplerBuffer, 502 | "iimageBuffer" => IImageBuffer, 503 | "isampler2MS" => ISampler2DMS, 504 | "iimage2DMS" => IImage2DMS, 505 | "isampler2DMSArray" => ISampler2DMSArray, 506 | "iimage2DMSArray" => IImage2DMSArray, 507 | "isamplerCubeArray" => ISamplerCubeArray, 508 | "iimageCubeArray" => IImageCubeArray, 509 | "atomic_uint" => AtomicUInt, 510 | "usampler1D" => USampler1D, 511 | "uimage1D" => UImage1D, 512 | "usampler2D" => USampler2D, 513 | "uimage2D" => UImage2D, 514 | "usampler3D" => USampler3D, 515 | "uimage3D" => UImage3D, 516 | "usamplerCube" => USamplerCube, 517 | "uimageCube" => UImageCube, 518 | "usampler2DRect" => USampler2DRect, 519 | "uimage2DRect" => UImage2DRect, 520 | "usampler1DArray" => USampler1DArray, 521 | "uimage1DArray" => UImage1DArray, 522 | "usampler2DArray" => USampler2DArray, 523 | "uimage2DArray" => UImage2DArray, 524 | "usamplerBuffer" => USamplerBuffer, 525 | "uimageBuffer" => UImageBuffer, 526 | "usampler2DMS" => USampler2DMS, 527 | "uimage2DMS" => UImage2DMS, 528 | "usamplerDMSArray" => USampler2DMSArray, 529 | "uimage2DMSArray" => UImage2DMSArray, 530 | "usamplerCubeArray" => USamplerCubeArray, 531 | "uimageCubeArray" => UImageCubeArray, 532 | _ => return None, 533 | }) 534 | } 535 | 536 | 537 | pub fn from_primitive_type_specifier(spec: &syntax::TypeSpecifierNonArray) -> Option { 538 | use syntax::TypeSpecifierNonArray; 539 | use TypeKind::*; 540 | Some(match spec { 541 | TypeSpecifierNonArray::Void => Void, 542 | TypeSpecifierNonArray::Bool => Bool, 543 | TypeSpecifierNonArray::Int => Int, 544 | TypeSpecifierNonArray::UInt => UInt, 545 | TypeSpecifierNonArray::Float => Float, 546 | TypeSpecifierNonArray::Double => Double, 547 | TypeSpecifierNonArray::Vec2 => Vec2, 548 | TypeSpecifierNonArray::Vec3 => Vec3, 549 | TypeSpecifierNonArray::Vec4 => Vec4, 550 | TypeSpecifierNonArray::DVec2 => DVec2, 551 | TypeSpecifierNonArray::DVec3 => DVec3, 552 | TypeSpecifierNonArray::DVec4 => DVec4, 553 | TypeSpecifierNonArray::BVec2 => BVec2, 554 | TypeSpecifierNonArray::BVec3 => BVec3, 555 | TypeSpecifierNonArray::BVec4 => BVec4, 556 | TypeSpecifierNonArray::IVec2 => IVec2, 557 | TypeSpecifierNonArray::IVec3 => IVec3, 558 | TypeSpecifierNonArray::IVec4 => IVec4, 559 | TypeSpecifierNonArray::UVec2 => UVec2, 560 | TypeSpecifierNonArray::UVec3 => UVec3, 561 | TypeSpecifierNonArray::UVec4 => UVec4, 562 | TypeSpecifierNonArray::Mat2 => Mat2, 563 | TypeSpecifierNonArray::Mat3 => Mat3, 564 | TypeSpecifierNonArray::Mat4 => Mat4, 565 | TypeSpecifierNonArray::Mat23 => Mat23, 566 | TypeSpecifierNonArray::Mat24 => Mat24, 567 | TypeSpecifierNonArray::Mat32 => Mat32, 568 | TypeSpecifierNonArray::Mat34 => Mat34, 569 | TypeSpecifierNonArray::Mat42 => Mat42, 570 | TypeSpecifierNonArray::Mat43 => Mat43, 571 | TypeSpecifierNonArray::DMat2 => DMat2, 572 | TypeSpecifierNonArray::DMat3 => DMat3, 573 | TypeSpecifierNonArray::DMat4 => DMat4, 574 | TypeSpecifierNonArray::DMat23 => DMat23, 575 | TypeSpecifierNonArray::DMat24 => DMat24, 576 | TypeSpecifierNonArray::DMat32 => DMat32, 577 | TypeSpecifierNonArray::DMat34 => DMat34, 578 | TypeSpecifierNonArray::DMat42 => DMat42, 579 | TypeSpecifierNonArray::DMat43 => DMat43, 580 | TypeSpecifierNonArray::Sampler1D => Sampler1D, 581 | TypeSpecifierNonArray::Image1D => Image1D, 582 | TypeSpecifierNonArray::Sampler2D => Sampler2D, 583 | TypeSpecifierNonArray::Image2D => Image2D, 584 | TypeSpecifierNonArray::Sampler3D => Sampler3D, 585 | TypeSpecifierNonArray::Image3D => Image3D, 586 | TypeSpecifierNonArray::SamplerCube => SamplerCube, 587 | TypeSpecifierNonArray::ImageCube => ImageCube, 588 | TypeSpecifierNonArray::Sampler2DRect => Sampler2DRect, 589 | TypeSpecifierNonArray::Image2DRect => Image2DRect, 590 | TypeSpecifierNonArray::Sampler1DArray => Sampler1DArray, 591 | TypeSpecifierNonArray::Image1DArray => Image1DArray, 592 | TypeSpecifierNonArray::Sampler2DArray => Sampler2DArray, 593 | TypeSpecifierNonArray::Image2DArray => Image2DArray, 594 | TypeSpecifierNonArray::SamplerBuffer => SamplerBuffer, 595 | TypeSpecifierNonArray::ImageBuffer => ImageBuffer, 596 | TypeSpecifierNonArray::Sampler2DMS => Sampler2DMS, 597 | TypeSpecifierNonArray::Image2DMS => Image2DMS, 598 | TypeSpecifierNonArray::Sampler2DMSArray => Sampler2DMSArray, 599 | TypeSpecifierNonArray::Image2DMSArray => Image2DMSArray, 600 | TypeSpecifierNonArray::SamplerCubeArray => SamplerCubeArray, 601 | TypeSpecifierNonArray::ImageCubeArray => ImageCubeArray, 602 | TypeSpecifierNonArray::Sampler1DShadow => Sampler1DShadow, 603 | TypeSpecifierNonArray::Sampler2DShadow => Sampler2DShadow, 604 | TypeSpecifierNonArray::Sampler2DRectShadow => Sampler2DRectShadow, 605 | TypeSpecifierNonArray::Sampler1DArrayShadow => Sampler1DArrayShadow, 606 | TypeSpecifierNonArray::Sampler2DArrayShadow => Sampler2DArrayShadow, 607 | TypeSpecifierNonArray::SamplerCubeShadow => SamplerCubeShadow, 608 | TypeSpecifierNonArray::SamplerCubeArrayShadow => SamplerCubeArrayShadow, 609 | TypeSpecifierNonArray::ISampler1D => ISampler1D, 610 | TypeSpecifierNonArray::IImage1D => IImage1D, 611 | TypeSpecifierNonArray::ISampler2D => ISampler2D, 612 | TypeSpecifierNonArray::IImage2D => IImage2D, 613 | TypeSpecifierNonArray::ISampler3D => ISampler3D, 614 | TypeSpecifierNonArray::IImage3D => IImage3D, 615 | TypeSpecifierNonArray::ISamplerCube => ISamplerCube, 616 | TypeSpecifierNonArray::IImageCube => IImageCube, 617 | TypeSpecifierNonArray::ISampler2DRect => ISampler2DRect, 618 | TypeSpecifierNonArray::IImage2DRect => IImage2DRect, 619 | TypeSpecifierNonArray::ISampler1DArray => ISampler1DArray, 620 | TypeSpecifierNonArray::IImage1DArray => IImage1DArray, 621 | TypeSpecifierNonArray::ISampler2DArray => ISampler2DArray, 622 | TypeSpecifierNonArray::IImage2DArray => IImage2DArray, 623 | TypeSpecifierNonArray::ISamplerBuffer => ISamplerBuffer, 624 | TypeSpecifierNonArray::IImageBuffer => IImageBuffer, 625 | TypeSpecifierNonArray::ISampler2DMS => ISampler2DMS, 626 | TypeSpecifierNonArray::IImage2DMS => IImage2DMS, 627 | TypeSpecifierNonArray::ISampler2DMSArray => ISampler2DMSArray, 628 | TypeSpecifierNonArray::IImage2DMSArray => IImage2DMSArray, 629 | TypeSpecifierNonArray::ISamplerCubeArray => ISamplerCubeArray, 630 | TypeSpecifierNonArray::IImageCubeArray => IImageCubeArray, 631 | TypeSpecifierNonArray::AtomicUInt => AtomicUInt, 632 | TypeSpecifierNonArray::USampler1D => USampler1D, 633 | TypeSpecifierNonArray::UImage1D => UImage1D, 634 | TypeSpecifierNonArray::USampler2D => USampler2D, 635 | TypeSpecifierNonArray::UImage2D => UImage2D, 636 | TypeSpecifierNonArray::USampler3D => USampler3D, 637 | TypeSpecifierNonArray::UImage3D => UImage3D, 638 | TypeSpecifierNonArray::USamplerCube => USamplerCube, 639 | TypeSpecifierNonArray::UImageCube => UImageCube, 640 | TypeSpecifierNonArray::USampler2DRect => USampler2DRect, 641 | TypeSpecifierNonArray::UImage2DRect => UImage2DRect, 642 | TypeSpecifierNonArray::USampler1DArray => USampler1DArray, 643 | TypeSpecifierNonArray::UImage1DArray => UImage1DArray, 644 | TypeSpecifierNonArray::USampler2DArray => USampler2DArray, 645 | TypeSpecifierNonArray::UImage2DArray => UImage2DArray, 646 | TypeSpecifierNonArray::USamplerBuffer => USamplerBuffer, 647 | TypeSpecifierNonArray::UImageBuffer => UImageBuffer, 648 | TypeSpecifierNonArray::USampler2DMS => USampler2DMS, 649 | TypeSpecifierNonArray::UImage2DMS => UImage2DMS, 650 | TypeSpecifierNonArray::USampler2DMSArray => USampler2DMSArray, 651 | TypeSpecifierNonArray::UImage2DMSArray => UImage2DMSArray, 652 | TypeSpecifierNonArray::USamplerCubeArray => USamplerCubeArray, 653 | TypeSpecifierNonArray::UImageCubeArray => UImageCubeArray, 654 | TypeSpecifierNonArray::Struct(..) | 655 | TypeSpecifierNonArray::TypeName(..) => return None 656 | }) 657 | } 658 | } 659 | 660 | impl LiftFrom<&syntax::TypeSpecifierNonArray> for TypeKind { 661 | fn lift(state: &mut State, spec: &syntax::TypeSpecifierNonArray) -> Self { 662 | use syntax::TypeSpecifierNonArray; 663 | use TypeKind::*; 664 | if let Some(kind) = TypeKind::from_primitive_type_specifier(spec) { 665 | kind 666 | } else { 667 | match spec { 668 | TypeSpecifierNonArray::Struct(s) => { 669 | Struct(state.lookup(s.name.as_ref().unwrap().as_str()).unwrap()) 670 | } 671 | TypeSpecifierNonArray::TypeName(s) => { 672 | Struct(state.lookup(&s.0).unwrap()) 673 | } 674 | _ => unreachable!(), 675 | } 676 | } 677 | } 678 | } 679 | 680 | #[derive(Clone, Debug, PartialEq)] 681 | pub struct Type { 682 | pub kind: TypeKind, 683 | pub precision: Option, 684 | pub array_sizes: Option> 685 | } 686 | 687 | impl Type { 688 | pub fn new(kind: TypeKind) -> Self { 689 | Type { kind, precision: None, array_sizes: None } 690 | } 691 | } 692 | 693 | impl LiftFrom<&syntax::FullySpecifiedType> for Type { 694 | fn lift(state: &mut State, ty: &syntax::FullySpecifiedType) -> Self { 695 | let kind = lift(state, &ty.ty.ty); 696 | let array_sizes = match ty.ty.array_specifier.as_ref() { 697 | Some(x) => Some(Box::new(lift(state, x))), 698 | None => None 699 | }; 700 | let precision = get_precision(&ty.qualifier); 701 | Type { 702 | kind, 703 | precision, 704 | array_sizes 705 | } 706 | } 707 | } 708 | 709 | impl LiftFrom<&syntax::TypeSpecifier> for Type { 710 | fn lift(state: &mut State, ty: &syntax::TypeSpecifier) -> Self { 711 | let kind = lift(state, &ty.ty); 712 | let array_sizes = ty.array_specifier.as_ref().map(|x| Box::new(lift(state, x))); 713 | Type { 714 | kind, 715 | precision: None, 716 | array_sizes 717 | } 718 | } 719 | } 720 | 721 | #[derive(Debug, Clone, PartialEq)] 722 | pub struct StructField { 723 | pub ty: Type, 724 | pub name: syntax::Identifier, 725 | } 726 | 727 | fn get_precision(qualifiers: &Option) -> Option{ 728 | let mut precision = None; 729 | for qual in qualifiers.iter().flat_map(|x| x.qualifiers.0.iter()) { 730 | match qual { 731 | syntax::TypeQualifierSpec::Precision(p) => { 732 | if precision.is_some() { 733 | panic!("Multiple precisions"); 734 | } 735 | precision = Some(p.clone()); 736 | } 737 | _ => {} 738 | } 739 | } 740 | precision 741 | } 742 | 743 | impl LiftFrom<&StructFieldSpecifier> for StructField { 744 | fn lift(state: &mut State, f: &StructFieldSpecifier) -> Self { 745 | let precision = get_precision(&f.qualifier); 746 | let mut ty: Type = lift(state, &f.ty); 747 | match &f.identifiers.0[..] { 748 | [ident] => { 749 | if let Some(a) = &ident.array_spec { 750 | ty.array_sizes = Some(Box::new(lift(state, a))); 751 | } 752 | StructField{ ty, name: ident.ident.clone() } 753 | } 754 | _ => panic!("bad number of identifiers") 755 | } 756 | } 757 | } 758 | 759 | #[derive(Debug, Clone, PartialEq)] 760 | pub struct StructFields { 761 | pub fields: Vec 762 | } 763 | 764 | impl LiftFrom<&StructSpecifier> for StructFields { 765 | fn lift(state: &mut State, s: &StructSpecifier) -> Self { 766 | let fields = s.fields.0.iter().map(|field| { 767 | lift(state, field) 768 | }).collect(); 769 | Self { fields } 770 | } 771 | } 772 | 773 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] 774 | pub enum RunClass { 775 | Unknown, 776 | Scalar, 777 | Vector, 778 | Dependent(u32), 779 | } 780 | 781 | impl RunClass { 782 | pub fn merge(self, run_class: RunClass) -> RunClass { 783 | match (self, run_class) { 784 | (RunClass::Vector, _) | (_, RunClass::Vector) => RunClass::Vector, 785 | (RunClass::Dependent(x), RunClass::Dependent(y)) => RunClass::Dependent(x | y), 786 | (RunClass::Unknown, _) | (_, RunClass::Dependent(..)) => run_class, 787 | _ => self, 788 | } 789 | } 790 | } 791 | 792 | #[derive(Debug, Clone, PartialEq)] 793 | pub enum SymDecl { 794 | NativeFunction(FunctionType, Option<&'static str>), 795 | UserFunction(Rc, RunClass), 796 | Local(StorageClass, Type, RunClass), 797 | Global(StorageClass, Option, Type, RunClass), 798 | Struct(StructFields) 799 | } 800 | 801 | #[derive(Clone, Debug, PartialEq, Copy, Eq, Hash)] 802 | pub struct SymRef(u32); 803 | 804 | #[derive(Debug)] 805 | struct Scope { 806 | name: String, 807 | names: HashMap, 808 | } 809 | impl Scope { 810 | fn new(name: String) -> Self { Scope { name, names: HashMap::new() }} 811 | } 812 | 813 | #[derive(Debug)] 814 | pub struct State { 815 | scopes: Vec, 816 | syms: Vec>, 817 | in_function: Option, 818 | run_class_changed: Cell, 819 | last_declaration: SymRef, 820 | branch_run_class: RunClass, 821 | branch_declaration: SymRef, 822 | modified_globals: RefCell>, 823 | } 824 | 825 | impl State { 826 | pub fn new() -> Self { 827 | State { 828 | scopes: Vec::new(), 829 | syms: Vec::new(), 830 | in_function: None, 831 | run_class_changed: Cell::new(false), 832 | last_declaration: SymRef(0), 833 | branch_run_class: RunClass::Unknown, 834 | branch_declaration: SymRef(0), 835 | modified_globals: RefCell::new(Vec::new()), 836 | } 837 | } 838 | 839 | pub fn lookup(&self, name: &str) -> Option { 840 | for s in self.scopes.iter().rev() { 841 | if let Some(sym) = s.names.get(name) { 842 | return Some(*sym); 843 | } 844 | } 845 | return None; 846 | } 847 | 848 | fn declare(&mut self, name: &str, decl: SymDecl) -> SymRef { 849 | let s = SymRef(self.syms.len() as u32); 850 | self.syms.push(RefCell::new(Symbol{ name: name.into(), decl})); 851 | self.scopes.last_mut().unwrap().names.insert(name.into(), s); 852 | s 853 | } 854 | 855 | pub fn sym(&self, sym: SymRef) -> Ref { 856 | self.syms[sym.0 as usize].borrow() 857 | } 858 | 859 | pub fn sym_mut(&mut self, sym: SymRef) -> &mut Symbol { 860 | self.syms[sym.0 as usize].get_mut() 861 | } 862 | 863 | pub fn lookup_sym_mut(&mut self, name: &str) -> Option<&mut Symbol> { 864 | self.lookup(name).map(move |x| self.syms[x.0 as usize].get_mut()) 865 | } 866 | 867 | fn push_scope(&mut self, name: String) { 868 | self.scopes.push(Scope::new(name)); 869 | } 870 | fn pop_scope(&mut self) { 871 | self.scopes.pop(); 872 | } 873 | 874 | fn return_run_class(&self, mut new_run_class: RunClass) { 875 | new_run_class = self.branch_run_class.merge(new_run_class); 876 | if let Some(sym) = self.in_function { 877 | let mut b = self.syms[sym.0 as usize].borrow_mut(); 878 | if let SymDecl::UserFunction(_, ref mut run_class) = b.decl { 879 | *run_class = run_class.merge(new_run_class); 880 | } 881 | } 882 | } 883 | 884 | pub fn function_definition(&self, name: SymRef) -> Option<(Rc, RunClass)> { 885 | if let SymDecl::UserFunction(ref fd, ref run_class) = &self.sym(name).decl { 886 | Some((fd.clone(), *run_class)) 887 | } else { 888 | None 889 | } 890 | } 891 | 892 | fn merge_run_class(&self, sym: SymRef, mut new_run_class: RunClass) -> RunClass { 893 | if sym.0 <= self.branch_declaration.0 { 894 | new_run_class = self.branch_run_class.merge(new_run_class); 895 | } 896 | let mut b = self.syms[sym.0 as usize].borrow_mut(); 897 | let mut old_run_class = new_run_class; 898 | if let SymDecl::Local(_, _, ref mut run_class) = b.decl { 899 | old_run_class = *run_class; 900 | new_run_class = old_run_class.merge(new_run_class); 901 | *run_class = new_run_class; 902 | } 903 | if old_run_class != RunClass::Unknown && old_run_class != new_run_class { 904 | self.run_class_changed.set(true); 905 | } 906 | new_run_class 907 | } 908 | } 909 | 910 | /// A declaration. 911 | #[derive(Clone, Debug, PartialEq)] 912 | pub enum Declaration { 913 | FunctionPrototype(FunctionPrototype), 914 | StructDefinition(SymRef), 915 | InitDeclaratorList(InitDeclaratorList), 916 | Precision(PrecisionQualifier, TypeSpecifier), 917 | Block(Block), 918 | Global(TypeQualifier, Vec) 919 | } 920 | 921 | /// A general purpose block, containing fields and possibly a list of declared identifiers. Semantic 922 | /// is given with the storage qualifier. 923 | #[derive(Clone, Debug, PartialEq)] 924 | pub struct Block { 925 | pub qualifier: TypeQualifier, 926 | pub name: Identifier, 927 | pub fields: Vec, 928 | pub identifier: Option 929 | } 930 | 931 | /// Function identifier. 932 | #[derive(Clone, Debug, PartialEq)] 933 | pub enum FunIdentifier { 934 | Identifier(SymRef), 935 | Constructor(Type) 936 | } 937 | 938 | /// Function prototype. 939 | #[derive(Clone, Debug, PartialEq)] 940 | pub struct FunctionPrototype { 941 | pub ty: Type, 942 | pub name: Identifier, 943 | pub parameters: Vec 944 | } 945 | 946 | /// Function parameter declaration. 947 | #[derive(Clone, Debug, PartialEq)] 948 | pub enum FunctionParameterDeclaration { 949 | Named(Option, FunctionParameterDeclarator), 950 | Unnamed(Option, TypeSpecifier) 951 | } 952 | 953 | /// Function parameter declarator. 954 | #[derive(Clone, Debug, PartialEq)] 955 | pub struct FunctionParameterDeclarator { 956 | pub ty: Type, 957 | pub name: Identifier, 958 | pub sym: SymRef, 959 | } 960 | 961 | /// Init declarator list. 962 | #[derive(Clone, Debug, PartialEq)] 963 | pub struct InitDeclaratorList { 964 | // XXX it feels like separating out the type and the names is better than 965 | // head and tail 966 | // Also, it might be nice to separate out type definitions from name definitions 967 | pub head: SingleDeclaration, 968 | pub tail: Vec 969 | } 970 | 971 | /// Type qualifier. 972 | #[derive(Clone, Debug, PartialEq)] 973 | pub struct TypeQualifier { 974 | pub qualifiers: NonEmpty 975 | } 976 | 977 | fn lift_type_qualifier_for_declaration(state: &mut State, q: &Option) -> Option { 978 | q.as_ref().and_then(|x| { 979 | NonEmpty::from_non_empty_iter(x.qualifiers.0.iter().flat_map(|x| { 980 | match x { 981 | syntax::TypeQualifierSpec::Precision(_) => None, 982 | syntax::TypeQualifierSpec::Interpolation(i) => None, 983 | syntax::TypeQualifierSpec::Invariant => Some(TypeQualifierSpec::Invariant), 984 | syntax::TypeQualifierSpec::Layout(l) => Some(TypeQualifierSpec::Layout(l.clone())), 985 | syntax::TypeQualifierSpec::Precise => Some(TypeQualifierSpec::Precise), 986 | syntax::TypeQualifierSpec::Storage(s) => None, 987 | } 988 | })).map(|x| TypeQualifier{ qualifiers: x}) 989 | }) 990 | } 991 | 992 | fn lift_type_qualifier_for_parameter(state: &mut State, q: &Option) -> Option { 993 | let mut qp: Option = None; 994 | if let Some(q) = q { 995 | for x in &q.qualifiers.0 { 996 | match (&qp, x) { 997 | (None, syntax::TypeQualifierSpec::Storage(s)) => { 998 | match s { 999 | syntax::StorageQualifier::Const => { qp = Some(ParameterQualifier::Const) } 1000 | syntax::StorageQualifier::In => { qp = Some(ParameterQualifier::In) } 1001 | syntax::StorageQualifier::Out => { qp = Some(ParameterQualifier::Out) }, 1002 | syntax::StorageQualifier::InOut => { qp = Some(ParameterQualifier::InOut) }, 1003 | _ => panic!("Bad storage qualifier for parameter") 1004 | } 1005 | } 1006 | (_, syntax::TypeQualifierSpec::Precision(_)) => { } 1007 | _ => panic!("Bad parameter qualifier {:?}", x) 1008 | 1009 | } 1010 | } 1011 | } 1012 | qp 1013 | } 1014 | 1015 | #[derive(Clone, Debug, PartialEq)] 1016 | pub enum ParameterQualifier { 1017 | Const, 1018 | In, 1019 | InOut, 1020 | Out, 1021 | } 1022 | 1023 | #[derive(Clone, Debug, PartialEq)] 1024 | pub enum MemoryQualifier { 1025 | Coherent, 1026 | Volatile, 1027 | Restrict, 1028 | ReadOnly, 1029 | WriteOnly, 1030 | } 1031 | 1032 | /// Type qualifier spec. 1033 | #[derive(Clone, Debug, PartialEq)] 1034 | pub enum TypeQualifierSpec { 1035 | Layout(syntax::LayoutQualifier), 1036 | Invariant, 1037 | Parameter(ParameterQualifier), 1038 | Memory(MemoryQualifier), 1039 | Precise 1040 | } 1041 | 1042 | 1043 | /// Single declaration. 1044 | #[derive(Clone, Debug, PartialEq)] 1045 | pub struct SingleDeclaration { 1046 | pub ty: Type, 1047 | pub ty_def: Option, 1048 | pub qualifier: Option, 1049 | pub name: SymRef, 1050 | pub initializer: Option 1051 | } 1052 | 1053 | /// A single declaration with implicit, already-defined type. 1054 | #[derive(Clone, Debug, PartialEq)] 1055 | pub struct SingleDeclarationNoType { 1056 | pub ident: ArrayedIdentifier, 1057 | pub initializer: Option 1058 | } 1059 | 1060 | /// Initializer. 1061 | #[derive(Clone, Debug, PartialEq)] 1062 | pub enum Initializer { 1063 | Simple(Box), 1064 | List(NonEmpty) 1065 | } 1066 | 1067 | impl From for Initializer { 1068 | fn from(e: Expr) -> Self { 1069 | Initializer::Simple(Box::new(e)) 1070 | } 1071 | } 1072 | 1073 | #[derive(Clone, Debug, PartialEq)] 1074 | pub struct Expr { 1075 | pub kind: ExprKind, 1076 | pub ty: Type 1077 | } 1078 | 1079 | #[derive(Clone, Debug, PartialEq)] 1080 | pub enum FieldSet { 1081 | Rgba, 1082 | Xyzw, 1083 | Stpq, 1084 | } 1085 | 1086 | #[derive(Clone, Debug, PartialEq)] 1087 | pub struct SwizzleSelector { 1088 | pub field_set: FieldSet, 1089 | pub components: Vec 1090 | } 1091 | 1092 | impl SwizzleSelector { 1093 | fn parse(s: &str) -> Self { 1094 | let mut components = Vec::new(); 1095 | let mut field_set = Vec::new(); 1096 | 1097 | for c in s.chars() { 1098 | match c { 1099 | 'r' => { components.push(0); field_set.push(FieldSet::Rgba); } 1100 | 'x' => { components.push(0); field_set.push(FieldSet::Xyzw); } 1101 | 's' => { components.push(0); field_set.push(FieldSet::Stpq); } 1102 | 1103 | 'g' => { components.push(1); field_set.push(FieldSet::Rgba); } 1104 | 'y' => { components.push(1); field_set.push(FieldSet::Xyzw); } 1105 | 't' => { components.push(1); field_set.push(FieldSet::Stpq); } 1106 | 1107 | 'b' => { components.push(2); field_set.push(FieldSet::Rgba); } 1108 | 'z' => { components.push(2); field_set.push(FieldSet::Xyzw); } 1109 | 'p' => { components.push(2); field_set.push(FieldSet::Stpq); } 1110 | 1111 | 'a' => { components.push(3); field_set.push(FieldSet::Rgba); } 1112 | 'w' => { components.push(3); field_set.push(FieldSet::Xyzw); } 1113 | 'q' => { components.push(3); field_set.push(FieldSet::Stpq); } 1114 | _ => panic!("bad selector") 1115 | } 1116 | } 1117 | 1118 | let first = &field_set[0]; 1119 | assert!(field_set.iter().all(|item| item == first)); 1120 | assert!(components.len() <= 4); 1121 | SwizzleSelector { field_set: first.clone(), components } 1122 | } 1123 | 1124 | pub fn to_string(&self) -> String { 1125 | let mut s = String::new(); 1126 | let fs = match self.field_set { 1127 | FieldSet::Rgba => ['r','g','b','a'], 1128 | FieldSet::Xyzw => ['x', 'y','z','w'], 1129 | FieldSet::Stpq => ['s','t','p','q'], 1130 | }; 1131 | for i in &self.components { 1132 | s.push(fs[*i as usize]) 1133 | } 1134 | s 1135 | } 1136 | } 1137 | 1138 | /// The most general form of an expression. As you can see if you read the variant list, in GLSL, an 1139 | /// assignment is an expression. This is a bit silly but think of an assignment as a statement first 1140 | /// then an expression which evaluates to what the statement “returns”. 1141 | /// 1142 | /// An expression is either an assignment or a list (comma) of assignments. 1143 | #[derive(Clone, Debug, PartialEq)] 1144 | pub enum ExprKind { 1145 | /// A variable expression, using an identifier. 1146 | Variable(SymRef), 1147 | /// Integral constant expression. 1148 | IntConst(i32), 1149 | /// Unsigned integral constant expression. 1150 | UIntConst(u32), 1151 | /// Boolean constant expression. 1152 | BoolConst(bool), 1153 | /// Single precision floating expression. 1154 | FloatConst(f32), 1155 | /// Double precision floating expression. 1156 | DoubleConst(f64), 1157 | /// A unary expression, gathering a single expression and a unary operator. 1158 | Unary(UnaryOp, Box), 1159 | /// A binary expression, gathering two expressions and a binary operator. 1160 | Binary(BinaryOp, Box, Box), 1161 | /// A ternary conditional expression, gathering three expressions. 1162 | Ternary(Box, Box, Box), 1163 | /// An assignment is also an expression. Gathers an expression that defines what to assign to, an 1164 | /// assignment operator and the value to associate with. 1165 | Assignment(Box, AssignmentOp, Box), 1166 | /// Add an array specifier to an expression. 1167 | Bracket(Box, Box), 1168 | /// A functional call. It has a function identifier and a list of expressions (arguments). 1169 | FunCall(FunIdentifier, Vec), 1170 | /// An expression associated with a field selection (struct). 1171 | Dot(Box, Identifier), 1172 | /// An expression associated with a component selection 1173 | SwizzleSelector(Box, SwizzleSelector), 1174 | /// Post-incrementation of an expression. 1175 | PostInc(Box), 1176 | /// Post-decrementation of an expression. 1177 | PostDec(Box), 1178 | /// An expression that contains several, separated with comma. 1179 | Comma(Box, Box), 1180 | /// A temporary condition variable 1181 | Cond(usize, Box), 1182 | CondMask, 1183 | } 1184 | 1185 | /* 1186 | impl From for Expr { 1187 | fn from(x: i32) -> Expr { 1188 | ExprKind::IntConst(x) 1189 | } 1190 | } 1191 | 1192 | impl From for Expr { 1193 | fn from(x: u32) -> Expr { 1194 | Expr::UIntConst(x) 1195 | } 1196 | } 1197 | 1198 | impl From for Expr { 1199 | fn from(x: bool) -> Expr { 1200 | Expr::BoolConst(x) 1201 | } 1202 | } 1203 | 1204 | impl From for Expr { 1205 | fn from(x: f32) -> Expr { 1206 | Expr::FloatConst(x) 1207 | } 1208 | } 1209 | 1210 | impl From for Expr { 1211 | fn from(x: f64) -> Expr { 1212 | Expr::DoubleConst(x) 1213 | } 1214 | } 1215 | */ 1216 | /// Starting rule. 1217 | #[derive(Clone, Debug, PartialEq)] 1218 | pub struct TranslationUnit(pub NonEmpty); 1219 | 1220 | impl TranslationUnit { 1221 | /// Construct a translation unit from an iterator. 1222 | /// 1223 | /// # Errors 1224 | /// 1225 | /// `None` if the iterator yields no value. 1226 | pub fn from_iter(iter: I) -> Option where I: IntoIterator { 1227 | NonEmpty::from_non_empty_iter(iter).map(TranslationUnit) 1228 | } 1229 | } 1230 | 1231 | impl Deref for TranslationUnit { 1232 | type Target = NonEmpty; 1233 | 1234 | fn deref(&self) -> &Self::Target { 1235 | &self.0 1236 | } 1237 | } 1238 | 1239 | impl DerefMut for TranslationUnit { 1240 | fn deref_mut(&mut self) -> &mut Self::Target { 1241 | &mut self.0 1242 | } 1243 | } 1244 | 1245 | impl IntoIterator for TranslationUnit { 1246 | type IntoIter = as IntoIterator>::IntoIter; 1247 | type Item = ExternalDeclaration; 1248 | 1249 | fn into_iter(self) -> Self::IntoIter { 1250 | self.0.into_iter() 1251 | } 1252 | } 1253 | 1254 | impl<'a> IntoIterator for &'a TranslationUnit { 1255 | type IntoIter = <&'a NonEmpty as IntoIterator>::IntoIter; 1256 | type Item = &'a ExternalDeclaration; 1257 | 1258 | fn into_iter(self) -> Self::IntoIter { 1259 | (&self.0).into_iter() 1260 | } 1261 | } 1262 | 1263 | impl<'a> IntoIterator for &'a mut TranslationUnit { 1264 | type IntoIter = <&'a mut NonEmpty as IntoIterator>::IntoIter; 1265 | type Item = &'a mut ExternalDeclaration; 1266 | 1267 | fn into_iter(self) -> Self::IntoIter { 1268 | (&mut self.0).into_iter() 1269 | } 1270 | } 1271 | 1272 | /// External declaration. 1273 | #[derive(Clone, Debug, PartialEq)] 1274 | pub enum ExternalDeclaration { 1275 | Preprocessor(syntax::Preprocessor), 1276 | FunctionDefinition(Rc), 1277 | Declaration(Declaration) 1278 | } 1279 | 1280 | /// Function definition. 1281 | #[derive(Clone, Debug, PartialEq)] 1282 | pub struct FunctionDefinition { 1283 | pub prototype: FunctionPrototype, 1284 | pub body: CompoundStatement, 1285 | pub globals: Vec, 1286 | } 1287 | 1288 | /// Compound statement (with no new scope). 1289 | #[derive(Clone, Debug, PartialEq)] 1290 | pub struct CompoundStatement { 1291 | pub statement_list: Vec 1292 | } 1293 | 1294 | impl CompoundStatement { 1295 | pub fn new() -> Self { 1296 | CompoundStatement { statement_list: Vec::new() } 1297 | } 1298 | } 1299 | 1300 | impl FromIterator for CompoundStatement { 1301 | fn from_iter(iter: T) -> Self where T: IntoIterator { 1302 | CompoundStatement { 1303 | statement_list: iter.into_iter().collect() 1304 | } 1305 | } 1306 | } 1307 | 1308 | /// Statement. 1309 | #[derive(Clone, Debug, PartialEq)] 1310 | pub enum Statement { 1311 | Compound(Box), 1312 | Simple(Box) 1313 | } 1314 | 1315 | /// Simple statement. 1316 | #[derive(Clone, Debug, PartialEq)] 1317 | pub enum SimpleStatement { 1318 | Declaration(Declaration), 1319 | Expression(ExprStatement), 1320 | Selection(SelectionStatement), 1321 | Switch(SwitchStatement), 1322 | Iteration(IterationStatement), 1323 | Jump(JumpStatement) 1324 | } 1325 | 1326 | impl SimpleStatement { 1327 | /// Create a new expression statement. 1328 | pub fn new_expr(expr: E) -> Self where E: Into { 1329 | SimpleStatement::Expression(Some(expr.into())) 1330 | } 1331 | 1332 | /// Create a new selection statement (if / else). 1333 | pub fn new_if_else( 1334 | ife: If, 1335 | truee: True, 1336 | falsee: False 1337 | ) -> Self 1338 | where If: Into, 1339 | True: Into, 1340 | False: Into { 1341 | SimpleStatement::Selection( 1342 | SelectionStatement { 1343 | cond: Box::new(ife.into()), 1344 | rest: SelectionRestStatement::Else(Box::new(truee.into()), Box::new(falsee.into())) 1345 | } 1346 | ) 1347 | } 1348 | 1349 | /// Create a new while statement. 1350 | pub fn new_while( 1351 | cond: C, 1352 | body: S 1353 | ) -> Self 1354 | where C: Into, 1355 | S: Into { 1356 | SimpleStatement::Iteration( 1357 | IterationStatement::While(cond.into(), Box::new(body.into())) 1358 | ) 1359 | } 1360 | 1361 | /// Create a new do-while statement. 1362 | pub fn new_do_while( 1363 | body: S, 1364 | cond: C 1365 | ) -> Self 1366 | where S: Into, 1367 | C: Into { 1368 | SimpleStatement::Iteration( 1369 | IterationStatement::DoWhile(Box::new(body.into()), Box::new(cond.into())) 1370 | ) 1371 | } 1372 | } 1373 | 1374 | /// Expression statement. 1375 | pub type ExprStatement = Option; 1376 | 1377 | /// Selection statement. 1378 | #[derive(Clone, Debug, PartialEq)] 1379 | pub struct SelectionStatement { 1380 | pub cond: Box, 1381 | pub rest: SelectionRestStatement 1382 | } 1383 | 1384 | /// Condition. 1385 | #[derive(Clone, Debug, PartialEq)] 1386 | pub enum Condition { 1387 | Expr(Box), 1388 | } 1389 | 1390 | impl From for Condition { 1391 | fn from(expr: Expr) -> Self { 1392 | Condition::Expr(Box::new(expr)) 1393 | } 1394 | } 1395 | 1396 | /// Selection rest statement. 1397 | #[derive(Clone, Debug, PartialEq)] 1398 | pub enum SelectionRestStatement { 1399 | /// Body of the if. 1400 | Statement(Box), 1401 | /// The first argument is the body of the if, the rest is the next statement. 1402 | Else(Box, Box) 1403 | } 1404 | 1405 | /// Switch statement. 1406 | #[derive(Clone, Debug, PartialEq)] 1407 | pub struct SwitchStatement { 1408 | pub head: Box, 1409 | pub cases: Vec 1410 | } 1411 | 1412 | /// Case label statement. 1413 | #[derive(Clone, Debug, PartialEq)] 1414 | pub enum CaseLabel { 1415 | Case(Box), 1416 | Def 1417 | } 1418 | 1419 | /// An individual case 1420 | #[derive(Clone, Debug, PartialEq)] 1421 | pub struct Case { 1422 | pub label: CaseLabel, 1423 | pub stmts: Vec 1424 | } 1425 | 1426 | /// Iteration statement. 1427 | #[derive(Clone, Debug, PartialEq)] 1428 | pub enum IterationStatement { 1429 | While(Condition, Box), 1430 | DoWhile(Box, Box), 1431 | For(ForInitStatement, ForRestStatement, Box) 1432 | } 1433 | 1434 | /// For init statement. 1435 | #[derive(Clone, Debug, PartialEq)] 1436 | pub enum ForInitStatement { 1437 | Expression(Option), 1438 | Declaration(Box) 1439 | } 1440 | 1441 | /// For init statement. 1442 | #[derive(Clone, Debug, PartialEq)] 1443 | pub struct ForRestStatement { 1444 | pub condition: Option, 1445 | pub post_expr: Option> 1446 | } 1447 | 1448 | /// Jump statement. 1449 | #[derive(Clone, Debug, PartialEq)] 1450 | pub enum JumpStatement { 1451 | Continue, 1452 | Break, 1453 | Return(Option>), 1454 | Discard 1455 | } 1456 | 1457 | trait NonEmptyExt { 1458 | fn map U>(&self, s: &mut State, f: F) -> NonEmpty; 1459 | fn new(x: T) -> NonEmpty; 1460 | } 1461 | 1462 | impl NonEmptyExt for NonEmpty { 1463 | fn map U>(&self, s: &mut State, mut f: F) -> NonEmpty { 1464 | NonEmpty::from_non_empty_iter(self.into_iter().map(|x| f(s, &x))).unwrap() 1465 | } 1466 | fn new(x: T) -> NonEmpty { 1467 | NonEmpty::from_non_empty_iter(vec![x].into_iter()).unwrap() 1468 | } 1469 | } 1470 | 1471 | 1472 | fn translate_initializater(state: &mut State, i: &syntax::Initializer) -> Initializer { 1473 | match i { 1474 | syntax::Initializer::Simple(i) => Initializer::Simple(Box::new(translate_expression(state, i))), 1475 | _ => panic!() 1476 | } 1477 | } 1478 | 1479 | fn translate_struct_declaration(state: &mut State, d: &syntax::SingleDeclaration) -> Declaration { 1480 | let mut ty = d.ty.clone(); 1481 | let ty_def = match &ty.ty.ty { 1482 | TypeSpecifierNonArray::Struct(s) => { 1483 | let decl = SymDecl::Struct(lift(state, s)); 1484 | Some(state.declare(s.name.as_ref().unwrap().as_str(), decl)) 1485 | } 1486 | _ => None 1487 | }; 1488 | 1489 | let ty_def = ty_def.expect("Must be type definition"); 1490 | 1491 | Declaration::StructDefinition(ty_def) 1492 | } 1493 | 1494 | fn translate_variable_declaration(state: &mut State, d: &syntax::InitDeclaratorList, default_run_class: RunClass) -> Declaration { 1495 | let mut ty = d.head.ty.clone(); 1496 | ty.ty.array_specifier = d.head.array_specifier.clone(); 1497 | let ty_def = match &ty.ty.ty { 1498 | TypeSpecifierNonArray::Struct(s) => { 1499 | let decl = SymDecl::Struct(lift(state, s)); 1500 | Some(state.declare(s.name.as_ref().unwrap().as_str(), decl)) 1501 | } 1502 | _ => None 1503 | }; 1504 | 1505 | let mut ty: Type = lift(state, &d.head.ty); 1506 | if let Some(array) = &d.head.array_specifier { 1507 | ty.array_sizes = Some(Box::new(lift(state, array))) 1508 | } 1509 | 1510 | let (sym, decl) = match d.head.name.as_ref() { 1511 | Some(name) => { 1512 | let mut storage = StorageClass::None; 1513 | let mut interpolation = None; 1514 | for qual in d.head.ty.qualifier.iter().flat_map(|x| x.qualifiers.0.iter()) { 1515 | match qual { 1516 | syntax::TypeQualifierSpec::Storage(s) => { 1517 | match (&storage, s) { 1518 | (StorageClass::None, syntax::StorageQualifier::Out) => { 1519 | storage = StorageClass::Out 1520 | } 1521 | (StorageClass::None, syntax::StorageQualifier::In) => { 1522 | storage = StorageClass::In 1523 | } 1524 | (StorageClass::None, syntax::StorageQualifier::Uniform) => { 1525 | storage = StorageClass::Uniform 1526 | } 1527 | (StorageClass::None, syntax::StorageQualifier::Const) => { 1528 | storage = StorageClass::Const 1529 | } 1530 | _ => panic!("bad storage {:?}", (storage, s)) 1531 | } 1532 | } 1533 | syntax::TypeQualifierSpec::Interpolation(i) => { 1534 | match (&interpolation, i) { 1535 | (None, i) => { 1536 | interpolation = Some(i.clone()) 1537 | } 1538 | _ => panic!("multiple interpolation") 1539 | } 1540 | } 1541 | _ => {} 1542 | } 1543 | } 1544 | let decl = if state.in_function.is_some() { 1545 | let run_class = match storage { 1546 | StorageClass::Const => RunClass::Scalar, 1547 | StorageClass::None => default_run_class, 1548 | _ => panic!("bad local storage {:?}", storage) 1549 | }; 1550 | SymDecl::Local(storage, ty.clone(), run_class) 1551 | } else { 1552 | let run_class = match storage { 1553 | StorageClass::Const | StorageClass::Uniform => RunClass::Scalar, 1554 | StorageClass::In | StorageClass::Out 1555 | if interpolation == Some(syntax::InterpolationQualifier::Flat) => RunClass::Scalar, 1556 | _ => RunClass::Vector, 1557 | }; 1558 | SymDecl::Global(storage, interpolation, ty.clone(), run_class) 1559 | }; 1560 | (state.declare(d.head.name.as_ref().unwrap().as_str(), decl.clone()), decl) 1561 | } 1562 | None => panic!() 1563 | }; 1564 | 1565 | let head = SingleDeclaration { 1566 | qualifier: lift_type_qualifier_for_declaration(state, &d.head.ty.qualifier), 1567 | name: sym, 1568 | ty, 1569 | ty_def, 1570 | initializer: d.head.initializer.as_ref().map(|x| translate_initializater(state, x)), 1571 | }; 1572 | 1573 | let tail = d.tail.iter().map(|d| { 1574 | if let Some(array) = &d.ident.array_spec { 1575 | panic!("unhandled array") 1576 | } 1577 | state.declare(d.ident.ident.as_str(), decl.clone()); 1578 | SingleDeclarationNoType { 1579 | ident: d.ident.clone(), 1580 | initializer: d.initializer.as_ref().map(|x| translate_initializater(state, x)), 1581 | } 1582 | }).collect(); 1583 | Declaration::InitDeclaratorList(InitDeclaratorList { 1584 | head, 1585 | tail 1586 | }) 1587 | } 1588 | 1589 | fn translate_init_declarator_list(state: &mut State, l: &syntax::InitDeclaratorList, default_run_class: RunClass) -> Declaration { 1590 | match &l.head.name { 1591 | Some(name) => { 1592 | translate_variable_declaration(state, l, default_run_class) 1593 | } 1594 | None => { 1595 | translate_struct_declaration(state, &l.head) 1596 | } 1597 | } 1598 | 1599 | } 1600 | 1601 | fn translate_declaration(state: &mut State, d: &syntax::Declaration, default_run_class: RunClass) -> Declaration { 1602 | match d { 1603 | syntax::Declaration::Block(b) => Declaration::Block(panic!()), 1604 | syntax::Declaration::FunctionPrototype(p) => Declaration::FunctionPrototype(translate_function_prototype(state, p)), 1605 | syntax::Declaration::Global(ty, ids) => { 1606 | // glsl non-es supports requalifying variables 1607 | // we don't right now 1608 | Declaration::Global(panic!(), panic!()) 1609 | }, 1610 | syntax::Declaration::InitDeclaratorList(dl) => translate_init_declarator_list(state, dl, default_run_class), 1611 | syntax::Declaration::Precision(p, ts) => Declaration::Precision(p.clone(), ts.clone()), 1612 | } 1613 | } 1614 | 1615 | fn is_vector(ty: &Type) -> bool { 1616 | match ty.kind { 1617 | TypeKind::Vec2 | TypeKind::Vec3 | TypeKind::Vec4 | 1618 | TypeKind::IVec2 | TypeKind::IVec3 | TypeKind::IVec4 => { 1619 | ty.array_sizes == None 1620 | } 1621 | _ => false 1622 | } 1623 | } 1624 | 1625 | fn index_matrix(ty: &Type) -> Option { 1626 | use TypeKind::*; 1627 | if ty.array_sizes != None { 1628 | return None 1629 | } 1630 | Some(match ty.kind { 1631 | Mat2 => Vec2, 1632 | Mat3 => Vec3, 1633 | Mat4 => Vec4, 1634 | Mat23 => Vec3, 1635 | Mat24 => Vec4, 1636 | Mat32 => Vec2, 1637 | Mat34 => Vec4, 1638 | Mat42 => Vec2, 1639 | Mat43 => Vec3, 1640 | DMat2 => DVec2, 1641 | DMat3 => DVec3, 1642 | DMat4 => DVec4, 1643 | DMat23 => DVec3, 1644 | DMat24 => DVec4, 1645 | DMat32 => DVec2, 1646 | DMat34 => DVec4, 1647 | DMat42 => DVec2, 1648 | DMat43 => DVec3, 1649 | _ => return None 1650 | }) 1651 | } 1652 | 1653 | 1654 | 1655 | fn is_ivec(ty: &Type) -> bool { 1656 | match ty.kind { 1657 | TypeKind::IVec2 | TypeKind::IVec3 | TypeKind::IVec4 => { 1658 | ty.array_sizes == None 1659 | } 1660 | _ => false 1661 | } 1662 | } 1663 | 1664 | fn compatible_type(lhs: &Type, rhs: &Type) -> bool { 1665 | 1666 | // XXX: use an underlying type helper 1667 | if lhs == &Type::new(TypeKind::Double) && 1668 | rhs == &Type::new(TypeKind::Float) { 1669 | true 1670 | } else if rhs == &Type::new(TypeKind::Double) && 1671 | lhs == &Type::new(TypeKind::Float) { 1672 | true 1673 | } else if rhs == &Type::new(TypeKind::Int) && 1674 | (lhs == &Type::new(TypeKind::Float) || lhs == &Type::new(TypeKind::Double)) { 1675 | true 1676 | } else if (rhs == &Type::new(TypeKind::Float) || rhs == &Type::new(TypeKind::Double)) && 1677 | lhs == &Type::new(TypeKind::Int) { 1678 | true 1679 | } else if (rhs == &Type::new(TypeKind::Vec2) || rhs == &Type::new(TypeKind::DVec2)) && 1680 | lhs == &Type::new(TypeKind::IVec2) { 1681 | true 1682 | } else if rhs == &Type::new(TypeKind::IVec2) && 1683 | (lhs == &Type::new(TypeKind::Vec2) || lhs == &Type::new(TypeKind::DVec2)) { 1684 | true 1685 | } else { 1686 | lhs.kind == rhs.kind && lhs.array_sizes == rhs.array_sizes 1687 | } 1688 | } 1689 | 1690 | fn promoted_type(lhs: &Type, rhs: &Type) -> Type { 1691 | if lhs == &Type::new(TypeKind::Double) && 1692 | rhs == &Type::new(TypeKind::Float) { 1693 | Type::new(TypeKind::Double) 1694 | } else if lhs == &Type::new(TypeKind::Float) && 1695 | rhs == &Type::new(TypeKind::Double) { 1696 | Type::new(TypeKind::Double) 1697 | } else if lhs == &Type::new(TypeKind::Int) && 1698 | rhs == &Type::new(TypeKind::Double) { 1699 | Type::new(TypeKind::Double) 1700 | } else if is_vector(&lhs) && ( 1701 | rhs == &Type::new(TypeKind::Float) || 1702 | rhs == &Type::new(TypeKind::Double) || 1703 | rhs == &Type::new(TypeKind::Int) 1704 | ) { 1705 | // scalars promote to vectors 1706 | lhs.clone() 1707 | } else if is_vector(&rhs) && ( 1708 | lhs == &Type::new(TypeKind::Float) || 1709 | lhs == &Type::new(TypeKind::Double) || 1710 | lhs == &Type::new(TypeKind::Int) 1711 | ) { 1712 | // scalars promote to vectors 1713 | rhs.clone() 1714 | } else if lhs == rhs { 1715 | lhs.clone() 1716 | } else if lhs.kind == rhs.kind { 1717 | if lhs.array_sizes == rhs.array_sizes { 1718 | // XXX: we need to be able to query the default precision here 1719 | match (&lhs.precision, &rhs.precision) { 1720 | (Some(PrecisionQualifier::High), _) => lhs.clone(), 1721 | (_, Some(PrecisionQualifier::High)) => rhs.clone(), 1722 | _ => panic!("precision mismatch") 1723 | } 1724 | } else { 1725 | panic!("array size mismatch") 1726 | } 1727 | } else { 1728 | assert_eq!(lhs, rhs); 1729 | lhs.clone() 1730 | } 1731 | } 1732 | 1733 | pub fn is_output(expr: &Expr, state: &State) -> Option { 1734 | match &expr.kind { 1735 | ExprKind::Variable(i) => { 1736 | match state.sym(*i).decl { 1737 | SymDecl::Global(storage, ..) => { 1738 | match storage { 1739 | StorageClass::Out => return Some(*i), 1740 | _ => {} 1741 | } 1742 | } 1743 | SymDecl::Local(storage, ..) => { 1744 | } 1745 | _ => { panic!("should be variable") } 1746 | } 1747 | } 1748 | ExprKind::SwizzleSelector(e, ..) => { 1749 | return is_output(e, state); 1750 | } 1751 | ExprKind::Bracket(e, ..) => { 1752 | return is_output(e, state); 1753 | } 1754 | ExprKind::Dot(e, ..) => { 1755 | return is_output(e, state); 1756 | } 1757 | _ => {} 1758 | }; 1759 | None 1760 | } 1761 | 1762 | fn translate_expression(state: &mut State, e: &syntax::Expr) -> Expr { 1763 | match e { 1764 | syntax::Expr::Variable(i) => { 1765 | let sym = match state.lookup(i.as_str()) { 1766 | Some(sym) => sym, 1767 | None => panic!("missing declaration {}", i.as_str()) 1768 | }; 1769 | let ty = match &state.sym(sym).decl { 1770 | SymDecl::Global(_, _, ty, _) => ty.clone(), 1771 | SymDecl::Local(_, ty, _) => ty.clone(), 1772 | _ => panic!("bad variable type") 1773 | }; 1774 | Expr { kind: ExprKind::Variable(sym), ty } 1775 | }, 1776 | syntax::Expr::Assignment(lhs, op, rhs) => { 1777 | let lhs = Box::new(translate_expression(state, lhs)); 1778 | let rhs = Box::new(translate_expression(state, rhs)); 1779 | let ty = if op == &AssignmentOp::Mult { 1780 | if lhs.ty.kind == TypeKind::Vec4 && rhs.ty.kind == TypeKind::Float { 1781 | lhs.ty.clone() 1782 | } else { 1783 | promoted_type(&lhs.ty, &rhs.ty) 1784 | } 1785 | } else { 1786 | promoted_type(&lhs.ty, &rhs.ty) 1787 | }; 1788 | if let Some(global) = is_output(&lhs, state) { 1789 | let mut globals = state.modified_globals.borrow_mut(); 1790 | if !globals.contains(&global) { 1791 | globals.push(global); 1792 | } 1793 | } 1794 | Expr { kind: ExprKind::Assignment(lhs, op.clone(), rhs), ty } 1795 | } 1796 | syntax::Expr::Binary(op, lhs, rhs) => { 1797 | let lhs = Box::new(translate_expression(state, lhs)); 1798 | let rhs = Box::new(translate_expression(state, rhs)); 1799 | let ty = if op == &BinaryOp::Mult { 1800 | if lhs.ty.kind == TypeKind::Mat3 && rhs.ty.kind == TypeKind::Vec3 { 1801 | rhs.ty.clone() 1802 | } else if lhs.ty.kind == TypeKind::Mat4 && rhs.ty.kind == TypeKind::Vec4 { 1803 | rhs.ty.clone() 1804 | } else if lhs.ty.kind == TypeKind::Mat2 && rhs.ty.kind == TypeKind::Vec2 { 1805 | rhs.ty.clone() 1806 | } else if lhs.ty.kind == TypeKind::Mat2 && rhs.ty.kind == TypeKind::Float { 1807 | lhs.ty.clone() 1808 | } else { 1809 | promoted_type(&lhs.ty, &rhs.ty) 1810 | } 1811 | } else { 1812 | promoted_type(&lhs.ty, &rhs.ty) 1813 | }; 1814 | 1815 | // comparison operators have a bool result 1816 | let ty = match op { 1817 | BinaryOp::Equal | 1818 | BinaryOp::GT | 1819 | BinaryOp::GTE | 1820 | BinaryOp::LT | 1821 | BinaryOp::LTE => Type::new(TypeKind::Bool), 1822 | _ => ty 1823 | }; 1824 | 1825 | 1826 | Expr { kind: ExprKind::Binary(op.clone(), lhs, rhs), ty} 1827 | } 1828 | syntax::Expr::Unary(op, e) => { 1829 | let e = Box::new(translate_expression(state, e)); 1830 | let ty = e.ty.clone(); 1831 | Expr { kind: ExprKind::Unary(op.clone(), e), ty} 1832 | } 1833 | syntax::Expr::BoolConst(b) => { 1834 | Expr { kind: ExprKind::BoolConst(*b), ty: Type::new(TypeKind::Bool) } 1835 | } 1836 | syntax::Expr::Comma(lhs, rhs) => { 1837 | let lhs = Box::new(translate_expression(state, lhs)); 1838 | let rhs = Box::new(translate_expression(state, rhs)); 1839 | assert_eq!(lhs.ty, rhs.ty); 1840 | let ty = lhs.ty.clone(); 1841 | Expr { kind: ExprKind::Comma(lhs, rhs), ty } 1842 | } 1843 | syntax::Expr::DoubleConst(d) => { 1844 | Expr { kind: ExprKind::DoubleConst(*d), ty: Type::new(TypeKind::Double) } 1845 | } 1846 | syntax::Expr::FloatConst(f) => { 1847 | Expr { kind: ExprKind::FloatConst(*f), ty: Type::new(TypeKind::Float) } 1848 | }, 1849 | syntax::Expr::FunCall(fun, params) => { 1850 | let ret_ty: Type; 1851 | let params: Vec = params.iter().map(|x| translate_expression(state, x)).collect(); 1852 | Expr { 1853 | kind: 1854 | ExprKind::FunCall( 1855 | match fun { 1856 | syntax::FunIdentifier::Identifier(i) => { 1857 | let sym = match state.lookup(i.as_str()) { 1858 | Some(s) => s, 1859 | None => panic!("missing symbol {}", i.as_str()) 1860 | }; 1861 | match &state.sym(sym).decl { 1862 | SymDecl::NativeFunction(fn_ty, _) => { 1863 | let mut ret = None; 1864 | for sig in &fn_ty.signatures { 1865 | let mut matching = true; 1866 | for (e, p) in params.iter().zip(sig.params.iter()) { 1867 | if !compatible_type(&e.ty, p) { 1868 | matching = false; 1869 | break; 1870 | } 1871 | } 1872 | if matching { 1873 | ret = Some(sig.ret.clone()); 1874 | break; 1875 | } 1876 | } 1877 | ret_ty = match ret { 1878 | Some(t) => t, 1879 | None => { 1880 | dbg!(&fn_ty.signatures); 1881 | dbg!(params.iter().map(|p| p).collect::>()); 1882 | panic!("no matching func {}", i.as_str()) 1883 | } 1884 | }; 1885 | }, 1886 | SymDecl::UserFunction(fd, _) => { 1887 | let mut globals = state.modified_globals.borrow_mut(); 1888 | for global in &fd.globals { 1889 | if !globals.contains(global) { 1890 | globals.push(*global); 1891 | } 1892 | } 1893 | let mut matching = true; 1894 | for (e, p) in params.iter().zip(fd.prototype.parameters.iter()) { 1895 | matching &= match p { 1896 | FunctionParameterDeclaration::Named(q, d) => { 1897 | match q { 1898 | Some(ParameterQualifier::InOut) | Some(ParameterQualifier::Out) => { 1899 | if let Some(global) = is_output(e, state) { 1900 | if !globals.contains(&global) { 1901 | globals.push(global); 1902 | } 1903 | } 1904 | } 1905 | _ => {} 1906 | } 1907 | compatible_type(&e.ty, &d.ty) 1908 | } 1909 | FunctionParameterDeclaration::Unnamed(_, d) => panic!(), 1910 | }; 1911 | } 1912 | assert!(matching); 1913 | ret_ty = fd.prototype.ty.clone(); 1914 | } 1915 | SymDecl::Struct(t) => { 1916 | ret_ty = Type::new(TypeKind::Struct(sym)) 1917 | } 1918 | _ => panic!("can only call functions") 1919 | }; 1920 | FunIdentifier::Identifier(sym) 1921 | }, 1922 | // array constructor 1923 | syntax::FunIdentifier::Expr(e) => { 1924 | let ty = match &**e { 1925 | syntax::Expr::Bracket(i, array) => { 1926 | let kind = match &**i { 1927 | syntax::Expr::Variable(i) => { 1928 | match i.as_str() { 1929 | "vec4" => TypeKind::Vec4, 1930 | "vec2" => TypeKind::Vec2, 1931 | _ => panic!("unexpected type constructor {:?}", i) 1932 | } 1933 | } 1934 | _ => panic!() 1935 | }; 1936 | 1937 | Type { kind, precision: None, array_sizes: Some(Box::new(lift(state, array)))} 1938 | } 1939 | _ => panic!() 1940 | }; 1941 | ret_ty = ty.clone(); 1942 | 1943 | FunIdentifier::Constructor(ty) 1944 | 1945 | } 1946 | }, 1947 | params 1948 | ), 1949 | ty: ret_ty, 1950 | } 1951 | } 1952 | syntax::Expr::IntConst(i) => { 1953 | Expr { kind: ExprKind::IntConst(*i), ty: Type::new(TypeKind::Int) } 1954 | } 1955 | syntax::Expr::UIntConst(u) => { 1956 | Expr { kind: ExprKind::UIntConst(*u), ty: Type::new(TypeKind::UInt) } 1957 | } 1958 | syntax::Expr::PostDec(e) => { 1959 | let e = Box::new(translate_expression(state, e)); 1960 | let ty = e.ty.clone(); 1961 | Expr { kind: ExprKind::PostDec(e), ty } 1962 | } 1963 | syntax::Expr::PostInc(e) => { 1964 | let e = Box::new(translate_expression(state, e)); 1965 | let ty = e.ty.clone(); 1966 | Expr { kind: ExprKind::PostInc(e), ty } 1967 | } 1968 | syntax::Expr::Ternary(cond, lhs, rhs) => { 1969 | let cond = Box::new(translate_expression(state, cond)); 1970 | let lhs = Box::new(translate_expression(state, lhs)); 1971 | let rhs = Box::new(translate_expression(state, rhs)); 1972 | let ty = promoted_type(&lhs.ty, &rhs.ty); 1973 | Expr { kind: ExprKind::Ternary(cond, lhs, rhs), ty } 1974 | } 1975 | syntax::Expr::Dot(e, i) => { 1976 | let e = Box::new(translate_expression(state, e)); 1977 | let ty = e.ty.clone(); 1978 | let ivec = is_ivec(&ty); 1979 | if is_vector(&ty) { 1980 | let ty = Type::new(match i.as_str().len() { 1981 | 1 => if ivec { TypeKind::Int } else { TypeKind::Float }, 1982 | 2 => if ivec { TypeKind::IVec2 } else { TypeKind::Vec2 }, 1983 | 3 => if ivec { TypeKind::IVec3 } else { TypeKind::Vec3 }, 1984 | 4 => if ivec { TypeKind::IVec4 } else { TypeKind::Vec4 }, 1985 | _ => panic!(), 1986 | }); 1987 | 1988 | Expr { kind: ExprKind::SwizzleSelector(e, SwizzleSelector::parse(i.as_str())), ty } 1989 | } else { 1990 | match ty.kind { 1991 | TypeKind::Struct(s) => { 1992 | let sym = state.sym(s); 1993 | let fields = match &sym.decl { 1994 | SymDecl::Struct(fields) => fields, 1995 | _ => panic!("expected struct"), 1996 | }; 1997 | let field = fields.fields.iter().find(|x| &x.name == i).expect("missing field"); 1998 | Expr { kind: ExprKind::Dot(e, i.clone()), ty: field.ty.clone() } 1999 | } 2000 | _ => panic!("expected struct found {:#?} {:#?}", e, ty) 2001 | } 2002 | } 2003 | } 2004 | syntax::Expr::Bracket(e, specifier) =>{ 2005 | let e = Box::new(translate_expression(state, e)); 2006 | let ty = if is_vector(&e.ty) { 2007 | Type::new(TypeKind::Float) 2008 | } else if let Some(ty) = index_matrix(&e.ty) { 2009 | Type::new(ty) 2010 | } else { 2011 | let a = match &e.ty.array_sizes { 2012 | Some(a) => { 2013 | let mut a = *a.clone(); 2014 | a.sizes.pop(); 2015 | if a.sizes.len() == 0 { 2016 | None 2017 | } else { 2018 | Some(Box::new(a)) 2019 | } 2020 | }, 2021 | _ => panic!("{:#?}", e) 2022 | }; 2023 | Type { kind: e.ty.kind.clone(), precision: e.ty.precision.clone(), array_sizes: a } 2024 | }; 2025 | let indx = match specifier { 2026 | ArraySpecifier::Unsized => panic!("need expression"), 2027 | ArraySpecifier::ExplicitlySized(e) => translate_expression(state, e) 2028 | }; 2029 | Expr { kind: ExprKind::Bracket(e, Box::new(indx)), ty } 2030 | } 2031 | } 2032 | } 2033 | 2034 | fn translate_switch(state: &mut State, s: &syntax::SwitchStatement) -> SwitchStatement { 2035 | let mut cases = Vec::new(); 2036 | 2037 | let mut case = None; 2038 | for stmt in &s.body { 2039 | match stmt { 2040 | syntax::Statement::Simple(s) => { 2041 | match &**s { 2042 | syntax::SimpleStatement::CaseLabel(label) => { 2043 | match case.take() { 2044 | Some(case) => cases.push(case), 2045 | _ => {} 2046 | } 2047 | case = Some(Case { label: translate_case(state, &label), stmts: Vec::new() }) 2048 | } 2049 | _ => { 2050 | match case { 2051 | Some(ref mut case) => case.stmts.push(translate_statement(state, stmt)), 2052 | _ => panic!("switch must start with case") 2053 | } 2054 | } 2055 | } 2056 | } 2057 | _ => { 2058 | match case { 2059 | Some(ref mut case) => case.stmts.push(translate_statement(state, stmt)), 2060 | _ => panic!("switch must start with case") 2061 | } 2062 | } 2063 | } 2064 | 2065 | } 2066 | match case.take() { 2067 | Some(case) => cases.push(case), 2068 | _ => {} 2069 | } 2070 | SwitchStatement { 2071 | head: Box::new(translate_expression(state, &s.head)), 2072 | cases 2073 | } 2074 | } 2075 | 2076 | fn translate_jump(state: &mut State, s: &syntax::JumpStatement) -> JumpStatement { 2077 | match s { 2078 | syntax::JumpStatement::Break => JumpStatement::Break, 2079 | syntax::JumpStatement::Continue => JumpStatement::Continue, 2080 | syntax::JumpStatement::Discard => JumpStatement::Discard, 2081 | syntax::JumpStatement::Return(e) => { 2082 | JumpStatement::Return(e.as_ref().map(|e| Box::new(translate_expression(state, e)))) 2083 | } 2084 | } 2085 | } 2086 | 2087 | fn translate_condition(state: &mut State, c: &syntax::Condition) -> Condition { 2088 | match c { 2089 | syntax::Condition::Expr(e) => Condition::Expr(Box::new(translate_expression(state, e))), 2090 | _ => panic!() 2091 | } 2092 | } 2093 | 2094 | fn translate_for_init(state: &mut State, s: &syntax::ForInitStatement) -> ForInitStatement { 2095 | match s { 2096 | syntax::ForInitStatement::Expression(e) => ForInitStatement::Expression(e.as_ref().map(|e| translate_expression(state, e))), 2097 | syntax::ForInitStatement::Declaration(d) => ForInitStatement::Declaration(Box::new(translate_declaration(state, d, RunClass::Scalar))), 2098 | } 2099 | } 2100 | 2101 | fn translate_for_rest(state: &mut State, s: &syntax::ForRestStatement) -> ForRestStatement { 2102 | ForRestStatement { 2103 | condition: s.condition.as_ref().map(|c| translate_condition(state, c)), 2104 | post_expr: s.post_expr.as_ref().map(|e| Box::new(translate_expression(state, e))) 2105 | } 2106 | } 2107 | 2108 | fn translate_iteration(state: &mut State, s: &syntax::IterationStatement) -> IterationStatement { 2109 | match s { 2110 | syntax::IterationStatement::While(cond, s) => 2111 | IterationStatement::While(translate_condition(state, cond), Box::new(translate_statement(state, s))), 2112 | syntax::IterationStatement::For(init, rest, s) => 2113 | IterationStatement::For(translate_for_init(state, init),translate_for_rest(state, rest), Box::new(translate_statement(state, s))), 2114 | syntax::IterationStatement::DoWhile(s, e) => 2115 | IterationStatement::DoWhile(Box::new(translate_statement(state, s)), Box::new(translate_expression(state, e))), 2116 | } 2117 | } 2118 | 2119 | fn translate_case(state: &mut State, c: &syntax::CaseLabel) -> CaseLabel { 2120 | match c { 2121 | syntax::CaseLabel::Def => CaseLabel::Def, 2122 | syntax::CaseLabel::Case(e) => CaseLabel::Case(Box::new(translate_expression(state, e))) 2123 | } 2124 | } 2125 | 2126 | fn translate_selection_rest(state: &mut State, s: &syntax::SelectionRestStatement) -> SelectionRestStatement { 2127 | match s { 2128 | syntax::SelectionRestStatement::Statement(s) => SelectionRestStatement::Statement(Box::new(translate_statement(state, s))), 2129 | syntax::SelectionRestStatement::Else(if_body, rest) => { 2130 | SelectionRestStatement::Else(Box::new(translate_statement(state, if_body)), Box::new(translate_statement(state, rest))) 2131 | } 2132 | } 2133 | } 2134 | 2135 | fn translate_selection(state: &mut State, s: &syntax::SelectionStatement) -> SelectionStatement { 2136 | SelectionStatement { 2137 | cond: Box::new(translate_expression(state, &s.cond)), 2138 | rest: translate_selection_rest(state, &s.rest), 2139 | } 2140 | } 2141 | 2142 | fn translate_simple_statement(state: &mut State, s: &syntax::SimpleStatement) -> SimpleStatement { 2143 | match s { 2144 | syntax::SimpleStatement::Declaration(d) => SimpleStatement::Declaration(translate_declaration(state, d, RunClass::Unknown)), 2145 | syntax::SimpleStatement::Expression(e) => SimpleStatement::Expression(e.as_ref().map(|e| translate_expression(state, e))), 2146 | syntax::SimpleStatement::Iteration(i) => SimpleStatement::Iteration(translate_iteration(state, i)), 2147 | syntax::SimpleStatement::Selection(s) => SimpleStatement::Selection(translate_selection(state, s)), 2148 | syntax::SimpleStatement::Jump(j) => SimpleStatement::Jump(translate_jump(state, j)), 2149 | syntax::SimpleStatement::Switch(s) => SimpleStatement::Switch(translate_switch(state, s)), 2150 | syntax::SimpleStatement::CaseLabel(s) => panic!("should be handled by translate_switch") 2151 | } 2152 | } 2153 | 2154 | fn translate_statement(state: &mut State, s: &syntax::Statement) -> Statement { 2155 | match s { 2156 | syntax::Statement::Compound(s) => Statement::Compound(Box::new(translate_compound_statement(state, s))), 2157 | syntax::Statement::Simple(s) => Statement::Simple(Box::new(translate_simple_statement(state, s))) 2158 | } 2159 | } 2160 | 2161 | 2162 | fn translate_compound_statement(state: &mut State, cs: &syntax::CompoundStatement) -> CompoundStatement { 2163 | CompoundStatement { statement_list: cs.statement_list.iter().map(|x| translate_statement(state, x)).collect() } 2164 | } 2165 | 2166 | 2167 | 2168 | 2169 | fn translate_function_parameter_declaration(state: &mut State, p: &syntax::FunctionParameterDeclaration, index: usize) -> 2170 | FunctionParameterDeclaration 2171 | { 2172 | match p { 2173 | syntax::FunctionParameterDeclaration::Named(qual, p) => { 2174 | let mut ty: Type = lift(state, &p.ty); 2175 | if let Some(a) = &p.ident.array_spec { 2176 | ty.array_sizes = Some(Box::new(lift(state, a))); 2177 | } 2178 | 2179 | ty.precision = get_precision(qual); 2180 | 2181 | let decl = SymDecl::Local( 2182 | StorageClass::None, 2183 | ty.clone(), 2184 | RunClass::Dependent(1 << index), 2185 | ); 2186 | let d = FunctionParameterDeclarator { 2187 | ty, 2188 | name: p.ident.ident.clone(), 2189 | sym: state.declare(p.ident.ident.as_str(), decl), 2190 | }; 2191 | FunctionParameterDeclaration::Named(lift_type_qualifier_for_parameter(state, qual), d) 2192 | } 2193 | syntax::FunctionParameterDeclaration::Unnamed(qual, p) => { 2194 | FunctionParameterDeclaration::Unnamed(lift_type_qualifier_for_parameter(state, qual), p.clone()) 2195 | } 2196 | 2197 | } 2198 | } 2199 | 2200 | fn translate_prototype(state: &mut State, cs: &syntax::FunctionPrototype) -> (FunctionPrototype, SymRef) { 2201 | let prototype = FunctionPrototype { 2202 | ty: lift(state, &cs.ty), 2203 | name: cs.name.clone(), 2204 | parameters: cs.parameters.iter().enumerate().map(|(i, x)| translate_function_parameter_declaration(state, x, i)).collect(), 2205 | }; 2206 | let sym = if let Some(sym) = state.lookup(prototype.name.as_str()) { 2207 | match &state.sym(sym).decl { 2208 | SymDecl::UserFunction(..) => {} 2209 | _ => panic!("prototype conflicts with existing symbol: {}", prototype.name.as_str()), 2210 | } 2211 | sym 2212 | } else { 2213 | let pfd = Rc::new(FunctionDefinition { prototype: prototype.clone(), body: CompoundStatement::new(), globals: Vec::new() }); 2214 | state.declare(prototype.name.as_str(), SymDecl::UserFunction(pfd, RunClass::Unknown)) 2215 | }; 2216 | (prototype, sym) 2217 | } 2218 | 2219 | fn translate_function_prototype(state: &mut State, prototype: &syntax::FunctionPrototype) -> FunctionPrototype { 2220 | let (prototype, _) = translate_prototype(state, prototype); 2221 | prototype 2222 | } 2223 | 2224 | fn translate_function_definition(state: &mut State, sfd: &syntax::FunctionDefinition) -> Rc { 2225 | let (prototype, sym) = translate_prototype(state, &sfd.prototype); 2226 | 2227 | state.push_scope(prototype.name.as_str().into()); 2228 | state.in_function = Some(sym); 2229 | state.modified_globals.get_mut().clear(); 2230 | let body = translate_compound_statement(state, &sfd.statement); 2231 | let mut globals = Vec::new(); 2232 | mem::swap(&mut globals, state.modified_globals.get_mut()); 2233 | state.in_function = None; 2234 | state.pop_scope(); 2235 | 2236 | let fd = Rc::new(FunctionDefinition { prototype, body, globals }); 2237 | state.sym_mut(sym).decl = SymDecl::UserFunction(fd.clone(), RunClass::Unknown); 2238 | fd 2239 | } 2240 | 2241 | fn translate_external_declaration(state: &mut State, ed: &syntax::ExternalDeclaration) -> ExternalDeclaration { 2242 | match ed { 2243 | syntax::ExternalDeclaration::Declaration(d) => 2244 | ExternalDeclaration::Declaration(translate_declaration(state, d, RunClass::Unknown)), 2245 | syntax::ExternalDeclaration::FunctionDefinition(fd) => 2246 | ExternalDeclaration::FunctionDefinition(translate_function_definition(state, fd)), 2247 | syntax::ExternalDeclaration::Preprocessor(p) => 2248 | ExternalDeclaration::Preprocessor(p.clone()) 2249 | } 2250 | } 2251 | 2252 | fn declare_function(state: &mut State, name: &str, cxx_name: Option<&'static str>, ret: Type, params: Vec) { 2253 | let sig = FunctionSignature{ ret, params }; 2254 | match state.lookup_sym_mut(name) { 2255 | Some(Symbol { decl: SymDecl::NativeFunction(f, ..), ..}) => f.signatures.push(sig), 2256 | None => { state.declare(name, SymDecl::NativeFunction(FunctionType{ signatures: NonEmpty::new(sig)}, cxx_name)); }, 2257 | _ => panic!("overloaded function name {}", name) 2258 | } 2259 | //state.declare(name, Type::Function(FunctionType{ v})) 2260 | } 2261 | 2262 | 2263 | pub fn ast_to_hir(state: &mut State, tu: &syntax::TranslationUnit) -> TranslationUnit { 2264 | // global scope 2265 | state.push_scope("global".into()); 2266 | use TypeKind::*; 2267 | declare_function(state, "vec2", Some("make_vec2"), Type::new(Vec2), 2268 | vec![Type::new(Float)]); 2269 | declare_function(state, "vec2", Some("make_vec2"), Type::new(Vec2), 2270 | vec![Type::new(IVec2)]); 2271 | declare_function(state, "vec3", Some("make_vec3"), Type::new(Vec3), 2272 | vec![Type::new(Float), Type::new(Float), Type::new(Float)]); 2273 | declare_function(state, "vec3", Some("make_vec3"), Type::new(Vec3), 2274 | vec![Type::new(Float)]); 2275 | declare_function(state, "vec3", Some("make_vec3"), Type::new(Vec3), 2276 | vec![Type::new(Vec2), Type::new(Float)]); 2277 | declare_function(state, "vec4", Some("make_vec4"), Type::new(Vec4), 2278 | vec![Type::new(Vec3), Type::new(Float)]); 2279 | declare_function(state, "vec4", Some("make_vec4"), Type::new(Vec4), 2280 | vec![Type::new(Float), Type::new(Float), Type::new(Float), Type::new(Float)]); 2281 | declare_function(state, "vec4", Some("make_vec4"), Type::new(Vec4), 2282 | vec![Type::new(Vec2), Type::new(Float), Type::new(Float)]); 2283 | declare_function(state, "vec4", Some("make_vec4"), Type::new(Vec4), 2284 | vec![Type::new(Vec2), Type::new(Vec2)]); 2285 | declare_function(state, "vec4", Some("make_vec4"), Type::new(Vec4), 2286 | vec![Type::new(Vec4)]); 2287 | 2288 | declare_function(state, "bvec2", Some("make_bvec2"), Type::new(BVec2), 2289 | vec![Type::new(UInt)]); 2290 | declare_function(state, "bvec4", Some("make_bvec4"), Type::new(BVec4), 2291 | vec![Type::new(BVec2), Type::new(BVec2)]); 2292 | 2293 | declare_function(state, "int", Some("make_int"), Type::new(Int), 2294 | vec![Type::new(Float)]); 2295 | declare_function(state, "float", Some("make_float"), Type::new(Float), 2296 | vec![Type::new(Float)]); 2297 | declare_function(state, "float", Some("make_float"), Type::new(Float), 2298 | vec![Type::new(Bool)]); 2299 | declare_function(state, "int", Some("make_int"), Type::new(Int), 2300 | vec![Type::new(UInt)]); 2301 | declare_function(state, "uint", Some("make_uint"), Type::new(UInt), 2302 | vec![Type::new(Float)]); 2303 | declare_function(state, "uint", Some("make_uint"), Type::new(UInt), 2304 | vec![Type::new(Int)]); 2305 | declare_function(state, "ivec2", Some("make_ivec2"), Type::new(IVec2), 2306 | vec![Type::new(UInt), Type::new(UInt)]); 2307 | declare_function(state, "ivec2", Some("make_ivec2"), Type::new(IVec2), 2308 | vec![Type::new(Int), Type::new(Int)]); 2309 | declare_function(state, "ivec2", Some("make_ivec2"), Type::new(IVec2), 2310 | vec![Type::new(Vec2)]); 2311 | declare_function(state, "ivec3", Some("make_ivec3"), Type::new(IVec3), 2312 | vec![Type::new(IVec2), Type::new(Int)]); 2313 | declare_function(state, "ivec4", Some("make_ivec4"), Type::new(IVec4), 2314 | vec![Type::new(Int), Type::new(Int), Type::new(Int), Type::new(Int)]); 2315 | declare_function(state, "ivec4", Some("make_ivec4"), Type::new(IVec4), 2316 | vec![Type::new(IVec2), Type::new(Int), Type::new(Int)]); 2317 | 2318 | declare_function(state, "mat2", Some("make_mat2"), Type::new(Mat2), 2319 | vec![Type::new(Vec2), Type::new(Vec2)]); 2320 | declare_function(state, "mat2", Some("make_mat2"), Type::new(Mat2), 2321 | vec![Type::new(Float)]); 2322 | declare_function(state, "mat2", Some("make_mat2"), Type::new(Mat2), 2323 | vec![Type::new(Mat4)]); 2324 | declare_function(state, "mat3", Some("make_mat3"), Type::new(Mat3), 2325 | vec![Type::new(Vec3), Type::new(Vec3), Type::new(Vec3)]); 2326 | declare_function(state, "mat3", Some("make_mat3"), Type::new(Mat3), 2327 | vec![Type::new(Mat4)]); 2328 | declare_function(state, "mat3", Some("make_mat3"), Type::new(Mat3), 2329 | vec![Type::new(Float), Type::new(Float), Type::new(Float), 2330 | Type::new(Float), Type::new(Float), Type::new(Float), 2331 | Type::new(Float), Type::new(Float), Type::new(Float)]); 2332 | declare_function(state, "abs", None, Type::new(Vec2), 2333 | vec![Type::new(Vec2)]); 2334 | declare_function(state, "abs", None, Type::new(Vec3), 2335 | vec![Type::new(Vec3)]); 2336 | declare_function(state, "abs", None, Type::new(Float), 2337 | vec![Type::new(Float)]); 2338 | declare_function(state, "dot", None, Type::new(Float), 2339 | vec![Type::new(Vec3), Type::new(Vec3)]); 2340 | declare_function(state, "dot", None, Type::new(Float), 2341 | vec![Type::new(Vec2), Type::new(Vec2)]); 2342 | declare_function(state, "min", None, Type::new(Float), 2343 | vec![Type::new(Float), Type::new(Float)]); 2344 | declare_function(state, "min", None, Type::new(Vec2), 2345 | vec![Type::new(Vec2), Type::new(Vec2)]); 2346 | declare_function(state, "min", None, Type::new(Vec3), 2347 | vec![Type::new(Vec3), Type::new(Vec3)]); 2348 | 2349 | declare_function(state, "max", None, Type::new(Float), 2350 | vec![Type::new(Float), Type::new(Float)]); 2351 | declare_function(state, "max", None, Type::new(Vec2), 2352 | vec![Type::new(Vec2), Type::new(Vec2)]); 2353 | declare_function(state, "max", None, Type::new(Vec2), 2354 | vec![Type::new(Vec2), Type::new(Float)]); 2355 | declare_function(state, "max", None, Type::new(Vec3), 2356 | vec![Type::new(Vec3), Type::new(Vec3)]); 2357 | 2358 | 2359 | declare_function(state, "mix", None, Type::new(Vec2), 2360 | vec![Type::new(Vec2), Type::new(Vec2), Type::new(Vec2)]); 2361 | declare_function(state, "mix", None, Type::new(Vec2), 2362 | vec![Type::new(Vec2), Type::new(Vec2), Type::new(BVec2)]); 2363 | declare_function(state, "mix", None, Type::new(Vec2), 2364 | vec![Type::new(Vec2), Type::new(Vec2), Type::new(Float)]); 2365 | declare_function(state, "mix", None, Type::new(Vec3), 2366 | vec![Type::new(Vec3), Type::new(Vec3), Type::new(Vec3)]); 2367 | declare_function(state, "mix", None, Type::new(Vec4), 2368 | vec![Type::new(Vec4), Type::new(Vec4), Type::new(Vec4)]); 2369 | declare_function(state, "mix", None, Type::new(Vec4), 2370 | vec![Type::new(Vec4), Type::new(Vec4), Type::new(Float)]); 2371 | declare_function(state, "mix", None, Type::new(Vec3), 2372 | vec![Type::new(Vec3), Type::new(Vec3), Type::new(Float)]); 2373 | declare_function(state, "mix", None, Type::new(Vec3), 2374 | vec![Type::new(Vec3), Type::new(Vec3), Type::new(BVec3)]); 2375 | declare_function(state, "mix", None, Type::new(Float), 2376 | vec![Type::new(Float), Type::new(Float), Type::new(Float)]); 2377 | declare_function(state, "mix", None, Type::new(Vec4), 2378 | vec![Type::new(Vec4), Type::new(Vec4), Type::new(BVec4)]); 2379 | declare_function(state, "step", None, Type::new(Float), 2380 | vec![Type::new(Float), Type::new(Float)]); 2381 | declare_function(state, "step", None, Type::new(Vec2), 2382 | vec![Type::new(Vec2), Type::new(Vec2)]); 2383 | declare_function(state, "step", None, Type::new(Vec3), 2384 | vec![Type::new(Vec3), Type::new(Vec3)]); 2385 | declare_function(state, "notEqual", None, Type::new(BVec4), 2386 | vec![Type::new(IVec4), Type::new(IVec4)]); 2387 | 2388 | declare_function(state, "fwidth", None, Type::new(Vec2), 2389 | vec![Type::new(Vec2)]); 2390 | declare_function(state, "cos", None, Type::new(Float), 2391 | vec![Type::new(Float)]); 2392 | declare_function(state, "sin", None, Type::new(Float), 2393 | vec![Type::new(Float)]); 2394 | declare_function(state, "clamp", None, Type::new(Vec3), 2395 | vec![Type::new(Vec3), Type::new(Float), Type::new(Float)]); 2396 | declare_function(state, "clamp", None, Type::new(Double), 2397 | vec![Type::new(Double), Type::new(Double), Type::new(Double)]); 2398 | declare_function(state, "clamp", None, Type::new(Vec2), 2399 | vec![Type::new(Vec2), Type::new(Vec2), Type::new(Vec2)]); 2400 | declare_function(state, "clamp", None, Type::new(Vec3), 2401 | vec![Type::new(Vec3), Type::new(Vec3), Type::new(Vec3)]); 2402 | declare_function(state, "clamp", None, Type::new(Vec4), 2403 | vec![Type::new(Vec4), Type::new(Vec4), Type::new(Vec4)]); 2404 | declare_function(state, "length", None, Type::new(Float), vec![Type::new(Vec2)]); 2405 | declare_function(state, "pow", None, Type::new(Vec3), vec![Type::new(Vec3)]); 2406 | declare_function(state, "pow", None, Type::new(Float), vec![Type::new(Float)]); 2407 | declare_function(state, "exp", None, Type::new(Float), vec![Type::new(Float)]); 2408 | declare_function(state, "inversesqrt", None, Type::new(Float), vec![Type::new(Float)]); 2409 | declare_function(state, "sqrt", None, Type::new(Float), vec![Type::new(Float)]); 2410 | declare_function(state, "distance", None, Type::new(Float), vec![Type::new(Vec2), Type::new(Vec2)]); 2411 | 2412 | declare_function(state, "lessThanEqual", None, Type::new(BVec2), 2413 | vec![Type::new(Vec2), Type::new(Vec2)]); 2414 | declare_function(state, "lessThanEqual", None, Type::new(BVec3), 2415 | vec![Type::new(Vec3), Type::new(Vec3)]); 2416 | declare_function(state, "lessThanEqual", None, Type::new(BVec4), 2417 | vec![Type::new(Vec4), Type::new(Vec4)]); 2418 | declare_function(state, "lessThan", None, Type::new(BVec2), 2419 | vec![Type::new(Vec2), Type::new(Vec2)]); 2420 | declare_function(state, "greaterThan", None, Type::new(BVec2), 2421 | vec![Type::new(Vec2), Type::new(Vec2)]); 2422 | declare_function(state, "greaterThanEqual", None, Type::new(BVec2), 2423 | vec![Type::new(Vec2), Type::new(Vec2)]); 2424 | declare_function(state, "greaterThanEqual", None, Type::new(BVec2), 2425 | vec![Type::new(Vec4), Type::new(Vec4)]); 2426 | declare_function(state, "any", None, Type::new(Bool), vec![Type::new(BVec2)]); 2427 | declare_function(state, "all", None, Type::new(Bool), vec![Type::new(BVec2)]); 2428 | declare_function(state, "all", None, Type::new(Bool), vec![Type::new(BVec4)]); 2429 | 2430 | declare_function(state, "if_then_else", None, Type::new(Vec3), 2431 | vec![Type::new(BVec3), Type::new(Vec3), Type::new(Vec3)]); 2432 | declare_function(state, "floor", None, Type::new(Vec4), 2433 | vec![Type::new(Vec4)]); 2434 | declare_function(state, "floor", None, Type::new(Vec2), 2435 | vec![Type::new(Vec2)]); 2436 | declare_function(state, "floor", None, Type::new(Double), 2437 | vec![Type::new(Double)]); 2438 | declare_function(state, "ceil", None, Type::new(Double), 2439 | vec![Type::new(Double)]); 2440 | declare_function(state, "fract", None, Type::new(Float), 2441 | vec![Type::new(Float)]); 2442 | declare_function(state, "mod", None, Type::new(Vec2), 2443 | vec![Type::new(Vec2)]); 2444 | declare_function(state, "mod", None, Type::new(Float), 2445 | vec![Type::new(Float)]); 2446 | 2447 | declare_function(state, "texelFetch", None, Type::new(Vec4), 2448 | vec![Type::new(Sampler2D), Type::new(IVec2), Type::new(Int)]); 2449 | declare_function(state, "texelFetch", None, Type::new(Vec4), 2450 | vec![Type::new(Sampler2DArray), Type::new(IVec3), Type::new(Int)]); 2451 | declare_function(state, "texelFetch", None, Type::new(IVec4), 2452 | vec![Type::new(ISampler2D), Type::new(IVec2), Type::new(Int)]); 2453 | declare_function(state, "texture", None, Type::new(Vec4), 2454 | vec![Type::new(Sampler2D), Type::new(Vec3)]); 2455 | declare_function(state, "texture", None, Type::new(Vec4), 2456 | vec![Type::new(Sampler2D), Type::new(Vec2)]); 2457 | declare_function(state, "texture", None, Type::new(Vec4), 2458 | vec![Type::new(Sampler2DArray), Type::new(Vec3)]); 2459 | declare_function(state, "textureLod", None, Type::new(Vec4), 2460 | vec![Type::new(Sampler2DArray), Type::new(Vec3), Type::new(Float)]); 2461 | declare_function(state, "textureSize", None, Type::new(IVec2), 2462 | vec![Type::new(Sampler2DArray), Type::new(Int)]); 2463 | 2464 | declare_function(state, "inverse", None, Type::new(Mat2), 2465 | vec![Type::new(Mat2)]); 2466 | declare_function(state, "transpose", None, Type::new(Mat3), 2467 | vec![Type::new(Mat3)]); 2468 | declare_function(state, "normalize", None, Type::new(Vec2), 2469 | vec![Type::new(Vec2)]); 2470 | state.declare("gl_FragCoord", SymDecl::Global(StorageClass::Out, None, Type::new(Vec4), RunClass::Vector)); 2471 | state.declare("gl_FragColor", SymDecl::Global(StorageClass::Out, None, Type::new(Vec4), RunClass::Vector)); 2472 | state.declare("gl_Position", SymDecl::Global(StorageClass::Out, None, Type::new(Vec4), RunClass::Vector)); 2473 | 2474 | 2475 | TranslationUnit(tu.0.map(state, translate_external_declaration)) 2476 | } 2477 | 2478 | fn infer_expr_inner(state: &mut State, expr: &Expr, assign: &mut SymRef) -> RunClass { 2479 | match expr.kind { 2480 | ExprKind::Variable(ref i) => { 2481 | *assign = *i; 2482 | match &state.sym(*i).decl { 2483 | SymDecl::Local(_, _, ref run_class) => *run_class, 2484 | SymDecl::Global(_, _, _, ref run_class) => *run_class, 2485 | _ => panic!(), 2486 | } 2487 | } 2488 | ExprKind::IntConst(_) | 2489 | ExprKind::UIntConst(_) | 2490 | ExprKind::BoolConst(_) | 2491 | ExprKind::FloatConst(_) | 2492 | ExprKind::DoubleConst(_) => RunClass::Scalar, 2493 | ExprKind::Unary(_, ref e) => infer_expr(state, e), 2494 | ExprKind::Binary(_, ref l, ref r) => infer_expr(state, l).merge(infer_expr(state, r)), 2495 | ExprKind::Ternary(ref c, ref s, ref e) => infer_expr(state, c).merge(infer_expr(state, s)).merge(infer_expr(state, e)), 2496 | ExprKind::Assignment(ref v, _, ref e) => { 2497 | let mut sym = SymRef(!0); 2498 | let run_class = infer_expr_inner(state, v, &mut sym).merge(infer_expr(state, e)); 2499 | assert!(sym != SymRef(!0)); 2500 | state.merge_run_class(sym, run_class) 2501 | } 2502 | ExprKind::Bracket(ref e, ref indx) => infer_expr_inner(state, e, assign).merge(infer_expr(state, indx)), 2503 | ExprKind::FunCall(ref fun, ref args) => { 2504 | let arg_classes: Vec<(RunClass, SymRef)> = args.iter().map(|e| { 2505 | let mut assign = SymRef(!0); 2506 | let run_class = infer_expr_inner(state, e, &mut assign); 2507 | (run_class, assign) 2508 | }).collect(); 2509 | let run_class = if args.is_empty() { 2510 | RunClass::Scalar 2511 | } else { 2512 | arg_classes.iter().fold(RunClass::Unknown, |x, &(y, _) | x.merge(y)) 2513 | }; 2514 | match fun { 2515 | FunIdentifier::Identifier(ref sym) => { 2516 | match &state.sym(*sym).decl { 2517 | SymDecl::NativeFunction(..) => run_class, 2518 | SymDecl::UserFunction(ref fd, ref run_class) => { 2519 | for (&(mut arg_class, assign), param) in arg_classes.iter().zip(fd.prototype.parameters.iter()) { 2520 | if let FunctionParameterDeclaration::Named(Some(qual), p) = param { 2521 | match qual { 2522 | ParameterQualifier::InOut | ParameterQualifier::Out => { 2523 | if let SymDecl::Local(_, _, param_class) = &state.sym(p.sym).decl { 2524 | match param_class { 2525 | RunClass::Unknown | RunClass::Vector => { arg_class = RunClass::Vector; } 2526 | RunClass::Dependent(mask) => { 2527 | for i in 0..31 { 2528 | if (mask & (1 << i)) != 0 { 2529 | arg_class = arg_class.merge(arg_classes[i].0); 2530 | } 2531 | } 2532 | } 2533 | RunClass::Scalar => {} 2534 | } 2535 | } 2536 | assert!(assign != SymRef(!0)); 2537 | state.merge_run_class(assign, arg_class); 2538 | } 2539 | _ => {} 2540 | } 2541 | } 2542 | } 2543 | if fd.prototype.ty.kind == TypeKind::Void { 2544 | RunClass::Scalar 2545 | } else { 2546 | match *run_class { 2547 | RunClass::Unknown | RunClass::Vector => RunClass::Vector, 2548 | RunClass::Dependent(mask) => { 2549 | let mut ret_class = RunClass::Unknown; 2550 | for i in 0..31 { 2551 | if (mask & (1 << i)) != 0 { 2552 | ret_class = ret_class.merge(arg_classes[i].0); 2553 | } 2554 | } 2555 | ret_class 2556 | } 2557 | RunClass::Scalar => RunClass::Scalar, 2558 | } 2559 | } 2560 | } 2561 | SymDecl::Struct(..) => run_class, 2562 | _ => panic!(), 2563 | } 2564 | } 2565 | FunIdentifier::Constructor(..) => run_class, 2566 | } 2567 | } 2568 | ExprKind::Dot(ref e, _) => infer_expr_inner(state, e, assign), 2569 | ExprKind::SwizzleSelector(ref e, _) => infer_expr_inner(state, e, assign), 2570 | ExprKind::PostInc(ref e) => infer_expr_inner(state, e, assign), 2571 | ExprKind::PostDec(ref e) => infer_expr_inner(state, e, assign), 2572 | ExprKind::Comma(ref a, ref b) => { 2573 | infer_expr(state, a); 2574 | infer_expr(state, b) 2575 | } 2576 | ExprKind::Cond(_, ref e) => infer_expr(state, e), 2577 | ExprKind::CondMask => RunClass::Vector, 2578 | } 2579 | } 2580 | 2581 | fn infer_expr(state: &mut State, expr: &Expr) -> RunClass { 2582 | infer_expr_inner(state, expr, &mut SymRef(!0)) 2583 | } 2584 | 2585 | fn infer_condition(state: &mut State, c: &Condition) { 2586 | match *c { 2587 | Condition::Expr(ref e) => { 2588 | infer_expr(state, e); 2589 | } 2590 | } 2591 | } 2592 | 2593 | fn infer_iteration_statement(state: &mut State, ist: &IterationStatement) { 2594 | let changed = state.run_class_changed.replace(true); 2595 | match *ist { 2596 | IterationStatement::While(ref cond, ref body) => { 2597 | while state.run_class_changed.replace(false) { 2598 | infer_condition(state, cond); 2599 | infer_statement(state, body); 2600 | } 2601 | } 2602 | IterationStatement::DoWhile(ref body, ref cond) => { 2603 | while state.run_class_changed.replace(false) { 2604 | infer_statement(state, body); 2605 | infer_expr(state, cond); 2606 | } 2607 | } 2608 | IterationStatement::For(ref init, ref rest, ref body) => { 2609 | match *init { 2610 | ForInitStatement::Expression(ref expr) => { 2611 | if let Some(ref e) = *expr { 2612 | infer_expr(state, e); 2613 | } 2614 | } 2615 | ForInitStatement::Declaration(ref d) => { 2616 | infer_declaration(state, d); 2617 | } 2618 | } 2619 | while state.run_class_changed.replace(false) { 2620 | if let Some(ref cond) = rest.condition { 2621 | infer_condition(state, cond); 2622 | } 2623 | if let Some(ref e) = rest.post_expr { 2624 | infer_expr(state, e); 2625 | } 2626 | infer_statement(state, body); 2627 | } 2628 | } 2629 | } 2630 | state.run_class_changed.set(changed); 2631 | } 2632 | 2633 | fn infer_selection_statement(state: &mut State, sst: &SelectionStatement) { 2634 | let mut branch_run_class = state.branch_run_class.merge(infer_expr(state, &sst.cond)); 2635 | mem::swap(&mut state.branch_run_class, &mut branch_run_class); 2636 | let branch_declaration = state.branch_declaration; 2637 | state.branch_declaration = state.last_declaration; 2638 | match sst.rest { 2639 | SelectionRestStatement::Statement(ref if_st) => { 2640 | infer_statement(state, if_st); 2641 | } 2642 | SelectionRestStatement::Else(ref if_st, ref else_st) => { 2643 | infer_statement(state, if_st); 2644 | infer_statement(state, else_st); 2645 | } 2646 | } 2647 | state.branch_run_class = branch_run_class; 2648 | state.branch_declaration = branch_declaration; 2649 | } 2650 | 2651 | fn infer_expression_statement(state: &mut State, est: &ExprStatement) { 2652 | if let Some(ref e) = *est { 2653 | infer_expr(state, e); 2654 | } 2655 | } 2656 | 2657 | fn infer_switch_statement(state: &mut State, sst: &SwitchStatement) { 2658 | let mut branch_run_class = state.branch_run_class.merge(infer_expr(state, &sst.head)); 2659 | mem::swap(&mut state.branch_run_class, &mut branch_run_class); 2660 | let branch_declaration = state.branch_declaration; 2661 | state.branch_declaration = state.last_declaration; 2662 | for case in &sst.cases { 2663 | for st in &case.stmts { 2664 | infer_statement(state, st); 2665 | } 2666 | } 2667 | state.branch_run_class = branch_run_class; 2668 | state.branch_declaration = branch_declaration; 2669 | } 2670 | 2671 | fn infer_jump_statement(state: &mut State, j: &JumpStatement) { 2672 | match *j { 2673 | JumpStatement::Continue => {} 2674 | JumpStatement::Break => {} 2675 | JumpStatement::Discard => {} 2676 | JumpStatement::Return(ref e) => { 2677 | if let Some(e) = e { 2678 | let run_class = infer_expr(state, e); 2679 | state.return_run_class(run_class); 2680 | } 2681 | } 2682 | } 2683 | } 2684 | 2685 | fn infer_initializer(state: &mut State, i: &Initializer) -> RunClass { 2686 | match *i { 2687 | Initializer::Simple(ref e) => infer_expr(state, e), 2688 | Initializer::List(ref list) => { 2689 | let mut run_class = RunClass::Unknown; 2690 | for ini in list.0.iter() { 2691 | run_class = run_class.merge(infer_initializer(state, ini)); 2692 | } 2693 | run_class 2694 | } 2695 | } 2696 | } 2697 | 2698 | fn infer_declaration(state: &mut State, d: &Declaration) { 2699 | match *d { 2700 | Declaration::FunctionPrototype(..) => {} 2701 | Declaration::InitDeclaratorList(ref list) => { 2702 | state.last_declaration = list.head.name; 2703 | 2704 | let mut run_class = RunClass::Unknown; 2705 | for decl in &list.tail { 2706 | if let Some(ref initializer) = decl.initializer { 2707 | run_class = run_class.merge(infer_initializer(state, initializer)); 2708 | } 2709 | } 2710 | if let Some(ref initializer) = list.head.initializer { 2711 | run_class = run_class.merge(infer_initializer(state, initializer)); 2712 | state.merge_run_class(list.head.name, run_class); 2713 | } 2714 | } 2715 | Declaration::Precision(..) => {} 2716 | Declaration::Block(..) => {} 2717 | Declaration::Global(..) => {} 2718 | Declaration::StructDefinition(..) => {} 2719 | } 2720 | } 2721 | 2722 | fn infer_simple_statement(state: &mut State, sst: &SimpleStatement) { 2723 | match *sst { 2724 | SimpleStatement::Declaration(ref d) => infer_declaration(state, d), 2725 | SimpleStatement::Expression(ref e) => infer_expression_statement(state, e), 2726 | SimpleStatement::Selection(ref s) => infer_selection_statement(state, s), 2727 | SimpleStatement::Switch(ref s) => infer_switch_statement(state, s), 2728 | SimpleStatement::Iteration(ref i) => infer_iteration_statement(state, i), 2729 | SimpleStatement::Jump(ref j) => infer_jump_statement(state, j), 2730 | } 2731 | } 2732 | 2733 | fn infer_compound_statement(state: &mut State, cst: &CompoundStatement) { 2734 | for st in &cst.statement_list { 2735 | infer_statement(state, st); 2736 | } 2737 | } 2738 | 2739 | fn infer_statement(state: &mut State, st: &Statement) { 2740 | match *st { 2741 | Statement::Compound(ref cst) => infer_compound_statement(state, cst), 2742 | Statement::Simple(ref sst) => infer_simple_statement(state, sst), 2743 | } 2744 | } 2745 | 2746 | fn infer_function_definition(state: &mut State, fd: &FunctionDefinition) { 2747 | state.in_function = Some(state.lookup(fd.prototype.name.as_str()).unwrap()); 2748 | 2749 | state.run_class_changed.set(true); 2750 | while state.run_class_changed.replace(false) { 2751 | for st in &fd.body.statement_list { 2752 | infer_statement(state, st); 2753 | } 2754 | } 2755 | 2756 | state.in_function = None; 2757 | } 2758 | 2759 | fn infer_external_declaration(state: &mut State, ed: &ExternalDeclaration) { 2760 | match *ed { 2761 | ExternalDeclaration::Preprocessor(_) => {} 2762 | ExternalDeclaration::FunctionDefinition(ref fd) => infer_function_definition(state, fd), 2763 | ExternalDeclaration::Declaration(_) => {} 2764 | } 2765 | } 2766 | 2767 | pub fn infer_run_class(state: &mut State, tu: &TranslationUnit) { 2768 | for ed in &(tu.0).0 { 2769 | infer_external_declaration(state, ed); 2770 | } 2771 | } 2772 | 2773 | 2774 | --------------------------------------------------------------------------------