├── .gitignore ├── Cargo.toml ├── LICENSE-APACHE ├── LICENSE-MIT ├── README.md ├── etc └── spirv.json ├── glsl-examples ├── cast.glsl.vert ├── cast.spv.dis ├── constbuffer.glsl.dis ├── constbuffer.glsl.vert ├── empty.frag ├── empty.spv.dis ├── fragcoord.frag ├── fragcoord.spv.dis ├── function_call.dis ├── function_call.vert ├── if.glsl.vert ├── matrix.glsl.vert ├── matrix.spv.dis ├── references.glsl.vert ├── references.spv.dis ├── struct.glsl.vert ├── struct.spv.dis ├── texture.glsl.frag ├── texture.spv.dis ├── vec.glsl.vert ├── vec.spv.dis ├── vec_op.glsl.vert └── vec_op.spv.dis ├── libcore ├── Cargo.toml ├── clone.rs ├── cmp.rs ├── default.rs ├── internal_macros.rs ├── iter │ ├── iterator.rs │ ├── mod.rs │ ├── range.rs │ └── traits.rs ├── lib.rs ├── macros.rs ├── marker.rs ├── num │ ├── f32.rs │ └── f64.rs ├── ops.rs ├── option.rs └── prelude │ ├── mod.rs │ └── v1.rs ├── libstd ├── Cargo.toml ├── image.rs ├── interface.rs ├── lib.rs ├── matrix.rs ├── prelude │ ├── mod.rs │ └── v1.rs └── vector.rs ├── rust-examples └── quad.rs ├── src ├── adt.rs ├── attributes.rs ├── bin │ └── inspirv-rust.rs ├── block.rs ├── collector.rs ├── constants.rs ├── context.rs ├── error.rs ├── intrinsic.rs ├── legacy │ ├── attribute.rs │ ├── error.rs │ ├── intrinsic.rs │ ├── monomorphize.rs │ ├── traits.rs │ └── trans.rs ├── lib.rs ├── lvalue.rs ├── monomorphize.rs ├── operand.rs ├── rvalue.rs ├── statement.rs ├── trans_item.rs └── type_of.rs └── tests ├── compile-fail └── hello.rs └── tests.rs /.gitignore: -------------------------------------------------------------------------------- 1 | target 2 | Cargo.lock 3 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | authors = [ 3 | "Scott Olson ", 4 | "Brian Anderson ", 5 | "Alon Zakai ", 6 | "msiglreith " 7 | ] 8 | description = "An experimental compiler from Rust to SPIR-V." 9 | license = "MIT/Apache-2.0" 10 | name = "inspirv-rust" 11 | version = "0.1.0" 12 | 13 | [[bin]] 14 | doc = false 15 | name = "inspirv-rust" 16 | 17 | [dependencies] 18 | log = "0.3.6" 19 | env_logger = "0.3.3" 20 | libc = "0.2" 21 | inspirv = { git = "https://github.com/msiglreith/inspirv.git" } 22 | inspirv-builder = { git = "https://github.com/msiglreith/inspirv-builder.git" } 23 | # clippy = "*" 24 | petgraph = "0.4.1" 25 | 26 | [dev-dependencies] 27 | compiletest_rs = "0.2.4" 28 | -------------------------------------------------------------------------------- /LICENSE-APACHE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | 203 | Copyright 2016 The Miri Developers 204 | 205 | Licensed under the Apache License, Version 2.0 (the "License"); 206 | you may not use this file except in compliance with the License. 207 | You may obtain a copy of the License at 208 | 209 | http://www.apache.org/licenses/LICENSE-2.0 210 | 211 | Unless required by applicable law or agreed to in writing, software 212 | distributed under the License is distributed on an "AS IS" BASIS, 213 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 214 | See the License for the specific language governing permissions and 215 | limitations under the License. 216 | -------------------------------------------------------------------------------- /LICENSE-MIT: -------------------------------------------------------------------------------- 1 | Copyright (c) 2016 The Miri Developers 2 | 3 | Permission is hereby granted, free of charge, to any 4 | person obtaining a copy of this software and associated 5 | documentation files (the "Software"), to deal in the 6 | Software without restriction, including without 7 | limitation the rights to use, copy, modify, merge, 8 | publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software 10 | is furnished to do so, subject to the following 11 | conditions: 12 | 13 | The above copyright notice and this permission notice 14 | shall be included in all copies or substantial portions 15 | of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF 18 | ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED 19 | TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A 20 | PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT 21 | SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 22 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 23 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR 24 | IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 25 | DEALINGS IN THE SOFTWARE. 26 | 27 | Copyright (c) 2010 The Rust Project Developers 28 | 29 | Permission is hereby granted, free of charge, to any 30 | person obtaining a copy of this software and associated 31 | documentation files (the "Software"), to deal in the 32 | Software without restriction, including without 33 | limitation the rights to use, copy, modify, merge, 34 | publish, distribute, sublicense, and/or sell copies of 35 | the Software, and to permit persons to whom the Software 36 | is furnished to do so, subject to the following 37 | conditions: 38 | 39 | The above copyright notice and this permission notice 40 | shall be included in all copies or substantial portions 41 | of the Software. 42 | 43 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF 44 | ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED 45 | TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A 46 | PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT 47 | SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 48 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 49 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR 50 | IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 51 | DEALINGS IN THE SOFTWARE. 52 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # inspirv-rust 2 | 3 | UPDATE 2: Next design iteration would probably be based on HIR instead of MIR. See more details [here](https://github.com/gfx-rs/gfx/issues/71#issuecomment-316728752). In the meantime, you might want to checkout [rlsl](https://github.com/MaikKlein/rlsl)! 4 | 5 | UPDATE: Development currently slowed down as other projects (i.e gfx-rs) have priority over this one. Will keep on working on it in the future (see above)! 6 | 7 | An experimental compiler from [Rust] to [SPIR-V], using the `rustc` compiler and [MIR]. 8 | The code is based upon [rustc_trans::mir], legacy (_actually working_) version was based on [miri] and [mir2wasm]. 9 | 10 | ``` 11 | rustc 1.17.0-nightly (0e7727795 2017-02-19) 12 | ``` 13 | 14 | ## Build 15 | In order to build the standard and core library directly, you can run: 16 | 17 | ``` 18 | cargo run -- libcore\lib.rs --target=etc/spirv.json 19 | cargo run -- libstd\lib.rs --extern core=libcore.rlib -L . --target=etc/spirv.json 20 | ``` 21 | 22 | To build the quad example shader: 23 | 24 | ``` 25 | cargo run -- rust-examples\quad.rs --extern std=libstd.rlib --extern core=libcore.lib -L . --target=etc/spirv.json 26 | ``` 27 | 28 | ## Resources 29 | 30 | * [miri](https://github.com/solson/miri) the MIR interpreter. 31 | * [rustc_trans::mir](https://github.com/rust-lang/rust/tree/master/src/librustc_trans/mir). 32 | * [mir2wasm](https://github.com/brson/mir2wasm) 33 | 34 | ## License 35 | 36 | Licensed under either of 37 | * Apache License, Version 2.0 ([LICENSE-APACHE](LICENSE-APACHE) or 38 | http://www.apache.org/licenses/LICENSE-2.0) 39 | * MIT license ([LICENSE-MIT](LICENSE-MIT) or 40 | http://opensource.org/licenses/MIT) at your option. 41 | 42 | ### Contribution 43 | 44 | Unless you explicitly state otherwise, any contribution intentionally submitted 45 | for inclusion in the work by you shall be dual licensed as above, without any 46 | additional terms or conditions. 47 | 48 | [Rust]: https://www.rust-lang.org/ 49 | [MIR]: https://github.com/rust-lang/rfcs/blob/master/text/1211-mir.md 50 | [miri]: https://github.com/solson/miri 51 | [mir2wasm]: https://github.com/brson/mir2wasm 52 | [SPIR-V]: https://www.khronos.org/registry/spir-v/specs/1.1/SPIRV.html 53 | -------------------------------------------------------------------------------- /etc/spirv.json: -------------------------------------------------------------------------------- 1 | { 2 | "arch": "spirv", 3 | "cpu": "", 4 | "data-layout": "e-m:e-p:32:32-f64:32:64-f80:32-n8:16:32-S128", 5 | "disable-redzone": true, 6 | "executables": false, 7 | "llvm-target": "i686-unknown-linux-gnu", 8 | "morestack": false, 9 | "os": "none", 10 | "relocation-model": "static", 11 | "target-endian": "little", 12 | "target-pointer-width": "32", 13 | "no-compiler-rt": true, 14 | "pre-link-args": [], 15 | "post-link-args": [] 16 | } 17 | -------------------------------------------------------------------------------- /glsl-examples/cast.glsl.vert: -------------------------------------------------------------------------------- 1 | #version 450 2 | 3 | void main() { 4 | uint x = 0; 5 | float y = x; 6 | float t = float(uint(0)); 7 | } -------------------------------------------------------------------------------- /glsl-examples/cast.spv.dis: -------------------------------------------------------------------------------- 1 | cast.glsl.vert 2 | Warning, version 450 is not yet complete; most version-specific features are present, but some are missing. 3 | 4 | 5 | Linked vertex stage: 6 | 7 | 8 | // Module Version 10000 9 | // Generated by (magic number): 80001 10 | // Id's are bound by 17 11 | 12 | Capability Shader 13 | 1: ExtInstImport "GLSL.std.450" 14 | MemoryModel Logical GLSL450 15 | EntryPoint Vertex 4 "main" 16 | Source GLSL 450 17 | Name 4 "main" 18 | Name 8 "x" 19 | Name 12 "y" 20 | Name 15 "t" 21 | 2: TypeVoid 22 | 3: TypeFunction 2 23 | 6: TypeInt 32 0 24 | 7: TypePointer Function 6(int) 25 | 9: 6(int) Constant 0 26 | 10: TypeFloat 32 27 | 11: TypePointer Function 10(float) 28 | 16: 10(float) Constant 0 29 | 4(main): 2 Function None 3 30 | 5: Label 31 | 8(x): 7(ptr) Variable Function 32 | 12(y): 11(ptr) Variable Function 33 | 15(t): 11(ptr) Variable Function 34 | Store 8(x) 9 35 | 13: 6(int) Load 8(x) 36 | 14: 10(float) ConvertUToF 13 37 | Store 12(y) 14 38 | Store 15(t) 16 39 | Return 40 | FunctionEnd 41 | -------------------------------------------------------------------------------- /glsl-examples/constbuffer.glsl.dis: -------------------------------------------------------------------------------- 1 | constbuffer.glsl.vert 2 | Warning, version 450 is not yet complete; most version-specific features are present, but some are missing. 3 | 4 | 5 | Linked vertex stage: 6 | 7 | 8 | // Module Version 10000 9 | // Generated by (magic number): 80001 10 | // Id's are bound by 11 11 | 12 | Capability Shader 13 | 1: ExtInstImport "GLSL.std.450" 14 | MemoryModel Logical GLSL450 15 | EntryPoint Vertex 4 "main" 16 | Source GLSL 450 17 | Name 4 "main" 18 | Name 8 "Block" 19 | MemberName 8(Block) 0 "a" 20 | MemberName 8(Block) 1 "b" 21 | Name 10 "test" 22 | MemberDecorate 8(Block) 0 Offset 0 23 | MemberDecorate 8(Block) 1 Offset 8 24 | Decorate 8(Block) Block 25 | Decorate 10(test) DescriptorSet 0 26 | Decorate 10(test) Binding 0 27 | 2: TypeVoid 28 | 3: TypeFunction 2 29 | 6: TypeFloat 32 30 | 7: TypeVector 6(float) 2 31 | 8(Block): TypeStruct 7(fvec2) 7(fvec2) 32 | 9: TypePointer Uniform 8(Block) 33 | 10(test): 9(ptr) Variable Uniform 34 | 4(main): 2 Function None 3 35 | 5: Label 36 | Return 37 | FunctionEnd 38 | -------------------------------------------------------------------------------- /glsl-examples/constbuffer.glsl.vert: -------------------------------------------------------------------------------- 1 | 2 | #version 450 3 | 4 | layout(set = 0, binding = 0) uniform Block { 5 | vec2 a; 6 | vec2 b; 7 | } test; 8 | 9 | void main() { 10 | 11 | } 12 | -------------------------------------------------------------------------------- /glsl-examples/empty.frag: -------------------------------------------------------------------------------- 1 | #version 450 2 | 3 | void main() { 4 | 5 | } -------------------------------------------------------------------------------- /glsl-examples/empty.spv.dis: -------------------------------------------------------------------------------- 1 | empty.frag 2 | Warning, version 450 is not yet complete; most version-specific features are present, but some are missing. 3 | 4 | 5 | Linked fragment stage: 6 | 7 | 8 | // Module Version 10000 9 | // Generated by (magic number): 80001 10 | // Id's are bound by 6 11 | 12 | Capability Shader 13 | 1: ExtInstImport "GLSL.std.450" 14 | MemoryModel Logical GLSL450 15 | EntryPoint Fragment 4 "main" 16 | ExecutionMode 4 OriginUpperLeft 17 | Source GLSL 450 18 | Name 4 "main" 19 | 2: TypeVoid 20 | 3: TypeFunction 2 21 | 4(main): 2 Function None 3 22 | 5: Label 23 | Return 24 | FunctionEnd 25 | -------------------------------------------------------------------------------- /glsl-examples/fragcoord.frag: -------------------------------------------------------------------------------- 1 | #version 450 2 | 3 | in vec4 gl_FragCoord; 4 | layout(location=0) out vec4 color; 5 | 6 | void main() { 7 | vec4 c = gl_FragCoord; 8 | c.w = 1.0f; 9 | color = c; 10 | } -------------------------------------------------------------------------------- /glsl-examples/fragcoord.spv.dis: -------------------------------------------------------------------------------- 1 | fragcoord.frag 2 | Warning, version 450 is not yet complete; most version-specific features are present, but some are missing. 3 | 4 | 5 | Linked fragment stage: 6 | 7 | 8 | // Module Version 10000 9 | // Generated by (magic number): 80001 10 | // Id's are bound by 20 11 | 12 | Capability Shader 13 | 1: ExtInstImport "GLSL.std.450" 14 | MemoryModel Logical GLSL450 15 | EntryPoint Fragment 4 "main" 14 16 | ExecutionMode 4 OriginUpperLeft 17 | Source GLSL 450 18 | Name 4 "main" 19 | Name 9 "x" 20 | Name 14 "gl_FragCoord" 21 | Decorate 14(gl_FragCoord) BuiltIn FragCoord 22 | 2: TypeVoid 23 | 3: TypeFunction 2 24 | 6: TypeFloat 32 25 | 7: TypeVector 6(float) 4 26 | 8: TypePointer Function 7(fvec4) 27 | 10: 6(float) Constant 0 28 | 11: 6(float) Constant 1065353216 29 | 12: 7(fvec4) ConstantComposite 10 10 10 11 30 | 13: TypePointer Input 7(fvec4) 31 | 14(gl_FragCoord): 13(ptr) Variable Input 32 | 15: TypeVector 6(float) 2 33 | 4(main): 2 Function None 3 34 | 5: Label 35 | 9(x): 8(ptr) Variable Function 36 | Store 9(x) 12 37 | 16: 7(fvec4) Load 14(gl_FragCoord) 38 | 17: 15(fvec2) VectorShuffle 16 16 0 1 39 | 18: 7(fvec4) Load 9(x) 40 | 19: 7(fvec4) VectorShuffle 18 17 4 5 2 3 41 | Store 9(x) 19 42 | Return 43 | FunctionEnd 44 | -------------------------------------------------------------------------------- /glsl-examples/function_call.dis: -------------------------------------------------------------------------------- 1 | function_call.vert 2 | Warning, version 450 is not yet complete; most version-specific features are present, but some are missing. 3 | 4 | 5 | Linked vertex stage: 6 | 7 | 8 | // Module Version 10000 9 | // Generated by (magic number): 80001 10 | // Id's are bound by 19 11 | 12 | Capability Shader 13 | 1: ExtInstImport "GLSL.std.450" 14 | MemoryModel Logical GLSL450 15 | EntryPoint Vertex 4 "main" 16 | Source GLSL 450 17 | Name 4 "main" 18 | Name 10 "foo(f1;" 19 | Name 9 "x" 20 | Name 15 "y" 21 | Name 17 "param" 22 | 2: TypeVoid 23 | 3: TypeFunction 2 24 | 6: TypeFloat 32 25 | 7: TypePointer Function 6(float) 26 | 8: TypeFunction 6(float) 7(ptr) 27 | 16: 6(float) Constant 0 28 | 4(main): 2 Function None 3 29 | 5: Label 30 | 15(y): 7(ptr) Variable Function 31 | 17(param): 7(ptr) Variable Function 32 | Store 17(param) 16 33 | 18: 6(float) FunctionCall 10(foo(f1;) 17(param) 34 | Store 15(y) 18 35 | Return 36 | FunctionEnd 37 | 10(foo(f1;): 6(float) Function None 8 38 | 9(x): 7(ptr) FunctionParameter 39 | 11: Label 40 | 12: 6(float) Load 9(x) 41 | ReturnValue 12 42 | FunctionEnd 43 | -------------------------------------------------------------------------------- /glsl-examples/function_call.vert: -------------------------------------------------------------------------------- 1 | 2 | #version 450 3 | 4 | float foo(float x) { return x; } 5 | 6 | void main() { 7 | float y = foo(0.0f); 8 | } 9 | -------------------------------------------------------------------------------- /glsl-examples/if.glsl.vert: -------------------------------------------------------------------------------- 1 | #version 450 2 | 3 | bool foo(uint x) { 4 | return x < 4; 5 | } 6 | void main() { 7 | uint cond = 3; 8 | if (foo(cond)) { 9 | uint x = 0; 10 | uint y = x+1; 11 | } else { 12 | uint a = 1; 13 | uint b = a*a; 14 | } 15 | } -------------------------------------------------------------------------------- /glsl-examples/matrix.glsl.vert: -------------------------------------------------------------------------------- 1 | #version 450 2 | 3 | struct test { mat4 a; vec4 b; }; 4 | 5 | void main() { 6 | mat4 x; 7 | transpose(x); 8 | inverse(x); 9 | mat4 y = x + x; 10 | mat4 z = y - x; 11 | 12 | test struct_test; 13 | 14 | struct_test.a += x; 15 | struct_test.b += vec4(1.0); 16 | 17 | y += x; 18 | z += y; 19 | } -------------------------------------------------------------------------------- /glsl-examples/matrix.spv.dis: -------------------------------------------------------------------------------- 1 | matrix.glsl.vert 2 | Warning, version 450 is not yet complete; most version-specific features are present, but some are missing. 3 | 4 | 5 | Linked vertex stage: 6 | 7 | 8 | // Module Version 10000 9 | // Generated by (magic number): 80001 10 | // Id's are bound by 30 11 | 12 | Capability Shader 13 | 1: ExtInstImport "GLSL.std.450" 14 | MemoryModel Logical GLSL450 15 | EntryPoint Vertex 4 "main" 16 | Source GLSL 450 17 | Name 4 "main" 18 | Name 9 "test" 19 | MemberName 9(test) 0 "a" 20 | MemberName 9(test) 1 "b" 21 | Name 11 "struct_test" 22 | Name 15 "x" 23 | 2: TypeVoid 24 | 3: TypeFunction 2 25 | 6: TypeFloat 32 26 | 7: TypeVector 6(float) 4 27 | 8: TypeMatrix 7(fvec4) 4 28 | 9(test): TypeStruct 8 7(fvec4) 29 | 10: TypePointer Function 9(test) 30 | 12: TypeInt 32 1 31 | 13: 12(int) Constant 0 32 | 14: TypePointer Function 8 33 | 16: TypePointer Function 7(fvec4) 34 | 23: 12(int) Constant 1 35 | 24: 6(float) Constant 1065353216 36 | 25: 7(fvec4) ConstantComposite 24 24 24 24 37 | 4(main): 2 Function None 3 38 | 5: Label 39 | 11(struct_test): 10(ptr) Variable Function 40 | 15(x): 14(ptr) Variable Function 41 | 17: 16(ptr) AccessChain 15(x) 13 42 | 18: 7(fvec4) Load 17 43 | 19: 16(ptr) AccessChain 11(struct_test) 13 13 44 | 20: 7(fvec4) Load 19 45 | 21: 7(fvec4) FAdd 20 18 46 | 22: 16(ptr) AccessChain 11(struct_test) 13 13 47 | Store 22 21 48 | 26: 16(ptr) AccessChain 11(struct_test) 23 49 | 27: 7(fvec4) Load 26 50 | 28: 7(fvec4) FAdd 27 25 51 | 29: 16(ptr) AccessChain 11(struct_test) 23 52 | Store 29 28 53 | Return 54 | FunctionEnd 55 | -------------------------------------------------------------------------------- /glsl-examples/references.glsl.vert: -------------------------------------------------------------------------------- 1 | #version 450 2 | 3 | void foo(out float bar, inout float baz, in float a, float b) { 4 | baz += 2.0f; 5 | bar = baz; 6 | } 7 | 8 | void main() { 9 | float bar = 0.0f; 10 | float baz = 0.0f; 11 | float a = 5.0f; 12 | foo(bar, baz, a, 5.0f); 13 | } 14 | -------------------------------------------------------------------------------- /glsl-examples/references.spv.dis: -------------------------------------------------------------------------------- 1 | references.glsl.vert 2 | Warning, version 450 is not yet complete; most version-specific features are present, but some are missing. 3 | 4 | 5 | Linked vertex stage: 6 | 7 | 8 | // Module Version 10000 9 | // Generated by (magic number): 80001 10 | // Id's are bound by 33 11 | 12 | Capability Shader 13 | 1: ExtInstImport "GLSL.std.450" 14 | MemoryModel Logical GLSL450 15 | EntryPoint Vertex 4 "main" 16 | Source GLSL 450 17 | Name 4 "main" 18 | Name 13 "foo(f1;f1;f1;f1;" 19 | Name 9 "bar" 20 | Name 10 "baz" 21 | Name 11 "a" 22 | Name 12 "b" 23 | Name 19 "bar" 24 | Name 21 "baz" 25 | Name 22 "a" 26 | Name 24 "param" 27 | Name 25 "param" 28 | Name 27 "param" 29 | Name 29 "param" 30 | 2: TypeVoid 31 | 3: TypeFunction 2 32 | 6: TypeFloat 32 33 | 7: TypePointer Function 6(float) 34 | 8: TypeFunction 2 7(ptr) 7(ptr) 7(ptr) 7(ptr) 35 | 15: 6(float) Constant 1073741824 36 | 20: 6(float) Constant 0 37 | 23: 6(float) Constant 1084227584 38 | 4(main): 2 Function None 3 39 | 5: Label 40 | 19(bar): 7(ptr) Variable Function 41 | 21(baz): 7(ptr) Variable Function 42 | 22(a): 7(ptr) Variable Function 43 | 24(param): 7(ptr) Variable Function 44 | 25(param): 7(ptr) Variable Function 45 | 27(param): 7(ptr) Variable Function 46 | 29(param): 7(ptr) Variable Function 47 | Store 19(bar) 20 48 | Store 21(baz) 20 49 | Store 22(a) 23 50 | 26: 6(float) Load 21(baz) 51 | Store 25(param) 26 52 | 28: 6(float) Load 22(a) 53 | Store 27(param) 28 54 | Store 29(param) 23 55 | 30: 2 FunctionCall 13(foo(f1;f1;f1;f1;) 24(param) 25(param) 27(param) 29(param) 56 | 31: 6(float) Load 24(param) 57 | Store 19(bar) 31 58 | 32: 6(float) Load 25(param) 59 | Store 21(baz) 32 60 | Return 61 | FunctionEnd 62 | 13(foo(f1;f1;f1;f1;): 2 Function None 8 63 | 9(bar): 7(ptr) FunctionParameter 64 | 10(baz): 7(ptr) FunctionParameter 65 | 11(a): 7(ptr) FunctionParameter 66 | 12(b): 7(ptr) FunctionParameter 67 | 14: Label 68 | 16: 6(float) Load 10(baz) 69 | 17: 6(float) FAdd 16 15 70 | Store 10(baz) 17 71 | 18: 6(float) Load 10(baz) 72 | Store 9(bar) 18 73 | Return 74 | FunctionEnd 75 | -------------------------------------------------------------------------------- /glsl-examples/struct.glsl.vert: -------------------------------------------------------------------------------- 1 | #version 450 2 | 3 | struct B { float a; }; 4 | 5 | layout(set = 0, binding = 0) uniform Block { 6 | vec2 a; 7 | B b; 8 | mat4 c; 9 | } test; 10 | 11 | void main() {} -------------------------------------------------------------------------------- /glsl-examples/struct.spv.dis: -------------------------------------------------------------------------------- 1 | struct.glsl.vert 2 | Warning, version 450 is not yet complete; most version-specific features are present, but some are missing. 3 | 4 | 5 | Linked vertex stage: 6 | 7 | 8 | // Module Version 10000 9 | // Generated by (magic number): 80001 10 | // Id's are bound by 14 11 | 12 | Capability Shader 13 | 1: ExtInstImport "GLSL.std.450" 14 | MemoryModel Logical GLSL450 15 | EntryPoint Vertex 4 "main" 16 | Source GLSL 450 17 | Name 4 "main" 18 | Name 8 "B" 19 | MemberName 8(B) 0 "a" 20 | Name 11 "Block" 21 | MemberName 11(Block) 0 "a" 22 | MemberName 11(Block) 1 "b" 23 | MemberName 11(Block) 2 "c" 24 | Name 13 "test" 25 | MemberDecorate 8(B) 0 Offset 0 26 | MemberDecorate 11(Block) 0 Offset 0 27 | MemberDecorate 11(Block) 1 Offset 16 28 | MemberDecorate 11(Block) 2 ColMajor 29 | MemberDecorate 11(Block) 2 Offset 32 30 | MemberDecorate 11(Block) 2 MatrixStride 16 31 | Decorate 11(Block) Block 32 | Decorate 13(test) DescriptorSet 0 33 | Decorate 13(test) Binding 0 34 | 2: TypeVoid 35 | 3: TypeFunction 2 36 | 6: TypeFloat 32 37 | 7: TypeVector 6(float) 2 38 | 8(B): TypeStruct 6(float) 39 | 9: TypeVector 6(float) 4 40 | 10: TypeMatrix 9(fvec4) 4 41 | 11(Block): TypeStruct 7(fvec2) 8(B) 10 42 | 12: TypePointer Uniform 11(Block) 43 | 13(test): 12(ptr) Variable Uniform 44 | 4(main): 2 Function None 3 45 | 5: Label 46 | Return 47 | FunctionEnd 48 | -------------------------------------------------------------------------------- /glsl-examples/texture.glsl.frag: -------------------------------------------------------------------------------- 1 | #version 450 2 | 3 | uniform sampler s; 4 | uniform texture2D t; 5 | uniform sampler2D ts; 6 | 7 | void main() { 8 | vec4 color = texture(sampler2D(t, s), vec2(1.0, 1.0)); 9 | } -------------------------------------------------------------------------------- /glsl-examples/texture.spv.dis: -------------------------------------------------------------------------------- 1 | texture.glsl.frag 2 | Warning, version 450 is not yet complete; most version-specific features are present, but some are missing. 3 | 4 | 5 | Linked fragment stage: 6 | 7 | 8 | // Module Version 10000 9 | // Generated by (magic number): 80001 10 | // Id's are bound by 26 11 | 12 | Capability Shader 13 | 1: ExtInstImport "GLSL.std.450" 14 | MemoryModel Logical GLSL450 15 | EntryPoint Fragment 4 "main" 16 | ExecutionMode 4 OriginLowerLeft 17 | Source GLSL 450 18 | Name 4 "main" 19 | Name 9 "color" 20 | Name 12 "t" 21 | Name 16 "s" 22 | Name 25 "ts" 23 | Decorate 12(t) DescriptorSet 0 24 | Decorate 16(s) DescriptorSet 0 25 | Decorate 25(ts) DescriptorSet 0 26 | 2: TypeVoid 27 | 3: TypeFunction 2 28 | 6: TypeFloat 32 29 | 7: TypeVector 6(float) 4 30 | 8: TypePointer Function 7(fvec4) 31 | 10: TypeImage 6(float) 2D sampled format:Unknown 32 | 11: TypePointer UniformConstant 10 33 | 12(t): 11(ptr) Variable UniformConstant 34 | 14: TypeSampler 35 | 15: TypePointer UniformConstant 14 36 | 16(s): 15(ptr) Variable UniformConstant 37 | 18: TypeSampledImage 10 38 | 20: TypeVector 6(float) 2 39 | 21: 6(float) Constant 1065353216 40 | 22: 20(fvec2) ConstantComposite 21 21 41 | 24: TypePointer UniformConstant 18 42 | 25(ts): 24(ptr) Variable UniformConstant 43 | 4(main): 2 Function None 3 44 | 5: Label 45 | 9(color): 8(ptr) Variable Function 46 | 13: 10 Load 12(t) 47 | 17: 14 Load 16(s) 48 | 19: 18 SampledImage 13 17 49 | 23: 7(fvec4) ImageSampleImplicitLod 19 22 50 | Store 9(color) 23 51 | Return 52 | FunctionEnd 53 | -------------------------------------------------------------------------------- /glsl-examples/vec.glsl.vert: -------------------------------------------------------------------------------- 1 | #version 450 2 | 3 | void main() { 4 | float x = 3.0f; 5 | float y = x + 0.5f; 6 | vec4 v = vec4(x, y, 1.0f, 0.0f); 7 | vec2 v2 = vec2(1.0, 1.0); 8 | vec4 v3 = vec4(v2, 0.3f, 0.2f); 9 | v3.yx = v.xx; 10 | v3.w = 1.0f; 11 | } -------------------------------------------------------------------------------- /glsl-examples/vec.spv.dis: -------------------------------------------------------------------------------- 1 | vec.glsl.vert 2 | Warning, version 450 is not yet complete; most version-specific features are present, but some are missing. 3 | 4 | 5 | Linked vertex stage: 6 | 7 | 8 | // Module Version 10000 9 | // Generated by (magic number): 80001 10 | // Id's are bound by 40 11 | 12 | Capability Shader 13 | 1: ExtInstImport "GLSL.std.450" 14 | MemoryModel Logical GLSL450 15 | EntryPoint Vertex 4 "main" 16 | Source GLSL 450 17 | Name 4 "main" 18 | Name 8 "x" 19 | Name 10 "y" 20 | Name 16 "v" 21 | Name 24 "v2" 22 | Name 26 "v3" 23 | 2: TypeVoid 24 | 3: TypeFunction 2 25 | 6: TypeFloat 32 26 | 7: TypePointer Function 6(float) 27 | 9: 6(float) Constant 1077936128 28 | 12: 6(float) Constant 1056964608 29 | 14: TypeVector 6(float) 4 30 | 15: TypePointer Function 14(fvec4) 31 | 19: 6(float) Constant 1065353216 32 | 20: 6(float) Constant 0 33 | 22: TypeVector 6(float) 2 34 | 23: TypePointer Function 22(fvec2) 35 | 25: 22(fvec2) ConstantComposite 19 19 36 | 28: 6(float) Constant 1050253722 37 | 29: 6(float) Constant 1045220557 38 | 37: TypeInt 32 0 39 | 38: 37(int) Constant 3 40 | 4(main): 2 Function None 3 41 | 5: Label 42 | 8(x): 7(ptr) Variable Function 43 | 10(y): 7(ptr) Variable Function 44 | 16(v): 15(ptr) Variable Function 45 | 24(v2): 23(ptr) Variable Function 46 | 26(v3): 15(ptr) Variable Function 47 | Store 8(x) 9 48 | 11: 6(float) Load 8(x) 49 | 13: 6(float) FAdd 11 12 50 | Store 10(y) 13 51 | 17: 6(float) Load 8(x) 52 | 18: 6(float) Load 10(y) 53 | 21: 14(fvec4) CompositeConstruct 17 18 19 20 54 | Store 16(v) 21 55 | Store 24(v2) 25 56 | 27: 22(fvec2) Load 24(v2) 57 | 30: 6(float) CompositeExtract 27 0 58 | 31: 6(float) CompositeExtract 27 1 59 | 32: 14(fvec4) CompositeConstruct 30 31 28 29 60 | Store 26(v3) 32 61 | 33: 14(fvec4) Load 16(v) 62 | 34: 22(fvec2) VectorShuffle 33 33 0 0 63 | 35: 14(fvec4) Load 26(v3) 64 | 36: 14(fvec4) VectorShuffle 35 34 5 4 2 3 65 | Store 26(v3) 36 66 | 39: 7(ptr) AccessChain 26(v3) 38 67 | Store 39 19 68 | Return 69 | FunctionEnd 70 | -------------------------------------------------------------------------------- /glsl-examples/vec_op.glsl.vert: -------------------------------------------------------------------------------- 1 | #version 450 2 | 3 | void main() { 4 | vec3 w = vec3(1.0, 0.3, 0.2); 5 | vec3 x = normalize(w); 6 | vec3 y = cross(x, x); 7 | } -------------------------------------------------------------------------------- /glsl-examples/vec_op.spv.dis: -------------------------------------------------------------------------------- 1 | vec_op.glsl.vert 2 | Warning, version 450 is not yet complete; most version-specific features are present, but some are missing. 3 | 4 | 5 | Linked vertex stage: 6 | 7 | 8 | // Module Version 10000 9 | // Generated by (magic number): 80001 10 | // Id's are bound by 21 11 | 12 | Capability Shader 13 | 1: ExtInstImport "GLSL.std.450" 14 | MemoryModel Logical GLSL450 15 | EntryPoint Vertex 4 "main" 16 | Source GLSL 450 17 | Name 4 "main" 18 | Name 9 "w" 19 | Name 14 "x" 20 | Name 17 "y" 21 | 2: TypeVoid 22 | 3: TypeFunction 2 23 | 6: TypeFloat 32 24 | 7: TypeVector 6(float) 3 25 | 8: TypePointer Function 7(fvec3) 26 | 10: 6(float) Constant 1065353216 27 | 11: 6(float) Constant 1050253722 28 | 12: 6(float) Constant 1045220557 29 | 13: 7(fvec3) ConstantComposite 10 11 12 30 | 4(main): 2 Function None 3 31 | 5: Label 32 | 9(w): 8(ptr) Variable Function 33 | 14(x): 8(ptr) Variable Function 34 | 17(y): 8(ptr) Variable Function 35 | Store 9(w) 13 36 | 15: 7(fvec3) Load 9(w) 37 | 16: 7(fvec3) ExtInst 1(GLSL.std.450) 69(Normalize) 15 38 | Store 14(x) 16 39 | 18: 7(fvec3) Load 14(x) 40 | 19: 7(fvec3) Load 14(x) 41 | 20: 7(fvec3) ExtInst 1(GLSL.std.450) 68(Cross) 18 19 42 | Store 17(y) 20 43 | Return 44 | FunctionEnd 45 | -------------------------------------------------------------------------------- /libcore/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "core" 3 | version = "0.1.0" 4 | 5 | [lib] 6 | name = "core" 7 | path = "lib.rs" 8 | -------------------------------------------------------------------------------- /libcore/clone.rs: -------------------------------------------------------------------------------- 1 | 2 | use super::marker::Sized; 3 | 4 | pub trait Clone : Sized { 5 | fn clone(&self) -> Self; 6 | } 7 | -------------------------------------------------------------------------------- /libcore/cmp.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT 2 | // file at the top-level directory of this distribution and at 3 | // http://rust-lang.org/COPYRIGHT. 4 | // 5 | // Licensed under the Apache License, Version 2.0 or the MIT license 7 | // , at your 8 | // option. This file may not be copied, modified, or distributed 9 | // except according to those terms. 10 | 11 | //! Functionality for ordering and comparison. 12 | //! 13 | //! This module defines both [`PartialOrd`] and [`PartialEq`] traits which are used 14 | //! by the compiler to implement comparison operators. Rust programs may 15 | //! implement [`PartialOrd`] to overload the `<`, `<=`, `>`, and `>=` operators, 16 | //! and may implement [`PartialEq`] to overload the `==` and `!=` operators. 17 | //! 18 | //! [`PartialOrd`]: trait.PartialOrd.html 19 | //! [`PartialEq`]: trait.PartialEq.html 20 | //! 21 | //! # Examples 22 | //! 23 | //! ``` 24 | //! let x: u32 = 0; 25 | //! let y: u32 = 1; 26 | //! 27 | //! // these two lines are equivalent 28 | //! assert_eq!(x < y, true); 29 | //! assert_eq!(x.lt(&y), true); 30 | //! 31 | //! // these two lines are also equivalent 32 | //! assert_eq!(x == y, false); 33 | //! assert_eq!(x.eq(&y), false); 34 | //! ``` 35 | 36 | use super::marker::Sized; 37 | 38 | /// Trait for equality comparisons which are [partial equivalence 39 | /// relations](http://en.wikipedia.org/wiki/Partial_equivalence_relation). 40 | /// 41 | /// Formally, the equality must be (for all `a`, `b` and `c`): 42 | /// 43 | /// - symmetric: `a == b` implies `b == a`; and 44 | /// - transitive: `a == b` and `b == c` implies `a == c`. 45 | /// 46 | /// Note that these requirements mean that the trait itself must be implemented 47 | /// symmetrically and transitively: if `T: PartialEq` and `U: PartialEq` 48 | /// then `U: PartialEq` and `T: PartialEq`. 49 | /// 50 | /// ## How can I implement `PartialEq`? 51 | /// 52 | /// PartialEq only requires the `eq` method to be implemented; `ne` is defined 53 | /// in terms of it by default. Any manual implementation of `ne` *must* respect 54 | /// the rule that `eq` is a strict inverse of `ne`; that is, `!(a == b)` if and 55 | /// only if `a != b`. 56 | /// 57 | /// # Examples 58 | /// 59 | /// ``` 60 | /// let x: u32 = 0; 61 | /// let y: u32 = 1; 62 | /// 63 | /// assert_eq!(x == y, false); 64 | /// assert_eq!(x.eq(&y), false); 65 | /// ``` 66 | #[lang = "eq"] 67 | pub trait PartialEq { 68 | /// This method tests for `self` and `other` values to be equal, and is used 69 | /// by `==`. 70 | fn eq(&self, other: &Rhs) -> bool; 71 | 72 | /// This method tests for `!=`. 73 | #[inline] 74 | fn ne(&self, other: &Rhs) -> bool { !self.eq(other) } 75 | } 76 | 77 | pub trait Eq: PartialEq { } 78 | 79 | #[lang = "ord"] 80 | pub trait PartialOrd: PartialEq { 81 | /// This method tests less than (for `self` and `other`) and is used by the `<` operator. 82 | /// 83 | /// # Examples 84 | /// 85 | /// ``` 86 | /// let result = 1.0 < 2.0; 87 | /// assert_eq!(result, true); 88 | /// 89 | /// let result = 2.0 < 1.0; 90 | /// assert_eq!(result, false); 91 | /// ``` 92 | #[inline] 93 | fn lt(&self, other: &Rhs) -> bool; 94 | 95 | /// This method tests less than or equal to (for `self` and `other`) and is used by the `<=` 96 | /// operator. 97 | /// 98 | /// # Examples 99 | /// 100 | /// ``` 101 | /// let result = 1.0 <= 2.0; 102 | /// assert_eq!(result, true); 103 | /// 104 | /// let result = 2.0 <= 2.0; 105 | /// assert_eq!(result, true); 106 | /// ``` 107 | #[inline] 108 | fn le(&self, other: &Rhs) -> bool; 109 | 110 | /// This method tests greater than (for `self` and `other`) and is used by the `>` operator. 111 | /// 112 | /// # Examples 113 | /// 114 | /// ``` 115 | /// let result = 1.0 > 2.0; 116 | /// assert_eq!(result, false); 117 | /// 118 | /// let result = 2.0 > 2.0; 119 | /// assert_eq!(result, false); 120 | /// ``` 121 | #[inline] 122 | fn gt(&self, other: &Rhs) -> bool; 123 | 124 | /// This method tests greater than or equal to (for `self` and `other`) and is used by the `>=` 125 | /// operator. 126 | /// 127 | /// # Examples 128 | /// 129 | /// ``` 130 | /// let result = 2.0 >= 1.0; 131 | /// assert_eq!(result, true); 132 | /// 133 | /// let result = 2.0 >= 2.0; 134 | /// assert_eq!(result, true); 135 | /// ``` 136 | #[inline] 137 | fn ge(&self, other: &Rhs) -> bool; 138 | } 139 | 140 | pub trait Ord: Eq + PartialOrd { 141 | } 142 | 143 | // Implementation of PartialEq, Eq, PartialOrd and Ord for primitive types 144 | mod impls { 145 | macro_rules! partial_eq_impl { 146 | ($($t:ty)*) => ($( 147 | 148 | impl PartialEq for $t { 149 | #[inline] 150 | fn eq(&self, other: &$t) -> bool { (*self) == (*other) } 151 | #[inline] 152 | fn ne(&self, other: &$t) -> bool { (*self) != (*other) } 153 | } 154 | )*) 155 | } 156 | 157 | impl PartialEq for () { 158 | #[inline] 159 | fn eq(&self, _other: &()) -> bool { true } 160 | #[inline] 161 | fn ne(&self, _other: &()) -> bool { false } 162 | } 163 | 164 | partial_eq_impl! { 165 | bool char usize u16 u32 u64 isize i16 i32 i64 f32 f64 166 | } 167 | 168 | macro_rules! eq_impl { 169 | ($($t:ty)*) => ($( 170 | 171 | impl Eq for $t {} 172 | )*) 173 | } 174 | 175 | eq_impl! { () bool char usize u16 u32 u64 isize i16 i32 i64 } 176 | 177 | macro_rules! partial_ord_impl { 178 | ($($t:ty)*) => ($( 179 | 180 | impl PartialOrd for $t { 181 | #[inline] 182 | fn lt(&self, other: &$t) -> bool { (*self) < (*other) } 183 | #[inline] 184 | fn le(&self, other: &$t) -> bool { (*self) <= (*other) } 185 | #[inline] 186 | fn ge(&self, other: &$t) -> bool { (*self) >= (*other) } 187 | #[inline] 188 | fn gt(&self, other: &$t) -> bool { (*self) > (*other) } 189 | } 190 | )*) 191 | } 192 | 193 | partial_ord_impl! { f32 f64 } 194 | 195 | macro_rules! ord_impl { 196 | ($($t:ty)*) => ($( 197 | impl PartialOrd for $t { 198 | #[inline] 199 | fn lt(&self, other: &$t) -> bool { (*self) < (*other) } 200 | #[inline] 201 | fn le(&self, other: &$t) -> bool { (*self) <= (*other) } 202 | #[inline] 203 | fn ge(&self, other: &$t) -> bool { (*self) >= (*other) } 204 | #[inline] 205 | fn gt(&self, other: &$t) -> bool { (*self) > (*other) } 206 | } 207 | 208 | 209 | impl Ord for $t { 210 | } 211 | )*) 212 | } 213 | 214 | ord_impl! { bool char usize u16 u32 u64 isize i16 i32 i64 } 215 | 216 | impl PartialEq for ! { 217 | fn eq(&self, _: &!) -> bool { 218 | *self 219 | } 220 | } 221 | 222 | impl Eq for ! {} 223 | } -------------------------------------------------------------------------------- /libcore/default.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2013 The Rust Project Developers. See the COPYRIGHT 2 | // file at the top-level directory of this distribution and at 3 | // http://rust-lang.org/COPYRIGHT. 4 | // 5 | // Licensed under the Apache License, Version 2.0 or the MIT license 7 | // , at your 8 | // option. This file may not be copied, modified, or distributed 9 | // except according to those terms. 10 | 11 | //! The `Default` trait for types which may have meaningful default values. 12 | 13 | /// A trait for giving a type a useful default value. 14 | /// 15 | /// Sometimes, you want to fall back to some kind of default value, and 16 | /// don't particularly care what it is. This comes up often with `struct`s 17 | /// that define a set of options: 18 | /// 19 | /// ``` 20 | /// # #[allow(dead_code)] 21 | /// struct SomeOptions { 22 | /// foo: i32, 23 | /// bar: f32, 24 | /// } 25 | /// ``` 26 | /// 27 | /// How can we define some default values? You can use `Default`: 28 | /// 29 | /// ``` 30 | /// # #[allow(dead_code)] 31 | /// #[derive(Default)] 32 | /// struct SomeOptions { 33 | /// foo: i32, 34 | /// bar: f32, 35 | /// } 36 | /// 37 | /// fn main() { 38 | /// let options: SomeOptions = Default::default(); 39 | /// } 40 | /// ``` 41 | /// 42 | /// Now, you get all of the default values. Rust implements `Default` for various primitives types. 43 | /// 44 | /// If you want to override a particular option, but still retain the other defaults: 45 | /// 46 | /// ``` 47 | /// # #[allow(dead_code)] 48 | /// # #[derive(Default)] 49 | /// # struct SomeOptions { 50 | /// # foo: i32, 51 | /// # bar: f32, 52 | /// # } 53 | /// fn main() { 54 | /// let options = SomeOptions { foo: 42, ..Default::default() }; 55 | /// } 56 | /// ``` 57 | /// 58 | /// ## Derivable 59 | /// 60 | /// This trait can be used with `#[derive]` if all of the type's fields implement 61 | /// `Default`. When `derive`d, it will use the default value for each field's type. 62 | /// 63 | /// ## How can I implement `Default`? 64 | /// 65 | /// Provide an implementation for the `default()` method that returns the value of 66 | /// your type that should be the default: 67 | /// 68 | /// ``` 69 | /// # #![allow(dead_code)] 70 | /// enum Kind { 71 | /// A, 72 | /// B, 73 | /// C, 74 | /// } 75 | /// 76 | /// impl Default for Kind { 77 | /// fn default() -> Kind { Kind::A } 78 | /// } 79 | /// ``` 80 | /// 81 | /// # Examples 82 | /// 83 | /// ``` 84 | /// # #[allow(dead_code)] 85 | /// #[derive(Default)] 86 | /// struct SomeOptions { 87 | /// foo: i32, 88 | /// bar: f32, 89 | /// } 90 | /// ``` 91 | pub trait Default: Sized { 92 | /// Returns the "default value" for a type. 93 | /// 94 | /// Default values are often some kind of initial value, identity value, or anything else that 95 | /// may make sense as a default. 96 | /// 97 | /// # Examples 98 | /// 99 | /// Using built-in default values: 100 | /// 101 | /// ``` 102 | /// let i: i8 = Default::default(); 103 | /// let (x, y): (Option, f64) = Default::default(); 104 | /// let (a, b, (c, d)): (i32, u32, (bool, bool)) = Default::default(); 105 | /// ``` 106 | /// 107 | /// Making your own: 108 | /// 109 | /// ``` 110 | /// # #[allow(dead_code)] 111 | /// enum Kind { 112 | /// A, 113 | /// B, 114 | /// C, 115 | /// } 116 | /// 117 | /// impl Default for Kind { 118 | /// fn default() -> Kind { Kind::A } 119 | /// } 120 | /// ``` 121 | fn default() -> Self; 122 | } 123 | 124 | macro_rules! default_impl { 125 | ($t:ty, $v:expr) => { 126 | impl Default for $t { 127 | #[inline] 128 | fn default() -> $t { $v } 129 | } 130 | } 131 | } 132 | 133 | default_impl! { (), () } 134 | default_impl! { bool, false } 135 | 136 | default_impl! { usize, 0 } 137 | default_impl! { u16, 0 } 138 | default_impl! { u32, 0 } 139 | default_impl! { u64, 0 } 140 | 141 | default_impl! { isize, 0 } 142 | default_impl! { i16, 0 } 143 | default_impl! { i32, 0 } 144 | default_impl! { i64, 0 } 145 | 146 | default_impl! { f32, 0.0f32 } 147 | default_impl! { f64, 0.0f64 } 148 | -------------------------------------------------------------------------------- /libcore/internal_macros.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2016 The Rust Project Developers. See the COPYRIGHT 2 | // file at the top-level directory of this distribution and at 3 | // http://rust-lang.org/COPYRIGHT. 4 | // 5 | // Licensed under the Apache License, Version 2.0 or the MIT license 7 | // , at your 8 | // option. This file may not be copied, modified, or distributed 9 | // except according to those terms. 10 | 11 | 12 | // implements the unary operator "op &T" 13 | // based on "op T" where T is expected to be `Copy`able 14 | macro_rules! forward_ref_unop { 15 | (impl $imp:ident, $method:ident for $t:ty) => { 16 | impl<'a> $imp for &'a $t { 17 | type Output = <$t as $imp>::Output; 18 | 19 | #[inline] 20 | fn $method(self) -> <$t as $imp>::Output { 21 | $imp::$method(*self) 22 | } 23 | } 24 | }; 25 | (impl $imp:ident, $method:ident for $t:ty, #[$attr:meta]) => { 26 | #[$attr] 27 | impl<'a> $imp for &'a $t { 28 | type Output = <$t as $imp>::Output; 29 | 30 | #[inline] 31 | fn $method(self) -> <$t as $imp>::Output { 32 | $imp::$method(*self) 33 | } 34 | } 35 | } 36 | } 37 | 38 | // implements binary operators "&T op U", "T op &U", "&T op &U" 39 | // based on "T op U" where T and U are expected to be `Copy`able 40 | macro_rules! forward_ref_binop { 41 | (impl $imp:ident, $method:ident for $t:ty, $u:ty) => { 42 | impl<'a> $imp<$u> for &'a $t { 43 | type Output = <$t as $imp<$u>>::Output; 44 | 45 | #[inline] 46 | fn $method(self, other: $u) -> <$t as $imp<$u>>::Output { 47 | $imp::$method(*self, other) 48 | } 49 | } 50 | 51 | impl<'a> $imp<&'a $u> for $t { 52 | type Output = <$t as $imp<$u>>::Output; 53 | 54 | #[inline] 55 | fn $method(self, other: &'a $u) -> <$t as $imp<$u>>::Output { 56 | $imp::$method(self, *other) 57 | } 58 | } 59 | 60 | impl<'a, 'b> $imp<&'a $u> for &'b $t { 61 | type Output = <$t as $imp<$u>>::Output; 62 | 63 | #[inline] 64 | fn $method(self, other: &'a $u) -> <$t as $imp<$u>>::Output { 65 | $imp::$method(*self, *other) 66 | } 67 | } 68 | }; 69 | (impl $imp:ident, $method:ident for $t:ty, $u:ty, #[$attr:meta]) => { 70 | #[$attr] 71 | impl<'a> $imp<$u> for &'a $t { 72 | type Output = <$t as $imp<$u>>::Output; 73 | 74 | #[inline] 75 | fn $method(self, other: $u) -> <$t as $imp<$u>>::Output { 76 | $imp::$method(*self, other) 77 | } 78 | } 79 | 80 | #[$attr] 81 | impl<'a> $imp<&'a $u> for $t { 82 | type Output = <$t as $imp<$u>>::Output; 83 | 84 | #[inline] 85 | fn $method(self, other: &'a $u) -> <$t as $imp<$u>>::Output { 86 | $imp::$method(self, *other) 87 | } 88 | } 89 | 90 | #[$attr] 91 | impl<'a, 'b> $imp<&'a $u> for &'b $t { 92 | type Output = <$t as $imp<$u>>::Output; 93 | 94 | #[inline] 95 | fn $method(self, other: &'a $u) -> <$t as $imp<$u>>::Output { 96 | $imp::$method(*self, *other) 97 | } 98 | } 99 | } 100 | } 101 | -------------------------------------------------------------------------------- /libcore/iter/iterator.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2013-2016 The Rust Project Developers. See the COPYRIGHT 2 | // file at the top-level directory of this distribution and at 3 | // http://rust-lang.org/COPYRIGHT. 4 | // 5 | // Licensed under the Apache License, Version 2.0 or the MIT license 7 | // , at your 8 | // option. This file may not be copied, modified, or distributed 9 | // except according to those terms. 10 | 11 | use option::Option; 12 | 13 | /// An interface for dealing with iterators. 14 | /// 15 | /// This is the main iterator trait. For more about the concept of iterators 16 | /// generally, please see the [module-level documentation]. In particular, you 17 | /// may want to know how to [implement `Iterator`][impl]. 18 | /// 19 | /// [module-level documentation]: index.html 20 | /// [impl]: index.html#implementing-iterator 21 | #[rustc_on_unimplemented = "`{Self}` is not an iterator; maybe try calling \ 22 | `.iter()` or a similar method"] 23 | pub trait Iterator { 24 | /// The type of the elements being iterated over. 25 | type Item; 26 | 27 | /// Advances the iterator and returns the next value. 28 | /// 29 | /// Returns `None` when iteration is finished. Individual iterator 30 | /// implementations may choose to resume iteration, and so calling `next()` 31 | /// again may or may not eventually start returning `Some(Item)` again at some 32 | /// point. 33 | /// 34 | /// # Examples 35 | /// 36 | /// Basic usage: 37 | /// 38 | /// ``` 39 | /// let a = [1, 2, 3]; 40 | /// 41 | /// let mut iter = a.iter(); 42 | /// 43 | /// // A call to next() returns the next value... 44 | /// assert_eq!(Some(&1), iter.next()); 45 | /// assert_eq!(Some(&2), iter.next()); 46 | /// assert_eq!(Some(&3), iter.next()); 47 | /// 48 | /// // ... and then None once it's over. 49 | /// assert_eq!(None, iter.next()); 50 | /// 51 | /// // More calls may or may not return None. Here, they always will. 52 | /// assert_eq!(None, iter.next()); 53 | /// assert_eq!(None, iter.next()); 54 | /// ``` 55 | fn next(&mut self) -> Option; 56 | 57 | /// Returns the bounds on the remaining length of the iterator. 58 | /// 59 | /// Specifically, `size_hint()` returns a tuple where the first element 60 | /// is the lower bound, and the second element is the upper bound. 61 | /// 62 | /// The second half of the tuple that is returned is an `Option`. A 63 | /// `None` here means that either there is no known upper bound, or the 64 | /// upper bound is larger than `usize`. 65 | /// 66 | /// # Implementation notes 67 | /// 68 | /// It is not enforced that an iterator implementation yields the declared 69 | /// number of elements. A buggy iterator may yield less than the lower bound 70 | /// or more than the upper bound of elements. 71 | /// 72 | /// `size_hint()` is primarily intended to be used for optimizations such as 73 | /// reserving space for the elements of the iterator, but must not be 74 | /// trusted to e.g. omit bounds checks in unsafe code. An incorrect 75 | /// implementation of `size_hint()` should not lead to memory safety 76 | /// violations. 77 | /// 78 | /// That said, the implementation should provide a correct estimation, 79 | /// because otherwise it would be a violation of the trait's protocol. 80 | /// 81 | /// The default implementation returns `(0, None)` which is correct for any 82 | /// iterator. 83 | /// 84 | /// # Examples 85 | /// 86 | /// Basic usage: 87 | /// 88 | /// ``` 89 | /// let a = [1, 2, 3]; 90 | /// let iter = a.iter(); 91 | /// 92 | /// assert_eq!((3, Some(3)), iter.size_hint()); 93 | /// ``` 94 | /// 95 | /// A more complex example: 96 | /// 97 | /// ``` 98 | /// // The even numbers from zero to ten. 99 | /// let iter = (0..10).filter(|x| x % 2 == 0); 100 | /// 101 | /// // We might iterate from zero to ten times. Knowing that it's five 102 | /// // exactly wouldn't be possible without executing filter(). 103 | /// assert_eq!((0, Some(10)), iter.size_hint()); 104 | /// 105 | /// // Let's add one five more numbers with chain() 106 | /// let iter = (0..10).filter(|x| x % 2 == 0).chain(15..20); 107 | /// 108 | /// // now both bounds are increased by five 109 | /// assert_eq!((5, Some(15)), iter.size_hint()); 110 | /// ``` 111 | /// 112 | /// Returning `None` for an upper bound: 113 | /// 114 | /// ``` 115 | /// // an infinite iterator has no upper bound 116 | /// let iter = 0..; 117 | /// 118 | /// assert_eq!((0, None), iter.size_hint()); 119 | /// ``` 120 | #[inline] 121 | fn size_hint(&self) -> (usize, Option) { (0, None) } 122 | } 123 | -------------------------------------------------------------------------------- /libcore/iter/mod.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2013-2016 The Rust Project Developers. See the COPYRIGHT 2 | // file at the top-level directory of this distribution and at 3 | // http://rust-lang.org/COPYRIGHT. 4 | // 5 | // Licensed under the Apache License, Version 2.0 or the MIT license 7 | // , at your 8 | // option. This file may not be copied, modified, or distributed 9 | // except according to those terms. 10 | 11 | mod iterator; 12 | mod range; 13 | mod traits; 14 | 15 | pub use self::iterator::Iterator; 16 | pub use self::traits::IntoIterator; 17 | -------------------------------------------------------------------------------- /libcore/iter/range.rs: -------------------------------------------------------------------------------- 1 | 2 | use ops::{self, Add}; 3 | 4 | // TODO 5 | impl Iterator for ops::Range { 6 | type Item = usize; 7 | 8 | #[inline] 9 | fn next(&mut self) -> Option { 10 | if self.start < self.end { 11 | let new = self.start + 1; 12 | let prev = self.start; 13 | self.start = new; 14 | Some(prev) 15 | } else { 16 | None 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /libcore/iter/traits.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2013-2016 The Rust Project Developers. See the COPYRIGHT 2 | // file at the top-level directory of this distribution and at 3 | // http://rust-lang.org/COPYRIGHT. 4 | // 5 | // Licensed under the Apache License, Version 2.0 or the MIT license 7 | // , at your 8 | // option. This file may not be copied, modified, or distributed 9 | // except according to those terms. 10 | 11 | use marker::Sized; 12 | use iter::Iterator; 13 | 14 | /// Conversion from an `Iterator`. 15 | /// 16 | /// By implementing `FromIterator` for a type, you define how it will be 17 | /// created from an iterator. This is common for types which describe a 18 | /// collection of some kind. 19 | /// 20 | /// `FromIterator`'s [`from_iter()`] is rarely called explicitly, and is instead 21 | /// used through [`Iterator`]'s [`collect()`] method. See [`collect()`]'s 22 | /// documentation for more examples. 23 | /// 24 | /// [`from_iter()`]: #tymethod.from_iter 25 | /// [`Iterator`]: trait.Iterator.html 26 | /// [`collect()`]: trait.Iterator.html#method.collect 27 | /// 28 | /// See also: [`IntoIterator`]. 29 | /// 30 | /// [`IntoIterator`]: trait.IntoIterator.html 31 | /// 32 | /// # Examples 33 | /// 34 | /// Basic usage: 35 | /// 36 | /// ``` 37 | /// use std::iter::FromIterator; 38 | /// 39 | /// let five_fives = std::iter::repeat(5).take(5); 40 | /// 41 | /// let v = Vec::from_iter(five_fives); 42 | /// 43 | /// assert_eq!(v, vec![5, 5, 5, 5, 5]); 44 | /// ``` 45 | /// 46 | /// Using [`collect()`] to implicitly use `FromIterator`: 47 | /// 48 | /// ``` 49 | /// let five_fives = std::iter::repeat(5).take(5); 50 | /// 51 | /// let v: Vec = five_fives.collect(); 52 | /// 53 | /// assert_eq!(v, vec![5, 5, 5, 5, 5]); 54 | /// ``` 55 | /// 56 | /// Implementing `FromIterator` for your type: 57 | /// 58 | /// ``` 59 | /// use std::iter::FromIterator; 60 | /// 61 | /// // A sample collection, that's just a wrapper over Vec 62 | /// #[derive(Debug)] 63 | /// struct MyCollection(Vec); 64 | /// 65 | /// // Let's give it some methods so we can create one and add things 66 | /// // to it. 67 | /// impl MyCollection { 68 | /// fn new() -> MyCollection { 69 | /// MyCollection(Vec::new()) 70 | /// } 71 | /// 72 | /// fn add(&mut self, elem: i32) { 73 | /// self.0.push(elem); 74 | /// } 75 | /// } 76 | /// 77 | /// // and we'll implement FromIterator 78 | /// impl FromIterator for MyCollection { 79 | /// fn from_iter>(iter: I) -> Self { 80 | /// let mut c = MyCollection::new(); 81 | /// 82 | /// for i in iter { 83 | /// c.add(i); 84 | /// } 85 | /// 86 | /// c 87 | /// } 88 | /// } 89 | /// 90 | /// // Now we can make a new iterator... 91 | /// let iter = (0..5).into_iter(); 92 | /// 93 | /// // ... and make a MyCollection out of it 94 | /// let c = MyCollection::from_iter(iter); 95 | /// 96 | /// assert_eq!(c.0, vec![0, 1, 2, 3, 4]); 97 | /// 98 | /// // collect works too! 99 | /// 100 | /// let iter = (0..5).into_iter(); 101 | /// let c: MyCollection = iter.collect(); 102 | /// 103 | /// assert_eq!(c.0, vec![0, 1, 2, 3, 4]); 104 | /// ``` 105 | #[rustc_on_unimplemented="a collection of type `{Self}` cannot be \ 106 | built from an iterator over elements of type `{A}`"] 107 | pub trait FromIterator: Sized { 108 | /// Creates a value from an iterator. 109 | /// 110 | /// See the [module-level documentation] for more. 111 | /// 112 | /// [module-level documentation]: trait.FromIterator.html 113 | /// 114 | /// # Examples 115 | /// 116 | /// Basic usage: 117 | /// 118 | /// ``` 119 | /// use std::iter::FromIterator; 120 | /// 121 | /// let five_fives = std::iter::repeat(5).take(5); 122 | /// 123 | /// let v = Vec::from_iter(five_fives); 124 | /// 125 | /// assert_eq!(v, vec![5, 5, 5, 5, 5]); 126 | /// ``` 127 | fn from_iter>(iter: T) -> Self; 128 | } 129 | 130 | /// Conversion into an `Iterator`. 131 | /// 132 | /// By implementing `IntoIterator` for a type, you define how it will be 133 | /// converted to an iterator. This is common for types which describe a 134 | /// collection of some kind. 135 | /// 136 | /// One benefit of implementing `IntoIterator` is that your type will [work 137 | /// with Rust's `for` loop syntax](index.html#for-loops-and-intoiterator). 138 | /// 139 | /// See also: [`FromIterator`]. 140 | /// 141 | /// [`FromIterator`]: trait.FromIterator.html 142 | /// 143 | /// # Examples 144 | /// 145 | /// Basic usage: 146 | /// 147 | /// ``` 148 | /// let v = vec![1, 2, 3]; 149 | /// 150 | /// let mut iter = v.into_iter(); 151 | /// 152 | /// let n = iter.next(); 153 | /// assert_eq!(Some(1), n); 154 | /// 155 | /// let n = iter.next(); 156 | /// assert_eq!(Some(2), n); 157 | /// 158 | /// let n = iter.next(); 159 | /// assert_eq!(Some(3), n); 160 | /// 161 | /// let n = iter.next(); 162 | /// assert_eq!(None, n); 163 | /// ``` 164 | /// 165 | /// Implementing `IntoIterator` for your type: 166 | /// 167 | /// ``` 168 | /// // A sample collection, that's just a wrapper over Vec 169 | /// #[derive(Debug)] 170 | /// struct MyCollection(Vec); 171 | /// 172 | /// // Let's give it some methods so we can create one and add things 173 | /// // to it. 174 | /// impl MyCollection { 175 | /// fn new() -> MyCollection { 176 | /// MyCollection(Vec::new()) 177 | /// } 178 | /// 179 | /// fn add(&mut self, elem: i32) { 180 | /// self.0.push(elem); 181 | /// } 182 | /// } 183 | /// 184 | /// // and we'll implement IntoIterator 185 | /// impl IntoIterator for MyCollection { 186 | /// type Item = i32; 187 | /// type IntoIter = ::std::vec::IntoIter; 188 | /// 189 | /// fn into_iter(self) -> Self::IntoIter { 190 | /// self.0.into_iter() 191 | /// } 192 | /// } 193 | /// 194 | /// // Now we can make a new collection... 195 | /// let mut c = MyCollection::new(); 196 | /// 197 | /// // ... add some stuff to it ... 198 | /// c.add(0); 199 | /// c.add(1); 200 | /// c.add(2); 201 | /// 202 | /// // ... and then turn it into an Iterator: 203 | /// for (i, n) in c.into_iter().enumerate() { 204 | /// assert_eq!(i as i32, n); 205 | /// } 206 | /// ``` 207 | pub trait IntoIterator { 208 | /// The type of the elements being iterated over. 209 | type Item; 210 | 211 | /// Which kind of iterator are we turning this into? 212 | type IntoIter: Iterator; 213 | 214 | /// Creates an iterator from a value. 215 | /// 216 | /// See the [module-level documentation] for more. 217 | /// 218 | /// [module-level documentation]: trait.IntoIterator.html 219 | /// 220 | /// # Examples 221 | /// 222 | /// Basic usage: 223 | /// 224 | /// ``` 225 | /// let v = vec![1, 2, 3]; 226 | /// 227 | /// let mut iter = v.into_iter(); 228 | /// 229 | /// let n = iter.next(); 230 | /// assert_eq!(Some(1), n); 231 | /// 232 | /// let n = iter.next(); 233 | /// assert_eq!(Some(2), n); 234 | /// 235 | /// let n = iter.next(); 236 | /// assert_eq!(Some(3), n); 237 | /// 238 | /// let n = iter.next(); 239 | /// assert_eq!(None, n); 240 | /// ``` 241 | fn into_iter(self) -> Self::IntoIter; 242 | } 243 | 244 | impl IntoIterator for I { 245 | type Item = I::Item; 246 | type IntoIter = I; 247 | 248 | fn into_iter(self) -> I { 249 | self 250 | } 251 | } 252 | -------------------------------------------------------------------------------- /libcore/lib.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2014 The Rust Project Developers. See the COPYRIGHT 2 | // file at the top-level directory of this distribution and at 3 | // http://rust-lang.org/COPYRIGHT. 4 | // 5 | // Licensed under the Apache License, Version 2.0 or the MIT license 7 | // , at your 8 | // option. This file may not be copied, modified, or distributed 9 | // except according to those terms. 10 | 11 | //! # The Rust Core Library (inspirv) 12 | 13 | #![crate_name = "core"] 14 | #![crate_type = "rlib"] 15 | 16 | #![feature(fundamental, no_core, lang_items, custom_attribute, attr_literals, optin_builtin_traits)] 17 | #![feature(unboxed_closures)] 18 | #![feature(allow_internal_unstable)] 19 | #![feature(on_unimplemented)] 20 | #![feature(prelude_import)] 21 | #![feature(specialization)] 22 | #![feature(associated_type_defaults)] 23 | #![feature(never_type)] 24 | 25 | #![allow(dead_code)] 26 | #![allow(unused_attributes)] 27 | #![no_core] 28 | 29 | #[prelude_import] 30 | use prelude::v1::*; 31 | 32 | #[macro_use] 33 | mod internal_macros; 34 | 35 | #[macro_use] 36 | mod macros; 37 | 38 | #[path = "num/f32.rs"] pub mod f32; 39 | #[path = "num/f64.rs"] pub mod f64; 40 | 41 | pub mod prelude; 42 | 43 | pub mod clone; 44 | pub mod cmp; 45 | pub mod default; 46 | pub mod iter; 47 | pub mod marker; 48 | pub mod ops; 49 | pub mod option; 50 | 51 | #[lang = "eh_personality"] pub extern fn eh_personality() {} 52 | -------------------------------------------------------------------------------- /libcore/macros.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2014 The Rust Project Developers. See the COPYRIGHT 2 | // file at the top-level directory of this distribution and at 3 | // http://rust-lang.org/COPYRIGHT. 4 | // 5 | // Licensed under the Apache License, Version 2.0 or the MIT license 7 | // , at your 8 | // option. This file may not be copied, modified, or distributed 9 | // except according to those terms. 10 | 11 | /// Entry point of thread panic, for details, see std::macros 12 | #[macro_export] 13 | #[allow_internal_unstable] 14 | #[cfg(not(target_arch = "spirv"))] 15 | macro_rules! panic { 16 | () => ( 17 | panic!("explicit panic") 18 | ); 19 | ($msg:expr) => ({ 20 | static _MSG_FILE_LINE: (&'static str, &'static str, u32) = ($msg, file!(), line!()); 21 | $crate::panicking::panic(&_MSG_FILE_LINE) 22 | }); 23 | ($fmt:expr, $($arg:tt)*) => ({ 24 | // The leading _'s are to avoid dead code warnings if this is 25 | // used inside a dead function. Just `#[allow(dead_code)]` is 26 | // insufficient, since the user may have 27 | // `#[forbid(dead_code)]` and which cannot be overridden. 28 | static _FILE_LINE: (&'static str, u32) = (file!(), line!()); 29 | $crate::panicking::panic_fmt(format_args!($fmt, $($arg)*), &_FILE_LINE) 30 | }); 31 | } 32 | 33 | #[macro_export] 34 | #[allow_internal_unstable] 35 | #[cfg(target_arch = "spirv")] 36 | macro_rules! panic { 37 | () => ( 38 | loop { } 39 | ); 40 | ($msg:expr) => ({ 41 | loop { } 42 | }); 43 | ($fmt:expr, $($arg:tt)*) => ({ 44 | loop { } 45 | }); 46 | } 47 | 48 | /// Ensure that a boolean expression is `true` at runtime. 49 | /// 50 | /// This will invoke the `panic!` macro if the provided expression cannot be 51 | /// evaluated to `true` at runtime. 52 | /// 53 | /// Assertions are always checked in both debug and release builds, and cannot 54 | /// be disabled. See `debug_assert!` for assertions that are not enabled in 55 | /// release builds by default. 56 | /// 57 | /// Unsafe code relies on `assert!` to enforce run-time invariants that, if 58 | /// violated could lead to unsafety. 59 | /// 60 | /// Other use-cases of `assert!` include 61 | /// [testing](https://doc.rust-lang.org/book/testing.html) and enforcing 62 | /// run-time invariants in safe code (whose violation cannot result in unsafety). 63 | /// 64 | /// This macro has a second version, where a custom panic message can be provided. 65 | /// 66 | /// # Examples 67 | /// 68 | /// ``` 69 | /// // the panic message for these assertions is the stringified value of the 70 | /// // expression given. 71 | /// assert!(true); 72 | /// 73 | /// fn some_computation() -> bool { true } // a very simple function 74 | /// 75 | /// assert!(some_computation()); 76 | /// 77 | /// // assert with a custom message 78 | /// let x = true; 79 | /// assert!(x, "x wasn't true!"); 80 | /// 81 | /// let a = 3; let b = 27; 82 | /// assert!(a + b == 30, "a = {}, b = {}", a, b); 83 | /// ``` 84 | #[macro_export] 85 | macro_rules! assert { 86 | ($cond:expr) => ( 87 | if !$cond { 88 | panic!(concat!("assertion failed: ", stringify!($cond))) 89 | } 90 | ); 91 | ($cond:expr, $($arg:tt)+) => ( 92 | if !$cond { 93 | panic!($($arg)+) 94 | } 95 | ); 96 | } 97 | 98 | /// A utility macro for indicating unreachable code. 99 | /// 100 | /// This is useful any time that the compiler can't determine that some code is unreachable. For 101 | /// example: 102 | /// 103 | /// * Match arms with guard conditions. 104 | /// * Loops that dynamically terminate. 105 | /// * Iterators that dynamically terminate. 106 | /// 107 | /// # Panics 108 | /// 109 | /// This will always panic. 110 | /// 111 | /// # Examples 112 | /// 113 | /// Match arms: 114 | /// 115 | /// ``` 116 | /// # #[allow(dead_code)] 117 | /// fn foo(x: Option) { 118 | /// match x { 119 | /// Some(n) if n >= 0 => println!("Some(Non-negative)"), 120 | /// Some(n) if n < 0 => println!("Some(Negative)"), 121 | /// Some(_) => unreachable!(), // compile error if commented out 122 | /// None => println!("None") 123 | /// } 124 | /// } 125 | /// ``` 126 | /// 127 | /// Iterators: 128 | /// 129 | /// ``` 130 | /// # #[allow(dead_code)] 131 | /// fn divide_by_three(x: u32) -> u32 { // one of the poorest implementations of x/3 132 | /// for i in 0.. { 133 | /// if 3*i < i { panic!("u32 overflow"); } 134 | /// if x < 3*i { return i-1; } 135 | /// } 136 | /// unreachable!(); 137 | /// } 138 | /// ``` 139 | #[macro_export] 140 | macro_rules! unreachable { 141 | () => ({ 142 | panic!("internal error: entered unreachable code") 143 | }); 144 | ($msg:expr) => ({ 145 | unreachable!("{}", $msg) 146 | }); 147 | ($fmt:expr, $($arg:tt)*) => ({ 148 | panic!(concat!("internal error: entered unreachable code: ", $fmt), $($arg)*) 149 | }); 150 | } 151 | 152 | /// A standardized placeholder for marking unfinished code. It panics with the 153 | /// message `"not yet implemented"` when executed. 154 | /// 155 | /// This can be useful if you are prototyping and are just looking to have your 156 | /// code typecheck, or if you're implementing a trait that requires multiple 157 | /// methods, and you're only planning on using one of them. 158 | /// 159 | /// # Examples 160 | /// 161 | /// Here's an example of some in-progress code. We have a trait `Foo`: 162 | /// 163 | /// ``` 164 | /// trait Foo { 165 | /// fn bar(&self); 166 | /// fn baz(&self); 167 | /// } 168 | /// ``` 169 | /// 170 | /// We want to implement `Foo` on one of our types, but we also want to work on 171 | /// just `bar()` first. In order for our code to compile, we need to implement 172 | /// `baz()`, so we can use `unimplemented!`: 173 | /// 174 | /// ``` 175 | /// # trait Foo { 176 | /// # fn bar(&self); 177 | /// # fn baz(&self); 178 | /// # } 179 | /// struct MyStruct; 180 | /// 181 | /// impl Foo for MyStruct { 182 | /// fn bar(&self) { 183 | /// // implementation goes here 184 | /// } 185 | /// 186 | /// fn baz(&self) { 187 | /// // let's not worry about implementing baz() for now 188 | /// unimplemented!(); 189 | /// } 190 | /// } 191 | /// 192 | /// fn main() { 193 | /// let s = MyStruct; 194 | /// s.bar(); 195 | /// 196 | /// // we aren't even using baz() yet, so this is fine. 197 | /// } 198 | /// ``` 199 | #[macro_export] 200 | macro_rules! unimplemented { 201 | () => (panic!("not yet implemented")) 202 | } 203 | -------------------------------------------------------------------------------- /libcore/marker.rs: -------------------------------------------------------------------------------- 1 | 2 | use super::clone::Clone; 3 | 4 | #[lang = "sized"] 5 | #[fundamental] 6 | pub trait Sized { } 7 | 8 | #[lang = "copy"] 9 | pub trait Copy { } 10 | 11 | #[lang = "sync"] 12 | pub unsafe trait Sync { 13 | // Empty 14 | } 15 | 16 | unsafe impl Sync for .. { } 17 | impl !Sync for *const T { } 18 | impl !Sync for *mut T { } 19 | -------------------------------------------------------------------------------- /libcore/num/f32.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT 2 | // file at the top-level directory of this distribution and at 3 | // http://rust-lang.org/COPYRIGHT. 4 | // 5 | // Licensed under the Apache License, Version 2.0 or the MIT license 7 | // , at your 8 | // option. This file may not be copied, modified, or distributed 9 | // except according to those terms. 10 | 11 | //! Operations and constants for 32-bits floats (`f32` type) 12 | 13 | #![allow(overflowing_literals)] 14 | 15 | /// The radix or base of the internal representation of `f32`. 16 | pub const RADIX: u32 = 2; 17 | 18 | /// Number of significant digits in base 2. 19 | pub const MANTISSA_DIGITS: u32 = 24; 20 | /// Approximate number of significant digits in base 10. 21 | pub const DIGITS: u32 = 6; 22 | 23 | /// Difference between `1.0` and the next largest representable number. 24 | pub const EPSILON: f32 = 1.19209290e-07_f32; 25 | 26 | /// Smallest finite `f32` value. 27 | pub const MIN: f32 = -3.40282347e+38_f32; 28 | /// Smallest positive normal `f32` value. 29 | pub const MIN_POSITIVE: f32 = 1.17549435e-38_f32; 30 | /// Largest finite `f32` value. 31 | pub const MAX: f32 = 3.40282347e+38_f32; 32 | 33 | /// One greater than the minimum possible normal power of 2 exponent. 34 | pub const MIN_EXP: i32 = -125; 35 | /// Maximum possible power of 2 exponent. 36 | pub const MAX_EXP: i32 = 128; 37 | 38 | /// Minimum possible normal power of 10 exponent. 39 | pub const MIN_10_EXP: i32 = -37; 40 | /// Maximum possible power of 10 exponent. 41 | pub const MAX_10_EXP: i32 = 38; 42 | 43 | /// Not a Number (NaN). 44 | pub const NAN: f32 = 0.0_f32 / 0.0_f32; 45 | /// Infinity (∞). 46 | pub const INFINITY: f32 = 1.0_f32 / 0.0_f32; 47 | /// Negative infinity (-∞). 48 | pub const NEG_INFINITY: f32 = -1.0_f32 / 0.0_f32; 49 | 50 | /// Basic mathematical constants. 51 | pub mod consts { 52 | // FIXME: replace with mathematical constants from cmath. 53 | 54 | /// Archimedes' constant (π) 55 | pub const PI: f32 = 3.14159265358979323846264338327950288_f32; 56 | 57 | /// π/2 58 | pub const FRAC_PI_2: f32 = 1.57079632679489661923132169163975144_f32; 59 | 60 | /// π/3 61 | pub const FRAC_PI_3: f32 = 1.04719755119659774615421446109316763_f32; 62 | 63 | /// π/4 64 | pub const FRAC_PI_4: f32 = 0.785398163397448309615660845819875721_f32; 65 | 66 | /// π/6 67 | pub const FRAC_PI_6: f32 = 0.52359877559829887307710723054658381_f32; 68 | 69 | /// π/8 70 | pub const FRAC_PI_8: f32 = 0.39269908169872415480783042290993786_f32; 71 | 72 | /// 1/π 73 | pub const FRAC_1_PI: f32 = 0.318309886183790671537767526745028724_f32; 74 | 75 | /// 2/π 76 | pub const FRAC_2_PI: f32 = 0.636619772367581343075535053490057448_f32; 77 | 78 | /// 2/sqrt(π) 79 | pub const FRAC_2_SQRT_PI: f32 = 1.12837916709551257389615890312154517_f32; 80 | 81 | /// sqrt(2) 82 | pub const SQRT_2: f32 = 1.41421356237309504880168872420969808_f32; 83 | 84 | /// 1/sqrt(2) 85 | pub const FRAC_1_SQRT_2: f32 = 0.707106781186547524400844362104849039_f32; 86 | 87 | /// Euler's number (e) 88 | pub const E: f32 = 2.71828182845904523536028747135266250_f32; 89 | 90 | /// log2(e) 91 | pub const LOG2_E: f32 = 1.44269504088896340735992468100189214_f32; 92 | 93 | /// log10(e) 94 | pub const LOG10_E: f32 = 0.434294481903251827651128918916605082_f32; 95 | 96 | /// ln(2) 97 | pub const LN_2: f32 = 0.693147180559945309417232121458176568_f32; 98 | 99 | /// ln(10) 100 | pub const LN_10: f32 = 2.30258509299404568401799145468436421_f32; 101 | } 102 | -------------------------------------------------------------------------------- /libcore/num/f64.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT 2 | // file at the top-level directory of this distribution and at 3 | // http://rust-lang.org/COPYRIGHT. 4 | // 5 | // Licensed under the Apache License, Version 2.0 or the MIT license 7 | // , at your 8 | // option. This file may not be copied, modified, or distributed 9 | // except according to those terms. 10 | 11 | //! Operations and constants for 64-bits floats (`f64` type) 12 | 13 | #![allow(overflowing_literals)] 14 | 15 | /// The radix or base of the internal representation of `f64`. 16 | pub const RADIX: u32 = 2; 17 | 18 | /// Number of significant digits in base 2. 19 | pub const MANTISSA_DIGITS: u32 = 53; 20 | /// Approximate number of significant digits in base 10. 21 | pub const DIGITS: u32 = 15; 22 | 23 | /// Difference between `1.0` and the next largest representable number. 24 | pub const EPSILON: f64 = 2.2204460492503131e-16_f64; 25 | 26 | /// Smallest finite `f64` value. 27 | pub const MIN: f64 = -1.7976931348623157e+308_f64; 28 | /// Smallest positive normal `f64` value. 29 | pub const MIN_POSITIVE: f64 = 2.2250738585072014e-308_f64; 30 | /// Largest finite `f64` value. 31 | pub const MAX: f64 = 1.7976931348623157e+308_f64; 32 | 33 | /// One greater than the minimum possible normal power of 2 exponent. 34 | pub const MIN_EXP: i32 = -1021; 35 | /// Maximum possible power of 2 exponent. 36 | pub const MAX_EXP: i32 = 1024; 37 | 38 | /// Minimum possible normal power of 10 exponent. 39 | pub const MIN_10_EXP: i32 = -307; 40 | /// Maximum possible power of 10 exponent. 41 | pub const MAX_10_EXP: i32 = 308; 42 | 43 | /// Not a Number (NaN). 44 | pub const NAN: f64 = 0.0_f64 / 0.0_f64; 45 | /// Infinity (∞). 46 | pub const INFINITY: f64 = 1.0_f64 / 0.0_f64; 47 | /// Negative infinity (-∞). 48 | pub const NEG_INFINITY: f64 = -1.0_f64 / 0.0_f64; 49 | 50 | /// Basic mathematical constants. 51 | pub mod consts { 52 | // FIXME: replace with mathematical constants from cmath. 53 | 54 | /// Archimedes' constant (π) 55 | pub const PI: f64 = 3.14159265358979323846264338327950288_f64; 56 | 57 | /// π/2 58 | pub const FRAC_PI_2: f64 = 1.57079632679489661923132169163975144_f64; 59 | 60 | /// π/3 61 | pub const FRAC_PI_3: f64 = 1.04719755119659774615421446109316763_f64; 62 | 63 | /// π/4 64 | pub const FRAC_PI_4: f64 = 0.785398163397448309615660845819875721_f64; 65 | 66 | /// π/6 67 | pub const FRAC_PI_6: f64 = 0.52359877559829887307710723054658381_f64; 68 | 69 | /// π/8 70 | pub const FRAC_PI_8: f64 = 0.39269908169872415480783042290993786_f64; 71 | 72 | /// 1/π 73 | pub const FRAC_1_PI: f64 = 0.318309886183790671537767526745028724_f64; 74 | 75 | /// 2/π 76 | pub const FRAC_2_PI: f64 = 0.636619772367581343075535053490057448_f64; 77 | 78 | /// 2/sqrt(π) 79 | pub const FRAC_2_SQRT_PI: f64 = 1.12837916709551257389615890312154517_f64; 80 | 81 | /// sqrt(2) 82 | pub const SQRT_2: f64 = 1.41421356237309504880168872420969808_f64; 83 | 84 | /// 1/sqrt(2) 85 | pub const FRAC_1_SQRT_2: f64 = 0.707106781186547524400844362104849039_f64; 86 | 87 | /// Euler's number (e) 88 | pub const E: f64 = 2.71828182845904523536028747135266250_f64; 89 | 90 | /// log2(e) 91 | pub const LOG2_E: f64 = 1.44269504088896340735992468100189214_f64; 92 | 93 | /// log10(e) 94 | pub const LOG10_E: f64 = 0.434294481903251827651128918916605082_f64; 95 | 96 | /// ln(2) 97 | pub const LN_2: f64 = 0.693147180559945309417232121458176568_f64; 98 | 99 | /// ln(10) 100 | pub const LN_10: f64 = 2.30258509299404568401799145468436421_f64; 101 | } 102 | -------------------------------------------------------------------------------- /libcore/option.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT 2 | // file at the top-level directory of this distribution and at 3 | // http://rust-lang.org/COPYRIGHT. 4 | // 5 | // Licensed under the Apache License, Version 2.0 or the MIT license 7 | // , at your 8 | // option. This file may not be copied, modified, or distributed 9 | // except according to those terms. 10 | 11 | //! Optional values. 12 | //! 13 | //! Type [`Option`] represents an optional value: every [`Option`] 14 | //! is either [`Some`] and contains a value, or [`None`], and 15 | //! does not. [`Option`] types are very common in Rust code, as 16 | //! they have a number of uses: 17 | //! 18 | //! * Initial values 19 | //! * Return values for functions that are not defined 20 | //! over their entire input range (partial functions) 21 | //! * Return value for otherwise reporting simple errors, where `None` is 22 | //! returned on error 23 | //! * Optional struct fields 24 | //! * Struct fields that can be loaned or "taken" 25 | //! * Optional function arguments 26 | //! * Nullable pointers 27 | //! * Swapping things out of difficult situations 28 | //! 29 | //! [`Option`]s are commonly paired with pattern matching to query the presence 30 | //! of a value and take action, always accounting for the [`None`] case. 31 | //! 32 | //! ``` 33 | //! fn divide(numerator: f64, denominator: f64) -> Option { 34 | //! if denominator == 0.0 { 35 | //! None 36 | //! } else { 37 | //! Some(numerator / denominator) 38 | //! } 39 | //! } 40 | //! 41 | //! // The return value of the function is an option 42 | //! let result = divide(2.0, 3.0); 43 | //! 44 | //! // Pattern match to retrieve the value 45 | //! match result { 46 | //! // The division was valid 47 | //! Some(x) => println!("Result: {}", x), 48 | //! // The division was invalid 49 | //! None => println!("Cannot divide by 0"), 50 | //! } 51 | //! ``` 52 | //! 53 | // 54 | // FIXME: Show how `Option` is used in practice, with lots of methods 55 | // 56 | //! # Options and pointers ("nullable" pointers) 57 | //! 58 | //! Rust's pointer types must always point to a valid location; there are 59 | //! no "null" pointers. Instead, Rust has *optional* pointers, like 60 | //! the optional owned box, [`Option`]`<`[`Box`]`>`. 61 | //! 62 | //! The following example uses [`Option`] to create an optional box of 63 | //! [`i32`]. Notice that in order to use the inner [`i32`] value first the 64 | //! `check_optional` function needs to use pattern matching to 65 | //! determine whether the box has a value (i.e. it is [`Some(...)`][`Some`]) or 66 | //! not ([`None`]). 67 | //! 68 | //! ``` 69 | //! let optional: Option> = None; 70 | //! check_optional(&optional); 71 | //! 72 | //! let optional: Option> = Some(Box::new(9000)); 73 | //! check_optional(&optional); 74 | //! 75 | //! fn check_optional(optional: &Option>) { 76 | //! match *optional { 77 | //! Some(ref p) => println!("have value {}", p), 78 | //! None => println!("have no value"), 79 | //! } 80 | //! } 81 | //! ``` 82 | //! 83 | //! This usage of [`Option`] to create safe nullable pointers is so 84 | //! common that Rust does special optimizations to make the 85 | //! representation of [`Option`]`<`[`Box`]`>` a single pointer. Optional pointers 86 | //! in Rust are stored as efficiently as any other pointer type. 87 | //! 88 | //! # Examples 89 | //! 90 | //! Basic pattern matching on [`Option`]: 91 | //! 92 | //! ``` 93 | //! let msg = Some("howdy"); 94 | //! 95 | //! // Take a reference to the contained string 96 | //! if let Some(ref m) = msg { 97 | //! println!("{}", *m); 98 | //! } 99 | //! 100 | //! // Remove the contained string, destroying the Option 101 | //! let unwrapped_msg = msg.unwrap_or("default message"); 102 | //! ``` 103 | //! 104 | //! Initialize a result to [`None`] before a loop: 105 | //! 106 | //! ``` 107 | //! enum Kingdom { Plant(u32, &'static str), Animal(u32, &'static str) } 108 | //! 109 | //! // A list of data to search through. 110 | //! let all_the_big_things = [ 111 | //! Kingdom::Plant(250, "redwood"), 112 | //! Kingdom::Plant(230, "noble fir"), 113 | //! Kingdom::Plant(229, "sugar pine"), 114 | //! Kingdom::Animal(25, "blue whale"), 115 | //! Kingdom::Animal(19, "fin whale"), 116 | //! Kingdom::Animal(15, "north pacific right whale"), 117 | //! ]; 118 | //! 119 | //! // We're going to search for the name of the biggest animal, 120 | //! // but to start with we've just got `None`. 121 | //! let mut name_of_biggest_animal = None; 122 | //! let mut size_of_biggest_animal = 0; 123 | //! for big_thing in &all_the_big_things { 124 | //! match *big_thing { 125 | //! Kingdom::Animal(size, name) if size > size_of_biggest_animal => { 126 | //! // Now we've found the name of some big animal 127 | //! size_of_biggest_animal = size; 128 | //! name_of_biggest_animal = Some(name); 129 | //! } 130 | //! Kingdom::Animal(..) | Kingdom::Plant(..) => () 131 | //! } 132 | //! } 133 | //! 134 | //! match name_of_biggest_animal { 135 | //! Some(name) => println!("the biggest animal is {}", name), 136 | //! None => println!("there are no animals :("), 137 | //! } 138 | //! ``` 139 | //! 140 | //! [`Option`]: enum.Option.html 141 | //! [`Some`]: enum.Option.html#variant.Some 142 | //! [`None`]: enum.Option.html#variant.None 143 | //! [`i32`]: ../../std/primitive.i32.html 144 | 145 | 146 | // Note that this is not a lang item per se, but it has a hidden dependency on 147 | // `Iterator`, which is one. The compiler assumes that the `next` method of 148 | // `Iterator` is an enumeration with one type parameter and two variants, 149 | // which basically means it must be `Option`. 150 | 151 | /// The `Option` type. See [the module level documentation](index.html) for more. 152 | #[inspirv(option)] 153 | pub enum Option { 154 | /// No value 155 | None, 156 | /// Some value `T` 157 | Some(T), 158 | } 159 | -------------------------------------------------------------------------------- /libcore/prelude/mod.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2015 The Rust Project Developers. See the COPYRIGHT 2 | // file at the top-level directory of this distribution and at 3 | // http://rust-lang.org/COPYRIGHT. 4 | // 5 | // Licensed under the Apache License, Version 2.0 or the MIT license 7 | // , at your 8 | // option. This file may not be copied, modified, or distributed 9 | // except according to those terms. 10 | 11 | //! The libcore prelude 12 | 13 | pub mod v1; 14 | -------------------------------------------------------------------------------- /libcore/prelude/v1.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2014 The Rust Project Developers. See the COPYRIGHT 2 | // file at the top-level directory of this distribution and at 3 | // http://rust-lang.org/COPYRIGHT. 4 | // 5 | // Licensed under the Apache License, Version 2.0 or the MIT license 7 | // , at your 8 | // option. This file may not be copied, modified, or distributed 9 | // except according to those terms. 10 | 11 | //! The core prelude 12 | //! 13 | //! This module is intended for users of libcore which do not link to libstd as 14 | //! well. This module is imported by default when `#![no_std]` is used in the 15 | //! same manner as the standard library's prelude. 16 | 17 | // Reexported core operators 18 | #[doc(no_inline)] pub use marker::{Copy, Sized, Sync}; 19 | 20 | // Reexported types and traits 21 | #[doc(no_inline)] pub use clone::Clone; 22 | #[doc(no_inline)] pub use cmp::{PartialEq, PartialOrd, Eq, Ord}; 23 | #[doc(no_inline)] pub use default::Default; 24 | #[doc(no_inline)] pub use option::Option::{self, Some, None}; 25 | #[doc(no_inline)] pub use iter::{Iterator, IntoIterator}; -------------------------------------------------------------------------------- /libstd/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "std" 3 | version = "0.1.0" 4 | 5 | [lib] 6 | name = "std" 7 | path = "lib.rs" 8 | 9 | [dependencies] 10 | core = { path = "../libstd" } 11 | -------------------------------------------------------------------------------- /libstd/image.rs: -------------------------------------------------------------------------------- 1 | 2 | enum Dimension { 3 | D1, 4 | D2, 5 | D3, 6 | Cube, 7 | Rect, 8 | Buffer, 9 | } 10 | 11 | enum Format { 12 | Rgba32f, 13 | Rgba16f, 14 | R32f, 15 | Rgba8, 16 | Rgba8Snorm, 17 | Rg32f, 18 | Rg16f, 19 | R11G11B10f, 20 | R16f, 21 | Rgba16, 22 | Rgb10A2, 23 | Rg16, 24 | Rg8, 25 | R16, 26 | R8, 27 | Rgba16Snorm, 28 | Rg16Snorm, 29 | R16Snorm, 30 | R8Snorm, 31 | Rgba32i, 32 | Rgba16i, 33 | Rgba8i, 34 | R32i, 35 | Rg32i, 36 | Rg16i, 37 | Rg8i, 38 | R16i, 39 | R8i, 40 | Rgba32ui, 41 | Rgba16ui, 42 | Rgba8ui, 43 | R32ui, 44 | Rgb10a2ui, 45 | Rg32ui, 46 | Rg16ui, 47 | Rg8ui, 48 | R16ui, 49 | R8ui, 50 | } 51 | 52 | pub struct Image; 53 | -------------------------------------------------------------------------------- /libstd/interface.rs: -------------------------------------------------------------------------------- 1 | 2 | use core::ops::Deref; 3 | 4 | #[inspirv(interface)] 5 | pub struct Attributes(T); 6 | 7 | impl Deref for Attributes { 8 | type Target = T; 9 | 10 | #[inline] 11 | #[inspirv(intrinsic(deref))] 12 | fn deref(&self) -> &Self::Target { 13 | &self.0 14 | } 15 | } 16 | 17 | #[inspirv(const_buffer)] 18 | pub struct Cbuffer(T); 19 | 20 | impl Deref for Cbuffer { 21 | type Target = T; 22 | 23 | #[inline] 24 | #[inspirv(intrinsic(deref))] 25 | fn deref(&self) -> &Self::Target { 26 | &self.0 27 | } 28 | } 29 | 30 | #[inspirv(constants)] 31 | pub struct Constants(T); 32 | 33 | impl Deref for Constants { 34 | type Target = T; 35 | 36 | #[inline] 37 | #[inspirv(intrinsic(deref))] 38 | fn deref(&self) -> &Self::Target { 39 | &self.0 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /libstd/lib.rs: -------------------------------------------------------------------------------- 1 | 2 | #![crate_name = "std"] 3 | #![crate_type = "rlib"] 4 | 5 | #![feature(custom_attribute)] 6 | #![feature(attr_literals)] 7 | #![feature(prelude_import)] 8 | 9 | #![allow(unused_attributes)] 10 | 11 | #![no_std] 12 | extern crate core as __core; 13 | 14 | #[prelude_import] 15 | #[allow(unused)] 16 | use prelude::v1::*; 17 | 18 | pub mod prelude; 19 | 20 | pub use core::clone; 21 | pub use core::cmp; 22 | pub use core::default; 23 | pub use core::iter; 24 | pub use core::marker; 25 | pub use core::ops; 26 | pub use core::option; 27 | 28 | pub use core::f32; 29 | pub use core::f64; 30 | 31 | pub mod interface; 32 | pub mod matrix; 33 | pub mod vector; 34 | 35 | pub use self::interface::*; 36 | pub use self::vector::*; 37 | pub use self::matrix::*; 38 | -------------------------------------------------------------------------------- /libstd/matrix.rs: -------------------------------------------------------------------------------- 1 | 2 | use core::marker::Copy; 3 | use core::ops::{Add, AddAssign, Sub, SubAssign, Mul, MulAssign}; 4 | 5 | use super::{Vector2, Vector3, Vector4}; 6 | 7 | #[derive(Copy)] 8 | #[inspirv(matrix(rows = 2, cols = 2))] 9 | pub struct Matrix2x2 { 10 | pub col0: Vector2, 11 | pub col1: Vector2, 12 | } 13 | 14 | macro_rules! matrix2x2_ops_impl { 15 | ($($t:ty)*) => ($( 16 | impl Add for Matrix2x2<$t> { 17 | type Output = Matrix2x2<$t>; 18 | 19 | #[inspirv(intrinsic(add))] 20 | fn add(self, rhs: Matrix2x2<$t>) -> Self::Output { 21 | Matrix2x2 { 22 | col0: self.col0 + rhs.col0, 23 | col1: self.col1 + rhs.col1, 24 | } 25 | } 26 | } 27 | 28 | impl AddAssign for Matrix2x2<$t> { 29 | #[inline] 30 | fn add_assign(&mut self, rhs: Matrix2x2<$t>) { 31 | *self = *self + rhs; 32 | } 33 | } 34 | 35 | impl Sub for Matrix2x2<$t> { 36 | type Output = Matrix2x2<$t>; 37 | 38 | #[inspirv(intrinsic(add))] 39 | fn sub(self, rhs: Matrix2x2<$t>) -> Self::Output { 40 | Matrix2x2 { 41 | col0: self.col0 - rhs.col0, 42 | col1: self.col1 - rhs.col1, 43 | } 44 | } 45 | } 46 | 47 | impl SubAssign for Matrix2x2<$t> { 48 | #[inline] 49 | fn sub_assign(&mut self, rhs: Matrix2x2<$t>) { 50 | *self = *self - rhs; 51 | } 52 | } 53 | 54 | impl Mul<$t> for Matrix2x2<$t> { 55 | type Output = Matrix2x2<$t>; 56 | 57 | #[inspirv(intrinsic(mul))] 58 | fn mul(self, _rhs: $t) -> Self::Output { loop {} } 59 | } 60 | 61 | impl Mul> for $t { 62 | type Output = Matrix2x2<$t>; 63 | 64 | #[inspirv(intrinsic(mul))] 65 | fn mul(self, _rhs: Matrix2x2<$t>) -> Self::Output { loop {} } 66 | } 67 | 68 | impl Mul> for Matrix2x2<$t> { 69 | type Output = Vector2<$t>; 70 | 71 | #[inspirv(intrinsic(mul))] 72 | fn mul(self, _rhs: Vector2<$t>) -> Self::Output { loop {} } 73 | } 74 | 75 | impl Mul> for Matrix2x2<$t> { 76 | type Output = Matrix2x2<$t>; 77 | 78 | #[inspirv(intrinsic(mul))] 79 | fn mul(self, _rhs: Matrix2x2<$t>) -> Self::Output { loop {} } 80 | } 81 | )*) 82 | } 83 | 84 | matrix2x2_ops_impl! { usize u16 u32 u64 isize i16 i32 i64 f32 f64 } 85 | 86 | pub type Float2x2 = Matrix2x2; 87 | 88 | impl Float2x2 { 89 | #[inspirv(intrinsic(transpose))] 90 | pub fn transpose(self) -> Float2x2 { loop {} } 91 | 92 | #[inspirv(intrinsic(inverse))] 93 | pub fn inverse(self) -> Float2x2 { loop {} } 94 | } 95 | 96 | #[derive(Copy)] 97 | #[inspirv(matrix(rows = 3, cols = 3))] 98 | pub struct Matrix3x3 { 99 | pub col0: Vector3, 100 | pub col1: Vector3, 101 | pub col2: Vector3, 102 | } 103 | 104 | macro_rules! matrix3x3_ops_impl { 105 | ($($t:ty)*) => ($( 106 | impl Add for Matrix3x3<$t> { 107 | type Output = Matrix3x3<$t>; 108 | 109 | #[inspirv(intrinsic(add))] 110 | fn add(self, _rhs: Matrix3x3<$t>) -> Self::Output { loop {} } 111 | } 112 | 113 | impl AddAssign for Matrix3x3<$t> { 114 | #[inline] 115 | fn add_assign(&mut self, rhs: Matrix3x3<$t>) { 116 | *self = *self + rhs; 117 | } 118 | } 119 | 120 | impl Sub for Matrix3x3<$t> { 121 | type Output = Matrix3x3<$t>; 122 | 123 | #[inspirv(intrinsic(add))] 124 | fn sub(self, _rhs: Matrix3x3<$t>) -> Self::Output { loop {} } 125 | } 126 | 127 | impl SubAssign for Matrix3x3<$t> { 128 | #[inline] 129 | fn sub_assign(&mut self, rhs: Matrix3x3<$t>) { 130 | *self = *self - rhs; 131 | } 132 | } 133 | 134 | impl Mul<$t> for Matrix3x3<$t> { 135 | type Output = Matrix3x3<$t>; 136 | 137 | #[inspirv(intrinsic(mul))] 138 | fn mul(self, _rhs: $t) -> Self::Output { loop {} } 139 | } 140 | 141 | impl Mul> for $t { 142 | type Output = Matrix3x3<$t>; 143 | 144 | #[inspirv(intrinsic(mul))] 145 | fn mul(self, _rhs: Matrix3x3<$t>) -> Self::Output { loop {} } 146 | } 147 | 148 | impl Mul> for Matrix3x3<$t> { 149 | type Output = Vector3<$t>; 150 | 151 | #[inspirv(intrinsic(mul))] 152 | fn mul(self, _rhs: Vector3<$t>) -> Self::Output { loop {} } 153 | } 154 | 155 | impl Mul> for Matrix3x3<$t> { 156 | type Output = Matrix3x3<$t>; 157 | 158 | #[inspirv(intrinsic(mul))] 159 | fn mul(self, _rhs: Matrix3x3<$t>) -> Self::Output { loop {} } 160 | } 161 | )*) 162 | } 163 | 164 | matrix3x3_ops_impl! { usize u16 u32 u64 isize i16 i32 i64 f32 f64 } 165 | 166 | pub type Float3x3 = Matrix3x3; 167 | 168 | impl Float3x3 { 169 | #[inspirv(intrinsic(transpose))] 170 | pub fn transpose(self) -> Float3x3 { loop {} } 171 | 172 | #[inspirv(intrinsic(inverse))] 173 | pub fn inverse(self) -> Float3x3 { loop {} } 174 | } 175 | 176 | #[derive(Copy)] 177 | #[inspirv(matrix(rows = 4, cols = 4))] 178 | pub struct Matrix4x4 { 179 | pub col0: Vector4, 180 | pub col1: Vector4, 181 | pub col2: Vector4, 182 | pub col3: Vector4, 183 | } 184 | 185 | macro_rules! matrix4x4_ops_impl { 186 | ($($t:ty)*) => ($( 187 | impl Add for Matrix4x4<$t> { 188 | type Output = Matrix4x4<$t>; 189 | 190 | #[inspirv(intrinsic(add))] 191 | fn add(self, _rhs: Matrix4x4<$t>) -> Self::Output { loop {} } 192 | } 193 | 194 | impl AddAssign for Matrix4x4<$t> { 195 | #[inline] 196 | fn add_assign(&mut self, rhs: Matrix4x4<$t>) { 197 | *self = *self + rhs; 198 | } 199 | } 200 | 201 | impl Sub for Matrix4x4<$t> { 202 | type Output = Matrix4x4<$t>; 203 | 204 | #[inspirv(intrinsic(add))] 205 | fn sub(self, _rhs: Matrix4x4<$t>) -> Self::Output { loop {} } 206 | } 207 | 208 | impl SubAssign for Matrix4x4<$t> { 209 | #[inline] 210 | fn sub_assign(&mut self, rhs: Matrix4x4<$t>) { 211 | *self = *self - rhs; 212 | } 213 | } 214 | 215 | impl Mul<$t> for Matrix4x4<$t> { 216 | type Output = Matrix4x4<$t>; 217 | 218 | #[inspirv(intrinsic(mul))] 219 | fn mul(self, _rhs: $t) -> Self::Output { loop {} } 220 | } 221 | 222 | impl Mul> for $t { 223 | type Output = Matrix4x4<$t>; 224 | 225 | #[inspirv(intrinsic(mul))] 226 | fn mul(self, _rhs: Matrix4x4<$t>) -> Self::Output { loop {} } 227 | } 228 | 229 | impl Mul> for Matrix4x4<$t> { 230 | type Output = Vector4<$t>; 231 | 232 | #[inspirv(intrinsic(mul))] 233 | fn mul(self, _rhs: Vector4<$t>) -> Self::Output { loop {} } 234 | } 235 | 236 | impl Mul> for Matrix4x4<$t> { 237 | type Output = Matrix4x4<$t>; 238 | 239 | #[inspirv(intrinsic(mul))] 240 | fn mul(self, _rhs: Matrix4x4<$t>) -> Self::Output { loop {} } 241 | } 242 | )*) 243 | } 244 | 245 | matrix4x4_ops_impl! { usize u16 u32 u64 isize i16 i32 i64 f32 f64 } 246 | 247 | pub type Float4x4 = Matrix4x4; 248 | 249 | impl Float4x4 { 250 | #[inspirv(intrinsic(transpose))] 251 | pub fn transpose(self) -> Float4x4 { loop {} } 252 | 253 | #[inspirv(intrinsic(inverse))] 254 | pub fn inverse(self) -> Float4x4 { loop {} } 255 | } 256 | -------------------------------------------------------------------------------- /libstd/prelude/mod.rs: -------------------------------------------------------------------------------- 1 | 2 | pub mod v1; 3 | -------------------------------------------------------------------------------- /libstd/prelude/v1.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2013 The Rust Project Developers. See the COPYRIGHT 2 | // file at the top-level directory of this distribution and at 3 | // http://rust-lang.org/COPYRIGHT. 4 | // 5 | // Licensed under the Apache License, Version 2.0 or the MIT license 7 | // , at your 8 | // option. This file may not be copied, modified, or distributed 9 | // except according to those terms. 10 | 11 | //! The first version of the prelude of The Rust Standard Library. 12 | 13 | // Reexported core operators 14 | #[doc(no_inline)] pub use marker::{Copy, Sized, Sync}; 15 | #[doc(no_inline)] pub use ops::{Fn, FnMut, FnOnce}; 16 | 17 | // Reexported types and traits 18 | #[doc(no_inline)] pub use clone::Clone; 19 | #[doc(no_inline)] pub use cmp::{PartialEq, PartialOrd, Eq, Ord}; 20 | #[doc(no_inline)] pub use default::Default; 21 | #[doc(no_inline)] pub use iter::{Iterator, IntoIterator}; 22 | #[doc(no_inline)] pub use option::Option::{self, Some, None}; 23 | #[doc(no_inline)] pub use interface::{Attributes, Cbuffer}; 24 | #[doc(no_inline)] pub use matrix::{Matrix2x2, Matrix3x3, Matrix4x4}; 25 | #[doc(no_inline)] pub use vector::{Vector2, Vector3, Vector4, Float2, Float3, Float4}; 26 | -------------------------------------------------------------------------------- /libstd/vector.rs: -------------------------------------------------------------------------------- 1 | 2 | use core::marker::Copy; 3 | use super::{Matrix2x2, Matrix3x3, Matrix4x4}; 4 | 5 | use core::ops::{Add, AddAssign, Sub, SubAssign, Mul, MulAssign}; 6 | 7 | #[derive(Copy)] 8 | #[inspirv(vector(components = 2))] 9 | pub struct Vector2 { 10 | pub x: T, 11 | pub y: T, 12 | } 13 | 14 | macro_rules! vector2_impl { 15 | ($($t:ty)*) => ($( 16 | impl Vector2<$t> { 17 | #[inspirv(intrinsic(vector_new(1, 1)))] 18 | pub fn new(x: $t, y: $t) -> Vector2<$t> { Vector2 { x: x, y: y } } 19 | 20 | #[inspirv(intrinsic(swizzle(num_in = 2, num_out = 2)))] 21 | pub fn swizzle2(self, idx_x: u32, idx_y: u32) -> Vector2<$t> { 22 | let x = match idx_x { 23 | 0 => self.x, 24 | 1 => self.y, 25 | _ => panic!("Swizzle index x out of range {:?}", idx_x), 26 | }; 27 | let y = match idx_y { 28 | 0 => self.x, 29 | 1 => self.y, 30 | _ => panic!("Swizzle index y out of range {:?}", idx_y), 31 | }; 32 | 33 | Vector2 { x: x, y: y } 34 | } 35 | 36 | #[inspirv(intrinsic(swizzle(num_in = 2, num_out = 3)))] 37 | pub fn swizzle3(self, idx_x: u32, idx_y: u32, idx_z: u32) -> Vector3<$t> { 38 | let x = match idx_x { 39 | 0 => self.x, 40 | 1 => self.y, 41 | _ => panic!("Swizzle index x out of range {:?}", idx_x), 42 | }; 43 | let y = match idx_y { 44 | 0 => self.x, 45 | 1 => self.y, 46 | _ => panic!("Swizzle index y out of range {:?}", idx_y), 47 | }; 48 | let z = match idx_z { 49 | 0 => self.x, 50 | 1 => self.y, 51 | _ => panic!("Swizzle index z out of range {:?}", idx_z), 52 | }; 53 | 54 | Vector3 { x: x, y: y, z: z } 55 | } 56 | 57 | #[inspirv(intrinsic(swizzle(num_in = 2, num_out = 4)))] 58 | pub fn swizzle4(self, idx_x: u32, idx_y: u32, idx_z: u32, idx_w: u32) -> Vector4<$t> { 59 | let x = match idx_x { 60 | 0 => self.x, 61 | 1 => self.y, 62 | _ => panic!("Swizzle index x out of range {:?}", idx_x), 63 | }; 64 | let y = match idx_y { 65 | 0 => self.x, 66 | 1 => self.y, 67 | _ => panic!("Swizzle index y out of range {:?}", idx_y), 68 | }; 69 | let z = match idx_z { 70 | 0 => self.x, 71 | 1 => self.y, 72 | _ => panic!("Swizzle index z out of range {:?}", idx_z), 73 | }; 74 | let w = match idx_w { 75 | 0 => self.x, 76 | 1 => self.y, 77 | _ => panic!("Swizzle index w out of range {:?}", idx_w), 78 | }; 79 | 80 | Vector4 { x: x, y: y, z: z, w: w } 81 | } 82 | 83 | #[inspirv(intrinsic(shuffle(num_in0 = 2, num_in1 = 2, num_out = 2)))] 84 | pub fn shuffle2x2(self, _v2: Vector2<$t>, _idx_x: u32, _idx_y: u32) -> Vector2<$t> { loop {} } 85 | 86 | #[inspirv(intrinsic(shuffle(num_in0 = 2, num_in1 = 3, num_out = 2)))] 87 | pub fn shuffle2x3(self, _v2: Vector3<$t>, _idx_x: u32, _idx_y: u32) -> Vector2<$t> { loop {} } 88 | 89 | #[inspirv(intrinsic(shuffle(num_in0 = 2, num_in1 = 4, num_out = 2)))] 90 | pub fn shuffle2x4(self, _v2: Vector4<$t>, _idx_x: u32, _idx_y: u32) -> Vector2<$t> { loop {} } 91 | 92 | #[inspirv(intrinsic(shuffle(num_in0 = 2, num_in1 = 2, num_out = 3)))] 93 | pub fn shuffle3x2(self, _v2: Vector2<$t>, _idx_x: u32, _idx_y: u32, _idx_z: u32) -> Vector3<$t> { loop {} } 94 | 95 | #[inspirv(intrinsic(shuffle(num_in0 = 2, num_in1 = 3, num_out = 3)))] 96 | pub fn shuffle3x3(self, _v2: Vector3<$t>, _idx_x: u32, _idx_y: u32, _idx_z: u32) -> Vector3<$t> { loop {} } 97 | 98 | #[inspirv(intrinsic(shuffle(num_in0 = 2, num_in1 = 4, num_out = 3)))] 99 | pub fn shuffle3x4(self, _v2: Vector4<$t>, _idx_x: u32, _idx_y: u32, _idx_z: u32) -> Vector3<$t> { loop {} } 100 | 101 | #[inspirv(intrinsic(shuffle(num_in0 = 2, num_in1 = 2, num_out = 4)))] 102 | pub fn shuffle4x2(self, _v2: Vector2<$t>, _idx_x: u32, _idx_y: u32, _idx_z: u32, _idx_w: u32) -> Vector4<$t> { loop {} } 103 | 104 | #[inspirv(intrinsic(shuffle(num_in0 = 2, num_in1 = 3, num_out = 4)))] 105 | pub fn shuffle4x3(self, _v2: Vector3<$t>, _idx_x: u32, _idx_y: u32, _idx_z: u32, _idx_w: u32) -> Vector4<$t> { loop {} } 106 | 107 | #[inspirv(intrinsic(shuffle(num_in0 = 2, num_in1 = 4, num_out = 4)))] 108 | pub fn shuffle4x4(self, _v2: Vector4<$t>, _idx_x: u32, _idx_y: u32, _idx_z: u32, _idx_w: u32) -> Vector4<$t> { loop {} } 109 | } 110 | )*) 111 | } 112 | 113 | vector2_impl! { usize u16 u32 u64 isize i16 i32 i64 f32 f64 bool } 114 | 115 | macro_rules! vector2_ops_impl { 116 | ($($t:ty)*) => ($( 117 | impl Add for Vector2<$t> { 118 | type Output = Vector2<$t>; 119 | 120 | #[inspirv(intrinsic(add))] 121 | fn add(self, rhs: Vector2<$t>) -> Self::Output { 122 | Vector2 { 123 | x: self.x + rhs.x, 124 | y: self.y + rhs.y, 125 | } 126 | } 127 | } 128 | 129 | impl AddAssign for Vector2<$t> { 130 | #[inline] 131 | fn add_assign(&mut self, rhs: Vector2<$t>) { 132 | *self = *self + rhs; 133 | } 134 | } 135 | 136 | impl Sub for Vector2<$t> { 137 | type Output = Vector2<$t> ; 138 | 139 | #[inspirv(intrinsic(sub))] 140 | fn sub(self, rhs: Vector2<$t> ) -> Self::Output { 141 | Vector2 { 142 | x: self.x - rhs.x, 143 | y: self.y - rhs.y, 144 | } 145 | } 146 | } 147 | 148 | impl SubAssign for Vector2<$t> { 149 | #[inline] 150 | fn sub_assign(&mut self, rhs: Vector2<$t> ) { 151 | *self = *self - rhs; 152 | } 153 | } 154 | 155 | impl Mul> for $t { 156 | type Output= Vector2<$t>; 157 | #[inspirv(intrinsic(mul))] 158 | fn mul(self, _rhs: Vector2<$t>) -> Self::Output { loop {} } 159 | } 160 | )*) 161 | } 162 | 163 | vector2_ops_impl! { usize u16 u32 u64 isize i16 i32 i64 f32 f64 } 164 | 165 | pub type Float2 = Vector2; 166 | 167 | impl Float2 { 168 | #[inspirv(intrinsic(mul))] 169 | pub fn dot(self, rhs: Float2) -> f32 { self.x * rhs.x + self.y * rhs.y } 170 | 171 | #[inspirv(intrinsic(outer_product))] 172 | pub fn outer(self, _rhs: Float2) -> Matrix2x2 { loop {} } 173 | 174 | #[inspirv(intrinsic(normalize))] 175 | pub fn normalize(self) -> Float2 { loop {} } 176 | } 177 | 178 | #[derive(Copy)] 179 | #[inspirv(vector(components = 3))] 180 | pub struct Vector3 { 181 | pub x: T, 182 | pub y: T, 183 | pub z: T, 184 | } 185 | 186 | macro_rules! vector3_impl { 187 | ($($t:ty)*) => ($( 188 | impl Vector3<$t> { 189 | #[inspirv(intrinsic(vector_new(1, 1, 1)))] 190 | pub fn new(x: $t, y: $t, z: $t) -> Vector3<$t> { 191 | Vector3 { x: x, y: y, z: z} 192 | } 193 | 194 | #[inspirv(intrinsic(vector_new(1, 2)))] 195 | pub fn from_1_2(x: $t, yz: Vector2<$t>) -> Vector3<$t> { 196 | Vector3 { x: x, y: yz.x, z: yz.y} 197 | } 198 | 199 | #[inspirv(intrinsic(vector_new(2, 1)))] 200 | pub fn from_2_1(xy: Vector2<$t>, z: $t) -> Vector3<$t> { 201 | Vector3 { x: xy.x, y: xy.y, z: z} 202 | } 203 | 204 | #[inspirv(intrinsic(swizzle(num_in = 3, num_out = 2)))] 205 | pub fn swizzle2(self, idx_x: u32, idx_y: u32) -> Vector2<$t> { 206 | let x = match idx_x { 207 | 0 => self.x, 208 | 1 => self.y, 209 | 2 => self.z, 210 | _ => panic!("Swizzle index x out of range {:?}", idx_x), 211 | }; 212 | let y = match idx_y { 213 | 0 => self.x, 214 | 1 => self.y, 215 | 2 => self.z, 216 | _ => panic!("Swizzle index y out of range {:?}", idx_y), 217 | }; 218 | 219 | Vector2 { x: x, y: y } 220 | } 221 | 222 | #[inspirv(intrinsic(swizzle(num_in = 3, num_out = 3)))] 223 | pub fn swizzle3(self, idx_x: u32, idx_y: u32, idx_z: u32) -> Vector3<$t> { 224 | let x = match idx_x { 225 | 0 => self.x, 226 | 1 => self.y, 227 | 2 => self.z, 228 | _ => panic!("Swizzle index x out of range {:?}", idx_x), 229 | }; 230 | let y = match idx_y { 231 | 0 => self.x, 232 | 1 => self.y, 233 | 2 => self.z, 234 | _ => panic!("Swizzle index y out of range {:?}", idx_y), 235 | }; 236 | let z = match idx_z { 237 | 0 => self.x, 238 | 1 => self.y, 239 | 2 => self.z, 240 | _ => panic!("Swizzle index z out of range {:?}", idx_z), 241 | }; 242 | 243 | Vector3 { x: x, y: y, z: z } 244 | } 245 | 246 | #[inspirv(intrinsic(swizzle(num_in = 3, num_out = 4)))] 247 | pub fn swizzle4(self, idx_x: u32, idx_y: u32, idx_z: u32, idx_w: u32) -> Vector4<$t> { 248 | let x = match idx_x { 249 | 0 => self.x, 250 | 1 => self.y, 251 | 2 => self.z, 252 | _ => panic!("Swizzle index x out of range {:?}", idx_x), 253 | }; 254 | let y = match idx_y { 255 | 0 => self.x, 256 | 1 => self.y, 257 | 2 => self.z, 258 | _ => panic!("Swizzle index y out of range {:?}", idx_y), 259 | }; 260 | let z = match idx_z { 261 | 0 => self.x, 262 | 1 => self.y, 263 | 2 => self.z, 264 | _ => panic!("Swizzle index z out of range {:?}", idx_z), 265 | }; 266 | let w = match idx_w { 267 | 0 => self.x, 268 | 1 => self.y, 269 | 2 => self.z, 270 | _ => panic!("Swizzle index w out of range {:?}", idx_w), 271 | }; 272 | 273 | Vector4 { x: x, y: y, z: z, w: w } 274 | } 275 | 276 | #[inspirv(intrinsic(shuffle(num_in0 = 3, num_in1 = 2, num_out = 2)))] 277 | pub fn shuffle2x2(self, _v2: Vector2<$t>, _idx_x: u32, _idx_y: u32) -> Vector2<$t> { loop {} } 278 | 279 | #[inspirv(intrinsic(shuffle(num_in0 = 3, num_in1 = 3, num_out = 2)))] 280 | pub fn shuffle2x3(self, _v2: Vector3<$t>, _idx_x: u32, _idx_y: u32) -> Vector2<$t> { loop {} } 281 | 282 | #[inspirv(intrinsic(shuffle(num_in0 = 3, num_in1 = 4, num_out = 2)))] 283 | pub fn shuffle2x4(self, _v2: Vector4<$t>, _idx_x: u32, _idx_y: u32) -> Vector2<$t> { loop {} } 284 | 285 | #[inspirv(intrinsic(shuffle(num_in0 = 3, num_in1 = 2, num_out = 3)))] 286 | pub fn shuffle3x2(self, _v2: Vector2<$t>, _idx_x: u32, _idx_y: u32, _idx_z: u32) -> Vector3<$t> { loop {} } 287 | 288 | #[inspirv(intrinsic(shuffle(num_in0 = 3, num_in1 = 3, num_out = 3)))] 289 | pub fn shuffle3x3(self, _v2: Vector3<$t>, _idx_x: u32, _idx_y: u32, _idx_z: u32) -> Vector3<$t> { loop {} } 290 | 291 | #[inspirv(intrinsic(shuffle(num_in0 = 3, num_in1 = 4, num_out = 3)))] 292 | pub fn shuffle3x4(self, _v2: Vector4<$t>, _idx_x: u32, _idx_y: u32, _idx_z: u32) -> Vector3<$t> { loop {} } 293 | 294 | #[inspirv(intrinsic(shuffle(num_in0 = 3, num_in1 = 2, num_out = 4)))] 295 | pub fn shuffle4x2(self, _v2: Vector2<$t>, _idx_x: u32, _idx_y: u32, _idx_z: u32, _idx_w: u32) -> Vector4<$t> { loop {} } 296 | 297 | #[inspirv(intrinsic(shuffle(num_in0 = 3, num_in1 = 3, num_out = 4)))] 298 | pub fn shuffle4x3(self, _v2: Vector3<$t>, _idx_x: u32, _idx_y: u32, _idx_z: u32, _idx_w: u32) -> Vector4<$t> { loop {} } 299 | 300 | #[inspirv(intrinsic(shuffle(num_in0 = 3, num_in1 = 4, num_out = 4)))] 301 | pub fn shuffle4x4(self, _v2: Vector4<$t>, _idx_x: u32, _idx_y: u32, _idx_z: u32, _idx_w: u32) -> Vector4<$t> { loop {} } 302 | } 303 | )*) 304 | } 305 | 306 | vector3_impl! { usize u16 u32 u64 isize i16 i32 i64 f32 f64 bool } 307 | 308 | macro_rules! vector3_ops_impl { 309 | ($($t:ty)*) => ($( 310 | impl Add for Vector3<$t> { 311 | type Output = Vector3<$t>; 312 | 313 | #[inspirv(intrinsic(add))] 314 | fn add(self, rhs: Vector3<$t>) -> Self::Output { 315 | Vector3 { 316 | x: self.x + rhs.x, 317 | y: self.y + rhs.y, 318 | z: self.z + rhs.z, 319 | } 320 | } 321 | } 322 | 323 | impl AddAssign for Vector3<$t> { 324 | #[inline] 325 | fn add_assign(&mut self, rhs: Vector3<$t>) { 326 | *self = *self + rhs; 327 | } 328 | } 329 | 330 | impl Sub for Vector3<$t> { 331 | type Output = Vector3<$t>; 332 | 333 | #[inspirv(intrinsic(sub))] 334 | fn sub(self, rhs: Vector3<$t>) -> Self::Output { 335 | Vector3 { 336 | x: self.x - rhs.x, 337 | y: self.y - rhs.y, 338 | z: self.z - rhs.z, 339 | } 340 | } 341 | } 342 | 343 | impl SubAssign for Vector3<$t> { 344 | #[inline] 345 | fn sub_assign(&mut self, rhs: Vector3<$t>) { 346 | *self = *self - rhs; 347 | } 348 | } 349 | 350 | impl Mul> for $t { 351 | type Output= Vector3<$t>; 352 | #[inspirv(intrinsic(mul))] 353 | fn mul(self, _rhs: Vector3<$t>) -> Self::Output { loop {} } 354 | } 355 | )*) 356 | } 357 | 358 | vector3_ops_impl! { usize u16 u32 u64 isize i16 i32 i64 f32 f64 } 359 | 360 | pub type Float3 = Vector3; 361 | 362 | impl Float3 { 363 | #[inspirv(intrinsic(mul))] 364 | pub fn dot(self, rhs: Float3) -> f32 { self.x * rhs.x + self.y * rhs.y + self.z * rhs.z } 365 | 366 | #[inspirv(intrinsic(outer_product))] 367 | pub fn outer(self, _rhs: Float3) -> Matrix3x3 { loop {} } 368 | 369 | #[inspirv(intrinsic(normalize))] 370 | pub fn normalize(self) -> Float3 { loop {} } 371 | 372 | #[inspirv(intrinsic(cross))] 373 | pub fn cross(self, _rhs: Float3) -> Float3 { loop {} } 374 | } 375 | 376 | #[derive(Copy)] 377 | #[inspirv(vector(components = 4))] 378 | pub struct Vector4 { 379 | pub x: T, 380 | pub y: T, 381 | pub z: T, 382 | pub w: T, 383 | } 384 | 385 | macro_rules! vector4_impl { 386 | ($($t:ty)*) => ($( 387 | impl Vector4<$t> { 388 | #[inspirv(intrinsic(vector_new(1, 1, 1, 1)))] 389 | pub fn new(x: $t, y: $t, z: $t, w: $t) -> Vector4<$t> { 390 | Vector4 { x: x, y: y, z: z, w: w } 391 | } 392 | 393 | #[inspirv(intrinsic(vector_new(1, 1, 2)))] 394 | pub fn from_1_1_2(x: $t, y: $t, zw: Vector2<$t>) -> Vector4<$t> { 395 | Vector4 { x: x, y: y, z: zw.x, w: zw.y } 396 | } 397 | 398 | #[inspirv(intrinsic(vector_new(1, 3)))] 399 | pub fn from_1_3(x: $t, yzw: Vector3<$t>) -> Vector4<$t> { 400 | Vector4 { x: x, y: yzw.x, z: yzw.y, w: yzw.z } 401 | } 402 | 403 | #[inspirv(intrinsic(vector_new(2, 1, 1)))] 404 | pub fn from_2_1_1(xy: Vector2<$t>, z: $t, w: $t) -> Vector4<$t> { 405 | Vector4 { x: xy.x, y: xy.y, z: z, w: w } 406 | } 407 | 408 | #[inspirv(intrinsic(vector_new(2, 2)))] 409 | pub fn from_2_2(xy: Vector2<$t>, zw: Vector2<$t>) -> Vector4<$t> { 410 | Vector4 { x: xy.x, y: xy.y, z: zw.x, w: zw.y } 411 | } 412 | 413 | #[inspirv(intrinsic(vector_new(3, 1)))] 414 | pub fn from_3_1(xyz: Vector3<$t>, w: $t) -> Vector4<$t> { 415 | Vector4 { x: xyz.x, y: xyz.y, z: xyz.z, w: w } 416 | } 417 | 418 | #[inspirv(intrinsic(swizzle(num_in = 4, num_out = 2)))] 419 | pub fn swizzle2(self, _idx_x: u32, _idx_y: u32) -> Vector2<$t> { loop {} } 420 | 421 | #[inspirv(intrinsic(swizzle(num_in = 4, num_out = 3)))] 422 | pub fn swizzle3(self, _idx_x: u32, _idx_y: u32, _idx_z: u32) -> Vector3<$t> { loop {} } 423 | 424 | #[inspirv(intrinsic(swizzle(num_in = 4, num_out = 4)))] 425 | pub fn swizzle4(self, _idx_x: u32, _idx_y: u32, _idx_z: u32, _idx_w: u32) -> Vector4<$t> { loop {} } 426 | 427 | #[inspirv(intrinsic(shuffle(num_in0 = 4, num_in1 = 2, num_out = 2)))] 428 | pub fn shuffle2x2(self, _v2: Vector2<$t>, _idx_x: u32, _idx_y: u32) -> Vector2<$t> { loop {} } 429 | 430 | #[inspirv(intrinsic(shuffle(num_in0 = 4, num_in1 = 3, num_out = 2)))] 431 | pub fn shuffle2x3(self, _v2: Vector3<$t>, _idx_x: u32, _idx_y: u32) -> Vector2<$t> { loop {} } 432 | 433 | #[inspirv(intrinsic(shuffle(num_in0 = 4, num_in1 = 4, num_out = 2)))] 434 | pub fn shuffle2x4(self, _v2: Vector4<$t>, _idx_x: u32, _idx_y: u32) -> Vector2<$t> { loop {} } 435 | 436 | #[inspirv(intrinsic(shuffle(num_in0 = 4, num_in1 = 2, num_out = 3)))] 437 | pub fn shuffle3x2(self, _v2: Vector2<$t>, _idx_x: u32, _idx_y: u32, _idx_z: u32) -> Vector3<$t> { loop {} } 438 | 439 | #[inspirv(intrinsic(shuffle(num_in0 = 4, num_in1 = 3, num_out = 3)))] 440 | pub fn shuffle3x3(self, _v2: Vector3<$t>, _idx_x: u32, _idx_y: u32, _idx_z: u32) -> Vector3<$t> { loop {} } 441 | 442 | #[inspirv(intrinsic(shuffle(num_in0 = 4, num_in1 = 4, num_out = 3)))] 443 | pub fn shuffle3x4(self, _v2: Vector4<$t>, _idx_x: u32, _idx_y: u32, _idx_z: u32) -> Vector3<$t> { loop {} } 444 | 445 | #[inspirv(intrinsic(shuffle(num_in0 = 4, num_in1 = 2, num_out = 4)))] 446 | pub fn shuffle4x2(self, _v2: Vector2<$t>, _idx_x: u32, _idx_y: u32, _idx_z: u32, _idx_w: u32) -> Vector4<$t> { loop {} } 447 | 448 | #[inspirv(intrinsic(shuffle(num_in0 = 4, num_in1 = 3, num_out = 4)))] 449 | pub fn shuffle4x3(self, _v2: Vector3<$t>, _idx_x: u32, _idx_y: u32, _idx_z: u32, _idx_w: u32) -> Vector4<$t> { loop {} } 450 | 451 | #[inspirv(intrinsic(shuffle(num_in0 = 4, num_in1 = 4, num_out = 4)))] 452 | pub fn shuffle4x4(self, _v2: Vector4<$t>, _idx_x: u32, _idx_y: u32, _idx_z: u32, _idx_w: u32) -> Vector4<$t> { loop {} } 453 | } 454 | )*) 455 | } 456 | 457 | vector4_impl! { usize u16 u32 u64 isize i16 i32 i64 f32 f64 bool } 458 | 459 | macro_rules! vector4_ops_impl { 460 | ($($t:ty)*) => ($( 461 | impl Add for Vector4<$t> { 462 | type Output = Vector4<$t>; 463 | 464 | #[inspirv(intrinsic(add))] 465 | fn add(self, rhs: Vector4<$t>) -> Self::Output { 466 | Vector4 { 467 | x: self.x + rhs.x, 468 | y: self.y + rhs.y, 469 | z: self.z + rhs.z, 470 | w: self.w + rhs.w, 471 | } 472 | } 473 | } 474 | 475 | impl AddAssign for Vector4<$t> { 476 | #[inline] 477 | fn add_assign(&mut self, rhs: Vector4<$t>) { 478 | *self = *self + rhs; 479 | } 480 | } 481 | 482 | impl Sub for Vector4<$t> { 483 | type Output = Vector4<$t>; 484 | 485 | #[inspirv(intrinsic(sub))] 486 | fn sub(self, rhs: Vector4<$t>) -> Self::Output { 487 | Vector4 { 488 | x: self.x - rhs.x, 489 | y: self.y - rhs.y, 490 | z: self.z - rhs.z, 491 | w: self.w - rhs.w, 492 | } 493 | } 494 | } 495 | 496 | impl SubAssign for Vector4<$t> { 497 | #[inline] 498 | fn sub_assign(&mut self, rhs: Vector4<$t>) { 499 | *self = *self - rhs; 500 | } 501 | } 502 | 503 | impl Mul> for $t { 504 | type Output = Vector4<$t>; 505 | 506 | #[inspirv(intrinsic(mul))] 507 | fn mul(self, _rhs: Vector4<$t>) -> Self::Output { loop {} } 508 | } 509 | )*) 510 | } 511 | 512 | vector4_ops_impl! { usize u16 u32 u64 isize i16 i32 i64 f32 f64 } 513 | 514 | pub type Float4 = Vector4; 515 | 516 | impl Float4 { 517 | #[inspirv(intrinsic(mul))] 518 | pub fn dot(self, rhs: Float4) -> f32 { self.x * rhs.x + self.y * rhs.y + self.z * rhs.z + self.w * rhs.w } 519 | 520 | #[inspirv(intrinsic(outer_product))] 521 | pub fn outer(self, _rhs: Float4) -> Matrix4x4 { loop {} } 522 | 523 | #[inspirv(intrinsic(normalize))] 524 | pub fn normalize(self) -> Float4 { loop {} } 525 | } 526 | -------------------------------------------------------------------------------- /rust-examples/quad.rs: -------------------------------------------------------------------------------- 1 | #![feature(custom_attribute, attr_literals)] 2 | #![allow(unused_attributes)] 3 | 4 | struct QuadVertex { 5 | #[inspirv(location = 0)] pos: Float4, 6 | #[inspirv(location = 1)] color: Float4, 7 | } 8 | 9 | struct QuadVarying { 10 | #[inspirv(builtin = "Position")] 11 | #[inspirv(location = 0)] pos: Float4, 12 | #[inspirv(location = 1)] color: Float4, 13 | } 14 | 15 | struct QuadFragment { 16 | #[inspirv(builtin = "FragCoord")] coord: Float4, 17 | } 18 | 19 | struct QuadOut { 20 | #[inspirv(location = 0)] color: Float4, 21 | } 22 | 23 | #[inspirv(descriptor(set = 0, binding = 0))] 24 | struct Locals { 25 | dimensions: Float2, 26 | } 27 | 28 | /* 29 | #[inspirv(entry_point = "vertex")] 30 | fn vertex(vertex: Attributes) -> QuadVarying { 31 | QuadVarying { 32 | pos: Float4::new(0.0, 0.0, 0.0, 1.0), //vertex.pos, 33 | color: Float4::new(0.0, 0.0, 0.0, 1.0), //vertex.color, 34 | } 35 | } 36 | */ 37 | 38 | #[inspirv(entry_point = "fragment")] 39 | fn fragment(varying: Attributes, fragment: Attributes, local: Cbuffer) -> QuadOut { 40 | // let w = local.dimensions.x; 41 | // let h = local.dimensions.x; 42 | QuadOut { 43 | color: Float4::new( 44 | 0.0, //fragment.coord.x / w, 45 | 0.0, //fragment.coord.y / h, 46 | 0.0, 1.0), 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/adt.rs: -------------------------------------------------------------------------------- 1 | 2 | use rustc::ty::{self, Ty, AdtKind}; 3 | use rustc_trans::Disr; 4 | 5 | use inspirv::types::*; 6 | 7 | use Block; 8 | 9 | pub fn trans_set_discr<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, t: Ty<'tcx>, 10 | val: Id, to: Disr) { 11 | // TODO 12 | } 13 | -------------------------------------------------------------------------------- /src/bin/inspirv-rust.rs: -------------------------------------------------------------------------------- 1 | #![feature(rustc_private)] 2 | 3 | extern crate env_logger; 4 | extern crate getopts; 5 | extern crate inspirv; 6 | extern crate inspirv_rust; 7 | extern crate rustc; 8 | extern crate rustc_driver; 9 | extern crate rustc_back; 10 | extern crate rustc_trans; 11 | extern crate rustc_lint; 12 | extern crate rustc_metadata; 13 | extern crate rustc_errors as errors; 14 | extern crate syntax; 15 | extern crate syntax_pos; 16 | extern crate serialize; 17 | extern crate rustc_incremental; 18 | 19 | use rustc_trans::back::link; 20 | use rustc::dep_graph::DepGraph; 21 | use rustc::session::{Session, build_session, early_error}; 22 | use rustc::session::config::{self, ErrorOutputType, Input, PrintRequest}; 23 | use rustc::util::common::time; 24 | use rustc_driver::{driver, target_features, CompilerCalls, Compilation, RustcDefaultCalls}; 25 | use rustc_metadata::cstore::CStore; 26 | use rustc::lint; 27 | use serialize::json::ToJson; 28 | 29 | use std::process; 30 | use std::path::PathBuf; 31 | 32 | use std::default::Default; 33 | use std::rc::Rc; 34 | use std::str; 35 | 36 | use syntax::ast; 37 | use syntax::feature_gate::{GatedCfg, UnstableFeatures}; 38 | use syntax::parse::{self, PResult}; 39 | use syntax_pos::DUMMY_SP; 40 | 41 | struct SpirvCompilerCalls; 42 | 43 | // copied from RustcDefaultCalls::print_crate_info 44 | // TODO: remove if this ever goes public 45 | fn print_crate_info(sess: &Session, 46 | input: Option<&Input>, 47 | odir: &Option, 48 | ofile: &Option) 49 | -> Compilation { 50 | if sess.opts.prints.is_empty() { 51 | return Compilation::Continue; 52 | } 53 | 54 | let attrs = match input { 55 | None => None, 56 | Some(input) => { 57 | let result = parse_crate_attrs(sess, input); 58 | match result { 59 | Ok(attrs) => Some(attrs), 60 | Err(mut parse_error) => { 61 | parse_error.emit(); 62 | return Compilation::Stop; 63 | } 64 | } 65 | } 66 | }; 67 | for req in &sess.opts.prints { 68 | match *req { 69 | PrintRequest::TargetList => { 70 | let mut targets = rustc_back::target::get_targets().collect::>(); 71 | targets.sort(); 72 | println!("{}", targets.join("\n")); 73 | }, 74 | PrintRequest::Sysroot => println!("{}", sess.sysroot().display()), 75 | PrintRequest::TargetSpec => println!("{}", sess.target.target.to_json().pretty()), 76 | PrintRequest::FileNames | 77 | PrintRequest::CrateName => { 78 | let input = match input { 79 | Some(input) => input, 80 | None => early_error(ErrorOutputType::default(), "no input file provided"), 81 | }; 82 | let attrs = attrs.as_ref().unwrap(); 83 | let t_outputs = driver::build_output_filenames(input, odir, ofile, attrs, sess); 84 | let id = link::find_crate_name(Some(sess), attrs, input); 85 | if *req == PrintRequest::CrateName { 86 | println!("{}", id); 87 | continue; 88 | } 89 | let crate_types = driver::collect_crate_types(sess, attrs); 90 | for &style in &crate_types { 91 | let fname = link::filename_for_input(sess, style, &id, &t_outputs); 92 | println!("{}", 93 | fname.file_name() 94 | .unwrap() 95 | .to_string_lossy()); 96 | } 97 | } 98 | PrintRequest::Cfg => { 99 | let allow_unstable_cfg = UnstableFeatures::from_environment() 100 | .is_nightly_build(); 101 | 102 | let mut cfgs = Vec::new(); 103 | for &(name, ref value) in sess.parse_sess.config.iter() { 104 | let gated_cfg = GatedCfg::gate(&ast::MetaItem { 105 | name: name, 106 | node: ast::MetaItemKind::Word, 107 | span: DUMMY_SP, 108 | }); 109 | if !allow_unstable_cfg && gated_cfg.is_some() { 110 | continue; 111 | } 112 | 113 | cfgs.push(if let &Some(ref value) = value { 114 | format!("{}=\"{}\"", name, value) 115 | } else { 116 | format!("{}", name) 117 | }); 118 | } 119 | 120 | cfgs.sort(); 121 | for cfg in cfgs { 122 | println!("{}", cfg); 123 | } 124 | } 125 | PrintRequest::TargetCPUs => { 126 | } 127 | PrintRequest::TargetFeatures => { 128 | } 129 | PrintRequest::RelocationModels => { 130 | } 131 | PrintRequest::CodeModels => { 132 | } 133 | } 134 | } 135 | return Compilation::Stop; 136 | } 137 | 138 | fn parse_crate_attrs<'a>(sess: &'a Session, input: &Input) -> PResult<'a, Vec> { 139 | match *input { 140 | Input::File(ref ifile) => { 141 | parse::parse_crate_attrs_from_file(ifile, &sess.parse_sess) 142 | } 143 | Input::Str { ref name, ref input } => { 144 | parse::parse_crate_attrs_from_source_str(name.clone(), 145 | input.clone(), 146 | &sess.parse_sess) 147 | } 148 | } 149 | } 150 | 151 | impl<'a> CompilerCalls<'a> for SpirvCompilerCalls { 152 | fn build_controller(&mut self, 153 | _: &Session, 154 | _: &getopts::Matches) 155 | -> driver::CompileController<'a> { 156 | let mut control = driver::CompileController::basic(); 157 | 158 | control.after_analysis.stop = Compilation::Stop; 159 | control.after_analysis.callback = Box::new(move |state| { 160 | state.session.abort_if_errors(); 161 | 162 | let tcx = state.tcx.unwrap(); 163 | let time_passes = state.session.time_passes(); 164 | 165 | // Need to recompute as we don't have directly access to it via CompilerCalls 166 | let incremental_hashes_map = 167 | time(time_passes, 168 | "compute_incremental_hashes_map", 169 | || rustc_incremental::compute_incremental_hashes_map(tcx)); 170 | 171 | { 172 | println!("Pre-trans"); 173 | tcx.print_debug_stats(); 174 | } 175 | 176 | inspirv_rust::translate_to_spirv(tcx, state.analysis.unwrap().clone(), &incremental_hashes_map, &state.out_dir); 177 | 178 | { 179 | println!("Post-trans"); 180 | tcx.print_debug_stats(); 181 | } 182 | }); 183 | 184 | control 185 | } 186 | 187 | fn no_input(&mut self, 188 | matches: &getopts::Matches, 189 | sopts: &config::Options, 190 | cfg: &ast::CrateConfig, 191 | odir: &Option, 192 | ofile: &Option, 193 | descriptions: &errors::registry::Registry) 194 | -> Option<(Input, Option)> { 195 | match matches.free.len() { 196 | 0 => { 197 | if sopts.describe_lints { 198 | let mut ls = lint::LintStore::new(); 199 | rustc_lint::register_builtins(&mut ls, None); 200 | // TODO: describe_lints(&ls, false); 201 | return None; 202 | } 203 | let dep_graph = DepGraph::new(sopts.build_dep_graph()); 204 | let cstore = Rc::new(CStore::new(&dep_graph)); 205 | let sess = build_session(sopts.clone(), 206 | &dep_graph, 207 | None, 208 | descriptions.clone(), 209 | cstore.clone()); 210 | rustc_lint::register_builtins(&mut sess.lint_store.borrow_mut(), Some(&sess)); 211 | let mut cfg = config::build_configuration(&sess, cfg.clone()); 212 | target_features::add_configuration(&mut cfg, &sess); 213 | let should_stop = print_crate_info(&sess, None, odir, ofile); 214 | if should_stop == Compilation::Stop { 215 | return None; 216 | } 217 | early_error(sopts.error_format, "no input filename given"); 218 | } 219 | 1 => panic!("make_input should have provided valid inputs"), 220 | _ => early_error(sopts.error_format, "multiple input filenames provided"), 221 | } 222 | } 223 | 224 | fn late_callback(&mut self, 225 | matches: &getopts::Matches, 226 | sess: &Session, 227 | input: &Input, 228 | odir: &Option, 229 | ofile: &Option) 230 | -> Compilation { 231 | print_crate_info(sess, Some(input), odir, ofile) 232 | .and_then(|| RustcDefaultCalls::list_metadata(sess, matches, input)) 233 | } 234 | } 235 | 236 | fn main() { 237 | env_logger::init().unwrap(); 238 | 239 | let inspirv_compiler_args = ["-h", "--help"]; 240 | let mut rustc_args: Vec = 241 | std::env::args().filter(|arg| !inspirv_compiler_args.contains(&arg.as_ref())).collect(); 242 | 243 | // TODO: use a command line parsing library 244 | for flag in std::env::args().filter(|arg| inspirv_compiler_args.contains(&arg.as_ref())) { 245 | match flag.as_ref() { 246 | "-h" | "--help" => { 247 | let usage = "inspirv-mir [OPTIONS] INPUT \n\nOptions: \n -h, --help Display \ 248 | this message"; 249 | println!("usage: {}", usage); 250 | process::exit(0); 251 | } 252 | _ => panic!("unexpected compiler flag: {}", flag), 253 | } 254 | } 255 | 256 | // rustc_args.push("--target=etc/spirv.json".into()); 257 | match rustc_driver::run_compiler(&rustc_args, &mut SpirvCompilerCalls, None, None) { 258 | (Ok(_), _) => process::exit(0), 259 | (Err(code), _) => { println!("error: {:?}", code); process::exit(code as i32) }, 260 | } 261 | } 262 | -------------------------------------------------------------------------------- /src/block.rs: -------------------------------------------------------------------------------- 1 | 2 | use super::{MirContext, BlockAndBuilder}; 3 | 4 | use rustc::mir; 5 | 6 | use inspirv::core::instruction::*; 7 | use inspirv::core::enumeration::*; 8 | use inspirv::instruction::BranchInstruction; 9 | 10 | use std::cell::Ref as CellRef; 11 | 12 | impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> { 13 | pub fn trans_block(&mut self, bb: mir::BasicBlock) { 14 | let mut bcx = self.bcx(bb); 15 | let data = &CellRef::clone(&self.mir)[bb]; 16 | 17 | println!("trans_block({:?}={:#?})", bb, data); 18 | 19 | for statement in &data.statements { 20 | bcx = self.trans_statement(bcx, statement); 21 | } 22 | 23 | let terminator = data.terminator(); 24 | println!("trans_block: terminator: {:#?}", terminator); 25 | 26 | match terminator.kind { 27 | mir::TerminatorKind::Return => { 28 | bcx.with_block(|block| { 29 | block.spv_block.borrow_mut().branch_instr = Some( 30 | BranchInstruction::Return(OpReturn)); 31 | }); 32 | } 33 | 34 | mir::TerminatorKind::Unreachable => { 35 | bcx.with_block(|block| { 36 | block.spv_block.borrow_mut().branch_instr = Some( 37 | BranchInstruction::Unreachable(OpUnreachable)); 38 | }); 39 | } 40 | 41 | mir::TerminatorKind::Resume => { 42 | bcx.with_block(|block| { 43 | block.spv_block.borrow_mut().branch_instr = Some( 44 | BranchInstruction::Return(OpReturn)); 45 | }); 46 | } 47 | 48 | mir::TerminatorKind::Call { ref func, ref args, ref destination, .. } => { 49 | let callee = self.trans_operand(&bcx, func); 50 | 51 | // TODO: 52 | bcx.with_block(|block| { 53 | block.spv_block.borrow_mut().branch_instr = Some( 54 | BranchInstruction::Unreachable(OpUnreachable)); 55 | }); 56 | // unimplemented!() 57 | } 58 | 59 | mir::TerminatorKind::Drop { target, .. } | 60 | mir::TerminatorKind::Goto { target } | 61 | mir::TerminatorKind::Assert { target, .. } => { 62 | let target = { 63 | let target_bcx = self.bcx(target); 64 | bcx.with_block(|block| block.spv_block.borrow_mut().label) 65 | }; 66 | bcx.with_block(|block| { 67 | block.spv_block.borrow_mut().branch_instr = Some( 68 | BranchInstruction::Branch(OpBranch(target))); 69 | }); 70 | } 71 | 72 | _ => unimplemented!(), 73 | } 74 | 75 | bcx.with_block(|block| { 76 | self.fcx.spv_fn_decl.borrow_mut().add_block(block.spv_block.borrow().clone()); // again.. clones!?.. 77 | }) 78 | } 79 | 80 | fn bcx(&self, bb: mir::BasicBlock) -> BlockAndBuilder<'bcx, 'tcx> { 81 | self.blocks[bb].build() 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /src/constants.rs: -------------------------------------------------------------------------------- 1 | 2 | use rustc::mir; 3 | use rustc::ty::Ty; 4 | use rustc::ty::TypeFoldable; 5 | use rustc::middle::const_val::ConstVal; 6 | 7 | use rustc_const_math::ConstInt::*; 8 | use rustc_const_math::ConstFloat::*; 9 | use rustc_const_math::{ConstInt, ConstIsize, ConstUsize, ConstMathErr}; 10 | 11 | use {MirContext, BlockAndBuilder}; 12 | use context::CrateContext; 13 | use lvalue::ValueRef; 14 | use type_of; 15 | use operand::{OperandRef, OperandValue}; 16 | 17 | use inspirv_builder::module::{self, ConstValue, ConstValueFloat}; 18 | 19 | /// A sized constant rvalue. 20 | #[derive(Clone, Debug)] 21 | pub struct Const<'tcx> { 22 | pub val: ConstRef, 23 | pub ty: Ty<'tcx> 24 | } 25 | 26 | #[derive(Clone, Debug)] 27 | pub enum ConstRef { 28 | Value(ValueRef), 29 | Null, 30 | } 31 | 32 | impl<'tcx> Const<'tcx> { 33 | pub fn new(val: ConstRef, ty: Ty<'tcx>) -> Const<'tcx> { 34 | Const { 35 | val: val, 36 | ty: ty 37 | } 38 | } 39 | 40 | pub fn from_constval<'a>(ccx: &CrateContext<'a, 'tcx>, 41 | cv: ConstVal, 42 | ty: Ty<'tcx>) 43 | -> Const<'tcx> 44 | { 45 | assert!(!ty.has_erasable_regions()); 46 | 47 | let spv_ty = type_of::spv_type_of(ccx, ty).expect_no_ref(); 48 | 49 | let const_val = match cv { 50 | ConstVal::Float(F32(v)) => module::Constant::Float(ConstValueFloat::F32(v)), 51 | ConstVal::Float(F64(v)) => module::Constant::Float(ConstValueFloat::F64(v)), 52 | ConstVal::Float(FInfer {..}) => bug!("MIR must not use `{:?}`", cv), 53 | 54 | ConstVal::Bool(v) => module::Constant::Scalar(ConstValue::Bool(v)), 55 | ConstVal::Integral(I8(v)) => bug!("Inspirv: `i8` is not supported for shaders `{:?}`", cv), 56 | ConstVal::Integral(I16(v)) => module::Constant::Scalar(ConstValue::I16(v)), 57 | ConstVal::Integral(I32(v)) => module::Constant::Scalar(ConstValue::I32(v)), 58 | ConstVal::Integral(I64(v)) => module::Constant::Scalar(ConstValue::I64(v)), 59 | ConstVal::Integral(Isize(v)) => { 60 | let i = v.as_i64(ccx.tcx().sess.target.int_type); 61 | module::Constant::Scalar(ConstValue::I64(i)) 62 | }, 63 | ConstVal::Integral(I128(_)) => bug!("Inspirv: `i128` is not supported for shaders `{:?}`", cv), 64 | ConstVal::Integral(U8(v)) => bug!("Inspirv: `u8` is not supported for shaders `{:?}`", cv), 65 | ConstVal::Integral(U16(v)) => module::Constant::Scalar(ConstValue::U16(v)), 66 | ConstVal::Integral(U32(v)) => module::Constant::Scalar(ConstValue::U32(v)), 67 | ConstVal::Integral(U64(v)) => module::Constant::Scalar(ConstValue::U64(v)), 68 | ConstVal::Integral(Usize(v)) => { 69 | let u = v.as_u64(ccx.tcx().sess.target.uint_type); 70 | module::Constant::Scalar(ConstValue::U64(u)) 71 | }, 72 | ConstVal::Integral(U128(_)) => bug!("Inspirv: `u128` is not supported for shaders `{:?}`", cv), 73 | ConstVal::Char(c) => bug!("Inspirv: `char` is (currently) not supported for shaders `{:?}`", cv), 74 | 75 | ConstVal::Integral(Infer(_)) | 76 | ConstVal::Integral(InferSigned(_)) | 77 | ConstVal::Str(_) | ConstVal::ByteStr(_) => bug!("MIR must not use `{:?}`", cv), // TODO: recheck string support later 78 | 79 | ConstVal::Struct(_) | ConstVal::Tuple(_) | 80 | ConstVal::Array(..) | ConstVal::Repeat(..) | 81 | ConstVal::Function(_) => bug!("MIR must not use `{:?}` (which refers to a local ID)", cv), 82 | }; 83 | 84 | let constant_id = ccx.spv().borrow_mut().define_constant(const_val); 85 | let value = ValueRef { 86 | spvid: constant_id, 87 | spvty: spv_ty, 88 | }; 89 | 90 | Const::new(ConstRef::Value(value), ty) 91 | } 92 | 93 | pub fn to_operand<'a>(self, ccx: &CrateContext<'a, 'tcx>) -> OperandRef<'tcx> { 94 | let val = match self.val { 95 | ConstRef::Value(val) => OperandValue::Immediate(val), 96 | ConstRef::Null => OperandValue::Null, 97 | }; 98 | 99 | OperandRef { 100 | val: val, 101 | ty: self.ty, 102 | } 103 | } 104 | } 105 | 106 | impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> { 107 | pub fn trans_constant(&mut self, 108 | bcx: &BlockAndBuilder<'bcx, 'tcx>, 109 | constant: &mir::Constant<'tcx>) 110 | -> Const<'tcx> 111 | { 112 | println!("trans_constant({:#?})", constant); 113 | 114 | let ty = bcx.monomorphize(&constant.ty); 115 | let result = match constant.literal.clone() { 116 | mir::Literal::Item { def_id, substs } => { 117 | Const::new(ConstRef::Null, ty) 118 | } 119 | 120 | mir::Literal::Promoted { index } => { 121 | unimplemented!() 122 | } 123 | 124 | mir::Literal::Value { value } => { 125 | Const::from_constval(bcx.ccx(), value, ty) 126 | } 127 | }; 128 | 129 | 130 | println!("trans_constant({:#?}) = {:#?}", constant, result); 131 | result 132 | } 133 | } -------------------------------------------------------------------------------- /src/context.rs: -------------------------------------------------------------------------------- 1 | 2 | use rustc::dep_graph::DepTrackingMap; 3 | use rustc::dep_graph::DepTrackingMapConfig; 4 | use rustc::dep_graph::DepNode; 5 | use rustc::ty::{self, Ty, TyCtxt}; 6 | use rustc::util::nodemap::{FxHashMap, FxHashSet, NodeSet}; 7 | use rustc::hir::def::ExportMap; 8 | use rustc::hir::def_id::DefId; 9 | use rustc::middle::cstore::LinkMeta; 10 | use rustc::session::Session; 11 | use rustc::ty::subst::Substs; 12 | use rustc::traits; 13 | use syntax_pos::DUMMY_SP; 14 | 15 | use std::cell::RefCell; 16 | use std::marker::PhantomData; 17 | 18 | use inspirv::core::enumeration::*; 19 | use inspirv_builder::function::FuncId; 20 | use inspirv_builder::module::{ModuleBuilder}; 21 | 22 | use trans_item::TransItem; 23 | use monomorphize::Instance; 24 | 25 | const VERSION_INSPIRV_RUST: u32 = 0x00010000; // |major(1 byte)|minor(1 byte)|patch(2 byte)| 26 | 27 | pub struct SharedCrateContext<'a, 'tcx: 'a> { 28 | tcx: TyCtxt<'a, 'tcx, 'tcx>, 29 | export_map: ExportMap, 30 | exported_symbols: NodeSet, 31 | link_meta: LinkMeta, 32 | translation_items: RefCell>>, 33 | trait_cache: RefCell>>, 34 | project_cache: RefCell>>, 35 | builder: RefCell, 36 | empty_param_env: ty::ParameterEnvironment<'tcx>, 37 | 38 | /// Cache instances of monomorphic and polymorphic items 39 | instances: RefCell, FuncId>>, 40 | } 41 | 42 | impl<'b, 'tcx> SharedCrateContext<'b, 'tcx> { 43 | pub fn new(tcx: TyCtxt<'b, 'tcx, 'tcx>, 44 | export_map: ExportMap, 45 | exported_symbols: NodeSet, 46 | link_meta: LinkMeta) 47 | -> SharedCrateContext<'b, 'tcx> { 48 | let mut builder = ModuleBuilder::new(); 49 | builder.with_source(SourceLanguage::SourceLanguageUnknown, VERSION_INSPIRV_RUST); 50 | 51 | SharedCrateContext { 52 | tcx: tcx, 53 | export_map: export_map, 54 | exported_symbols: exported_symbols, 55 | link_meta: link_meta, 56 | translation_items: RefCell::new(FxHashSet()), 57 | trait_cache: RefCell::new(DepTrackingMap::new(tcx.dep_graph.clone())), 58 | project_cache: RefCell::new(DepTrackingMap::new(tcx.dep_graph.clone())), 59 | builder: RefCell::new(builder), 60 | instances: RefCell::new(FxHashMap()), 61 | empty_param_env: tcx.empty_parameter_environment(), 62 | } 63 | } 64 | 65 | pub fn trait_cache(&self) -> &RefCell>> { 66 | &self.trait_cache 67 | } 68 | 69 | pub fn project_cache(&self) -> &RefCell>> { 70 | &self.project_cache 71 | } 72 | 73 | pub fn tcx<'a>(&'a self) -> TyCtxt<'a, 'tcx, 'tcx> { 74 | self.tcx 75 | } 76 | 77 | pub fn export_map<'a>(&'a self) -> &'a ExportMap { 78 | &self.export_map 79 | } 80 | 81 | pub fn exported_symbols<'a>(&'a self) -> &'a NodeSet { 82 | &self.exported_symbols 83 | } 84 | 85 | pub fn sess<'a>(&'a self) -> &'a Session { 86 | &self.tcx.sess 87 | } 88 | 89 | pub fn spv<'a>(&'a self) -> &'a RefCell { 90 | &self.builder 91 | } 92 | 93 | pub fn link_meta<'a>(&'a self) -> &'a LinkMeta { 94 | &self.link_meta 95 | } 96 | 97 | pub fn translation_items(&self) -> &RefCell>> { 98 | &self.translation_items 99 | } 100 | 101 | /// Given the def-id of some item that has no type parameters, make 102 | /// a suitable "empty substs" for it. 103 | pub fn empty_substs_for_def_id(&self, item_def_id: DefId) -> &'tcx Substs<'tcx> { 104 | Substs::for_item(self.tcx(), item_def_id, 105 | |_, _| self.tcx().mk_region(ty::ReErased), 106 | |_, _| { 107 | bug!("empty_substs_for_def_id: {:?} has type parameters", item_def_id) 108 | }) 109 | } 110 | 111 | pub fn type_is_sized(&self, ty: Ty<'tcx>) -> bool { 112 | ty.is_sized(self.tcx, &self.empty_param_env, DUMMY_SP) 113 | } 114 | } 115 | 116 | pub struct CrateContext<'a, 'tcx: 'a> { 117 | shared: &'a SharedCrateContext<'a, 'tcx>, 118 | } 119 | 120 | impl<'b, 'tcx> CrateContext<'b, 'tcx> { 121 | pub fn new(shared: &'b SharedCrateContext<'b, 'tcx>) -> CrateContext<'b, 'tcx> { 122 | CrateContext { 123 | shared: shared, 124 | } 125 | } 126 | 127 | pub fn shared(&self) -> &'b SharedCrateContext<'b, 'tcx> { 128 | self.shared 129 | } 130 | 131 | pub fn tcx<'a>(&'a self) -> TyCtxt<'a, 'tcx, 'tcx> { 132 | self.shared.tcx 133 | } 134 | 135 | pub fn sess<'a>(&'a self) -> &'a Session { 136 | &self.shared.tcx.sess 137 | } 138 | 139 | pub fn spv<'a>(&'a self) -> &'a RefCell { 140 | &self.shared.builder 141 | } 142 | 143 | pub fn instances<'a>(&'a self) -> &'a RefCell, FuncId>> { 144 | &self.shared.instances 145 | } 146 | } 147 | 148 | // Implement DepTrackingMapConfig for `trait_cache` 149 | pub struct TraitSelectionCache<'tcx> { 150 | data: PhantomData<&'tcx ()> 151 | } 152 | 153 | impl<'tcx> DepTrackingMapConfig for TraitSelectionCache<'tcx> { 154 | type Key = ty::PolyTraitRef<'tcx>; 155 | type Value = traits::Vtable<'tcx, ()>; 156 | fn to_dep_node(key: &ty::PolyTraitRef<'tcx>) -> DepNode { 157 | key.to_poly_trait_predicate().dep_node() 158 | } 159 | } 160 | 161 | pub struct ProjectionCache<'gcx> { 162 | data: PhantomData<&'gcx ()> 163 | } 164 | 165 | impl<'gcx> DepTrackingMapConfig for ProjectionCache<'gcx> { 166 | type Key = Ty<'gcx>; 167 | type Value = Ty<'gcx>; 168 | fn to_dep_node(key: &Self::Key) -> DepNode { 169 | // Ideally, we'd just put `key` into the dep-node, but we 170 | // can't put full types in there. So just collect up all the 171 | // def-ids of structs/enums as well as any traits that we 172 | // project out of. It doesn't matter so much what we do here, 173 | // except that if we are too coarse, we'll create overly 174 | // coarse edges between impls and the trans. For example, if 175 | // we just used the def-id of things we are projecting out of, 176 | // then the key for `::T` and `::T` would both share a dep-node 178 | // (`TraitSelect(SomeTrait)`), and hence the impls for both 179 | // `Foo` and `Bar` would be considered inputs. So a change to 180 | // `Bar` would affect things that just normalized `Foo`. 181 | // Anyway, this heuristic is not ideal, but better than 182 | // nothing. 183 | let def_ids: Vec = 184 | key.walk() 185 | .filter_map(|t| match t.sty { 186 | ty::TyAdt(adt_def, _) => Some(adt_def.did), 187 | ty::TyProjection(ref proj) => Some(proj.trait_ref.def_id), 188 | _ => None, 189 | }) 190 | .collect(); 191 | 192 | DepNode::ProjectionCache { def_ids: def_ids } 193 | } 194 | } 195 | -------------------------------------------------------------------------------- /src/error.rs: -------------------------------------------------------------------------------- 1 | use syntax_pos::MultiSpan; 2 | use rustc_errors::DiagnosticBuilder; 3 | pub use rustc_errors::Level; 4 | 5 | pub type PResult<'a, T> = Result>; 6 | 7 | pub trait DiagnosticBuilderExt { 8 | fn set_span>(self, sp: S) -> Self; 9 | } 10 | 11 | impl<'a> DiagnosticBuilderExt for DiagnosticBuilder<'a> { 12 | fn set_span>(mut self, sp: S) -> Self { 13 | self.span = sp.into(); 14 | self 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/intrinsic.rs: -------------------------------------------------------------------------------- 1 | 2 | #[derive(Clone, Debug, PartialEq, Eq)] 3 | pub enum Intrinsic { 4 | Swizzle { 5 | components_out: u32, 6 | components_in: u32 7 | }, 8 | Shuffle { 9 | components_out: u32, 10 | components_in0: u32, 11 | components_in1: u32 12 | }, 13 | VectorNew(Vec), 14 | Add, 15 | Sub, 16 | Mul, 17 | Transpose, 18 | Inverse, 19 | OuterProduct, 20 | Normalize, 21 | Cross, 22 | Deref, 23 | } 24 | -------------------------------------------------------------------------------- /src/legacy/error.rs: -------------------------------------------------------------------------------- 1 | 2 | use syntax_pos::MultiSpan; 3 | use rustc_errors::DiagnosticBuilder; 4 | pub use rustc_errors::Level; 5 | 6 | pub type PResult<'a, T> = Result>; 7 | 8 | pub trait DiagnosticBuilderExt { 9 | fn set_span>(self, sp: S) -> Self; 10 | } 11 | 12 | impl<'a> DiagnosticBuilderExt for DiagnosticBuilder<'a> { 13 | fn set_span>(mut self, sp: S) -> Self { 14 | self.span = sp.into(); 15 | self 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/legacy/monomorphize.rs: -------------------------------------------------------------------------------- 1 | use rustc::ty::subst::{Subst, Substs}; 2 | use rustc::ty::{Ty, TyCtxt, TypeFoldable}; 3 | use rustc::infer::TransNormalize; 4 | 5 | pub fn apply_param_substs<'a, 'tcx, T>(tcx: &TyCtxt<'a, 'tcx, 'tcx>, param_substs: &Substs<'tcx>, value: &T) -> T 6 | where T: TypeFoldable<'tcx> + TransNormalize<'tcx> 7 | { 8 | let substituted = value.subst(*tcx, param_substs); 9 | tcx.normalize_associated_type(&substituted) 10 | } 11 | 12 | pub fn apply_ty_substs<'a, 'tcx>(tcx: &TyCtxt<'a, 'tcx, 'tcx>, ty_substs: &Substs<'tcx>, ty: Ty<'tcx>) -> Ty<'tcx> { 13 | let substituted = ty.subst(*tcx, ty_substs); 14 | tcx.normalize_associated_type(&substituted) 15 | } 16 | -------------------------------------------------------------------------------- /src/legacy/traits.rs: -------------------------------------------------------------------------------- 1 | use rustc::ty::{self, TyCtxt}; 2 | use rustc::hir::def_id::DefId; 3 | 4 | use std::rc::Rc; 5 | use rustc::traits::{self, Reveal}; 6 | use rustc::ty::subst::{Substs}; 7 | use rustc::ty::fold::TypeFoldable; 8 | use syntax::ast::{Name, DUMMY_NODE_ID}; 9 | use syntax::codemap::{DUMMY_SP}; 10 | 11 | // The following is 99% from Miri (terminator.rs), with error handling from rustc trans 12 | 13 | /// Trait method, which has to be resolved to an impl method. 14 | pub fn resolve_trait_method<'a, 'tcx>( 15 | tcx: &TyCtxt<'a, 'tcx, 'tcx>, 16 | def_id: DefId, 17 | substs: &'tcx Substs<'tcx> 18 | ) -> (DefId, &'tcx Substs<'tcx>) { 19 | let trait_ref = ty::TraitRef::new(def_id, substs); 20 | let trait_id = trait_ref.def_id; 21 | let trait_ref = ty::Binder(trait_ref); 22 | match fulfill_obligation(tcx, trait_ref) { 23 | traits::VtableImpl(vtable_impl) => { 24 | let impl_did = vtable_impl.impl_def_id; 25 | let mname = tcx.item_name(def_id); 26 | // Create a concatenated set of substitutions which includes those from the impl 27 | // and those from the method: 28 | let substs = substs.rebase_onto(*tcx, trait_id, vtable_impl.substs); 29 | let mth = get_impl_method(*tcx, impl_did, substs, mname); 30 | 31 | (mth.method.def_id, mth.substs) 32 | } 33 | 34 | traits::VtableClosure(vtable_closure) => 35 | (vtable_closure.closure_def_id, vtable_closure.substs.substs), 36 | 37 | traits::VtableFnPointer(_fn_ty) => { 38 | let _trait_closure_kind = tcx.lang_items.fn_trait_kind(trait_id).unwrap(); 39 | unimplemented!() 40 | } 41 | 42 | traits::VtableObject(ref _data) => { 43 | unimplemented!() 44 | } 45 | vtable => unreachable!("resolved vtable bad vtable {:?} in trans", vtable), 46 | } 47 | } 48 | 49 | fn fulfill_obligation<'a, 'tcx>( 50 | tcx: &TyCtxt<'a, 'tcx, 'tcx>, 51 | trait_ref: ty::PolyTraitRef<'tcx> 52 | ) -> traits::Vtable<'tcx, ()> { 53 | let trait_ref = tcx.erase_regions(&trait_ref); 54 | 55 | tcx.infer_ctxt(None, None, Reveal::All).enter(|infcx| { 56 | let mut selcx = traits::SelectionContext::new(&infcx); 57 | 58 | let obligation = traits::Obligation::new( 59 | traits::ObligationCause::misc(DUMMY_SP, DUMMY_NODE_ID), 60 | trait_ref.to_poly_trait_predicate(), 61 | ); 62 | 63 | let selection = match selcx.select(&obligation) { 64 | Ok(Some(selection)) => selection, 65 | Ok(None) => { 66 | // Ambiguity can happen when monomorphizing during trans 67 | // expands to some humongo type that never occurred 68 | // statically -- this humongo type can then overflow, 69 | // leading to an ambiguous result. So report this as an 70 | // overflow bug, since I believe this is the only case 71 | // where ambiguity can result. 72 | debug!("Encountered ambiguity selecting `{:?}` during trans, \ 73 | presuming due to overflow", 74 | trait_ref); 75 | // NOTE: in trans, this is a tcx.sess.span_fatal(&self.span,...) error rather than a panic 76 | panic!("reached the recursion limit during monomorphization \ 77 | (selection ambiguity)"); 78 | } 79 | Err(e) => { 80 | panic!("Encountered error `{:?}` selecting `{:?}` during trans", 81 | e, trait_ref) 82 | } 83 | }; 84 | 85 | // Currently, we use a fulfillment context to completely resolve 86 | // all nested obligations. This is because they can inform the 87 | // inference of the impl's type parameters. 88 | let mut fulfill_cx = traits::FulfillmentContext::new(); 89 | let vtable = selection.map(|predicate| { 90 | fulfill_cx.register_predicate_obligation(&infcx, predicate); 91 | }); 92 | infcx.drain_fulfillment_cx_or_panic(DUMMY_SP, &mut fulfill_cx, &vtable) 93 | }) 94 | } 95 | 96 | #[derive(Debug)] 97 | struct ImplMethod<'tcx> { 98 | method: ty::AssociatedItem, 99 | substs: &'tcx Substs<'tcx>, 100 | is_provided: bool, 101 | } 102 | 103 | /// Locates the applicable definition of a method, given its name. 104 | fn get_impl_method<'a, 'tcx>( 105 | tcx: TyCtxt<'a, 'tcx, 'tcx>, 106 | impl_def_id: DefId, 107 | substs: &'tcx Substs<'tcx>, 108 | name: Name, 109 | ) -> ImplMethod<'tcx> { 110 | assert!(!substs.needs_infer()); 111 | 112 | let trait_def_id = tcx.trait_id_of_impl(impl_def_id).unwrap(); 113 | let trait_def = tcx.lookup_trait_def(trait_def_id); 114 | 115 | match trait_def.ancestors(impl_def_id).defs(tcx, name, ty::AssociatedKind::Method).next() { 116 | Some(node_item) => { 117 | let substs = tcx.infer_ctxt(None, None, Reveal::All).enter(|infcx| { 118 | let substs = traits::translate_substs(&infcx, impl_def_id, 119 | substs, node_item.node); 120 | tcx.lift(&substs).unwrap_or_else(|| { 121 | bug!("trans::meth::get_impl_method: translate_substs \ 122 | returned {:?} which contains inference types/regions", 123 | substs); 124 | }) 125 | }); 126 | ImplMethod { 127 | method: node_item.item, 128 | substs: substs, 129 | is_provided: node_item.node.is_from_trait(), 130 | } 131 | } 132 | None => { 133 | bug!("method {:?} not found in {:?}", name, impl_def_id) 134 | } 135 | } 136 | } 137 | -------------------------------------------------------------------------------- /src/lvalue.rs: -------------------------------------------------------------------------------- 1 | 2 | use rustc::mir; 3 | use rustc::ty::{self, Ty, TypeFoldable, TyCtxt}; 4 | use rustc::mir::tcx::LvalueTy; 5 | 6 | use inspirv::types::*; 7 | use inspirv_builder::module::{Type}; 8 | 9 | use {BlockAndBuilder, MirContext, LocalRef}; 10 | use type_of; 11 | 12 | #[derive(Debug, Clone)] 13 | pub enum LvalueRef<'tcx> { 14 | Value(ValueRef, LvalueTy<'tcx>), 15 | Ref(ValueRef, Option, LvalueTy<'tcx>), 16 | SigStruct(Vec, LvalueTy<'tcx>), 17 | Ignore, 18 | } 19 | 20 | #[derive(Debug, Clone)] 21 | enum LvalueInner<'tcx> { 22 | LvalueRef(LvalueRef<'tcx>), 23 | AccessChain, 24 | } 25 | 26 | #[derive(Debug, Clone)] 27 | pub struct ValueRef{ 28 | pub spvid: Id, 29 | pub spvty: Type, 30 | } 31 | 32 | impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> { 33 | fn resolve_lvalue(&mut self, 34 | bcx: &BlockAndBuilder<'bcx, 'tcx>, 35 | lvalue: &mir::Lvalue<'tcx>) 36 | -> LvalueInner<'tcx> { 37 | let ccx = bcx.ccx(); 38 | let tcx = bcx.tcx(); 39 | 40 | let result = match *lvalue { 41 | mir::Lvalue::Local(index) => { 42 | let ty = LvalueTy::from_ty(self.monomorphized_lvalue_ty(lvalue)); 43 | let lvalue_ref = match self.locals[index] { 44 | Some(LocalRef::Local(ref local)) => { 45 | LvalueRef::Value( 46 | ValueRef { 47 | spvid: local.id, 48 | spvty: local.ty.clone(), 49 | }, 50 | ty, 51 | ) 52 | } 53 | Some(LocalRef::Ref { ref local, referent }) => { 54 | LvalueRef::Ref( 55 | ValueRef { 56 | spvid: local.id, 57 | spvty: local.ty.clone(), 58 | }, 59 | referent, 60 | ty, 61 | ) 62 | } 63 | Some(LocalRef::Interface(ref locals)) => { 64 | LvalueRef::SigStruct( 65 | locals.iter().map(|local| { 66 | ValueRef { 67 | spvid: local.id, 68 | spvty: local.ty.clone(), 69 | } 70 | }).collect(), 71 | ty, 72 | ) 73 | } 74 | None => LvalueRef::Ignore, 75 | }; 76 | 77 | LvalueInner::LvalueRef(lvalue_ref) 78 | } 79 | mir::Lvalue::Static(def_id) => { 80 | let const_ty = self.monomorphized_lvalue_ty(lvalue); 81 | bug!("unsupported static lvalue {:?}", const_ty) 82 | } 83 | mir::Lvalue::Projection(ref projection) => { 84 | let tr_base = self.trans_lvalue(bcx, &projection.base); 85 | let ty = self.monomorphized_lvalue_ty(lvalue); 86 | let spv_ty = type_of::spv_type_of(ccx, &ty).expect_no_ref(); 87 | let ty = LvalueTy::from_ty(self.monomorphized_lvalue_ty(lvalue)); 88 | 89 | println!("{:?}", (projection, &tr_base)); 90 | 91 | match (&projection.elem, tr_base) { 92 | (&mir::ProjectionElem::Deref, LvalueRef::Ref(id, Some(referent), _)) => { 93 | LvalueInner::LvalueRef( 94 | LvalueRef::Value( 95 | ValueRef { 96 | spvid: referent, 97 | spvty: spv_ty, 98 | }, 99 | ty 100 | )) 101 | } 102 | _ => unimplemented!(), 103 | } 104 | } 105 | }; 106 | 107 | result 108 | } 109 | 110 | pub fn trans_lvalue(&mut self, 111 | bcx: &BlockAndBuilder<'bcx, 'tcx>, 112 | lvalue: &mir::Lvalue<'tcx>) 113 | -> LvalueRef<'tcx> { 114 | println!("trans_lvalue(lvalue={:?})", lvalue); 115 | 116 | let inner = self.resolve_lvalue(bcx, lvalue); 117 | 118 | // Lift inner lvalue to an simplier type if possible 119 | match inner { 120 | LvalueInner::LvalueRef(lvalue) => lvalue, 121 | LvalueInner::AccessChain => unimplemented!() 122 | } 123 | } 124 | 125 | pub fn monomorphized_lvalue_ty(&self, lvalue: &mir::Lvalue<'tcx>) -> Ty<'tcx> { 126 | let tcx = self.fcx.ccx.tcx(); 127 | let lvalue_ty = lvalue.ty(&self.mir, tcx); 128 | self.fcx.monomorphize(&lvalue_ty.to_ty(tcx)) 129 | } 130 | } 131 | -------------------------------------------------------------------------------- /src/monomorphize.rs: -------------------------------------------------------------------------------- 1 | 2 | use super::*; 3 | use rustc::ty::subst::Subst; 4 | use rustc::ty::fold::{TypeFolder, TypeFoldable}; 5 | use rustc::util::ppaux; 6 | use std::fmt; 7 | 8 | #[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)] 9 | pub struct Instance<'tcx> { 10 | pub def: DefId, 11 | pub substs: &'tcx Substs<'tcx>, 12 | } 13 | 14 | impl<'tcx> fmt::Display for Instance<'tcx> { 15 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 16 | ppaux::parameterized(f, &self.substs, self.def, &[]) 17 | } 18 | } 19 | 20 | impl<'a, 'tcx> Instance<'tcx> { 21 | pub fn new(def_id: DefId, substs: &'tcx Substs<'tcx>) 22 | -> Instance<'tcx> { 23 | assert!(substs.regions().all(|&r| r == ty::ReErased)); 24 | Instance { def: def_id, substs: substs } 25 | } 26 | pub fn mono(scx: &SharedCrateContext<'a, 'tcx>, def_id: DefId) -> Instance<'tcx> { 27 | Instance::new(def_id, scx.empty_substs_for_def_id(def_id)) 28 | } 29 | 30 | pub fn symbol_name(self, scx: &SharedCrateContext<'a, 'tcx>) -> String { 31 | let Instance { def: def_id, substs } = self; 32 | 33 | debug!("symbol_name(def_id={:?}, substs={:?})", 34 | def_id, substs); 35 | 36 | let node_id = scx.tcx().hir.as_local_node_id(def_id); 37 | 38 | if let Some(id) = node_id { 39 | if scx.sess().plugin_registrar_fn.get() == Some(id) { 40 | let svh = &scx.link_meta().crate_hash; 41 | let idx = def_id.index; 42 | return scx.sess().generate_plugin_registrar_symbol(svh, idx); 43 | } 44 | if scx.sess().derive_registrar_fn.get() == Some(id) { 45 | let svh = &scx.link_meta().crate_hash; 46 | let idx = def_id.index; 47 | return scx.sess().generate_derive_registrar_symbol(svh, idx); 48 | } 49 | } 50 | 51 | return scx.tcx().item_name(def_id).as_str().to_string(); 52 | } 53 | 54 | /// For associated constants from traits, return the impl definition. 55 | pub fn resolve_const(&self, scx: &SharedCrateContext<'a, 'tcx>) -> Self { 56 | if let Some(trait_id) = scx.tcx().trait_of_item(self.def) { 57 | let trait_ref = ty::TraitRef::new(trait_id, self.substs); 58 | let trait_ref = ty::Binder(trait_ref); 59 | let vtable = fulfill_obligation(scx, DUMMY_SP, trait_ref); 60 | if let traits::VtableImpl(vtable_impl) = vtable { 61 | let name = scx.tcx().item_name(self.def); 62 | let ac = scx.tcx().associated_items(vtable_impl.impl_def_id) 63 | .find(|item| item.kind == ty::AssociatedKind::Const && item.name == name); 64 | if let Some(ac) = ac { 65 | return Instance::new(ac.def_id, vtable_impl.substs); 66 | } 67 | } 68 | } 69 | 70 | *self 71 | } 72 | } 73 | 74 | /// Monomorphizes a type from the AST by first applying the in-scope 75 | /// substitutions and then normalizing any associated types. 76 | pub fn apply_param_substs<'a, 'tcx, T>(scx: &SharedCrateContext<'a, 'tcx>, 77 | param_substs: &Substs<'tcx>, 78 | value: &T) 79 | -> T 80 | where T: TransNormalize<'tcx> 81 | { 82 | let tcx = scx.tcx(); 83 | debug!("apply_param_substs(param_substs={:?}, value={:?})", param_substs, value); 84 | let substituted = value.subst(tcx, param_substs); 85 | let substituted = scx.tcx().erase_regions(&substituted); 86 | AssociatedTypeNormalizer::new(scx).fold(&substituted) 87 | } 88 | 89 | struct AssociatedTypeNormalizer<'a, 'b: 'a, 'gcx: 'b> { 90 | shared: &'a SharedCrateContext<'b, 'gcx>, 91 | } 92 | 93 | impl<'a, 'b, 'gcx> AssociatedTypeNormalizer<'a, 'b, 'gcx> { 94 | fn new(shared: &'a SharedCrateContext<'b, 'gcx>) -> Self { 95 | AssociatedTypeNormalizer { 96 | shared: shared, 97 | } 98 | } 99 | 100 | fn fold>(&mut self, value: &T) -> T { 101 | if !value.has_projection_types() { 102 | value.clone() 103 | } else { 104 | value.fold_with(self) 105 | } 106 | } 107 | } 108 | 109 | impl<'a, 'b, 'gcx> TypeFolder<'gcx, 'gcx> for AssociatedTypeNormalizer<'a, 'b, 'gcx> { 110 | fn tcx<'c>(&'c self) -> TyCtxt<'c, 'gcx, 'gcx> { 111 | self.shared.tcx() 112 | } 113 | 114 | fn fold_ty(&mut self, ty: Ty<'gcx>) -> Ty<'gcx> { 115 | if !ty.has_projection_types() { 116 | ty 117 | } else { 118 | self.shared.project_cache().memoize(ty, || { 119 | debug!("AssociatedTypeNormalizer: ty={:?}", ty); 120 | self.shared.tcx().normalize_associated_type(&ty) 121 | }) 122 | } 123 | } 124 | } -------------------------------------------------------------------------------- /src/operand.rs: -------------------------------------------------------------------------------- 1 | 2 | use rustc::mir; 3 | use rustc::ty::{self, Ty, TypeFoldable, TyCtxt}; 4 | use inspirv::core::instruction::*; 5 | 6 | use {BlockAndBuilder, MirContext}; 7 | use lvalue::{LvalueRef, ValueRef}; 8 | 9 | #[derive(Debug)] 10 | pub enum OperandValue { 11 | Immediate(ValueRef), 12 | Null, 13 | } 14 | 15 | #[derive(Debug)] 16 | pub struct OperandRef<'tcx> { 17 | // The value. 18 | pub val: OperandValue, 19 | 20 | // The type of value being returned. 21 | pub ty: Ty<'tcx> 22 | } 23 | 24 | impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> { 25 | pub fn trans_operand(&mut self, 26 | bcx: &BlockAndBuilder<'bcx, 'tcx>, 27 | operand: &mir::Operand<'tcx>) 28 | -> Option> 29 | { 30 | println!("trans_operand(operand={:#?})", operand); 31 | 32 | match *operand { 33 | mir::Operand::Consume(ref lvalue) => { 34 | self.trans_consume(bcx, lvalue) 35 | } 36 | 37 | mir::Operand::Constant(ref constant) => { 38 | let const_val = self.trans_constant(bcx, constant); 39 | let operand = const_val.to_operand(bcx.ccx()); 40 | Some(operand) 41 | } 42 | } 43 | } 44 | 45 | pub fn trans_load(&mut self, 46 | bcx: &BlockAndBuilder<'bcx, 'tcx>, 47 | spv_val: ValueRef, 48 | ty: Ty<'tcx>) 49 | -> OperandRef<'tcx> 50 | { 51 | println!("trans_load: {:#?} @ {:#?}", spv_val, ty); 52 | let mut builder = self.fcx.spv().borrow_mut(); 53 | let operand_id = builder.alloc_id(); 54 | bcx.with_block(|bcx| { 55 | bcx.spv_block.borrow_mut().emit_instruction(OpLoad(builder.define_type(&spv_val.spvty), operand_id, spv_val.spvid, None)) 56 | }); 57 | 58 | OperandRef { 59 | val: OperandValue::Immediate(ValueRef { 60 | spvid: operand_id, 61 | spvty: spv_val.spvty, 62 | }), 63 | ty: ty, 64 | } 65 | } 66 | 67 | pub fn trans_consume(&mut self, 68 | bcx: &BlockAndBuilder<'bcx, 'tcx>, 69 | lvalue: &mir::Lvalue<'tcx>) 70 | -> Option> 71 | { 72 | println!("trans_consume(lvalue={:#?})", lvalue); 73 | 74 | let tr_lvalue = self.trans_lvalue(bcx, lvalue); 75 | match tr_lvalue { 76 | LvalueRef::Value(val, ty) => { 77 | let ty = ty.to_ty(bcx.tcx()); 78 | Some(self.trans_load(bcx, val, ty)) 79 | } 80 | LvalueRef::Ref { .. } => { 81 | // unimplemented!(), 82 | None 83 | } 84 | LvalueRef::SigStruct(_, _) => { 85 | // unimplemented!(), 86 | None 87 | } 88 | LvalueRef::Ignore => None, 89 | } 90 | } 91 | 92 | pub fn store_operand(&mut self, 93 | bcx: &BlockAndBuilder<'bcx, 'tcx>, 94 | dest: LvalueRef, 95 | operand: OperandRef<'tcx>) 96 | { 97 | println!("store_operand: operand={:#?}", operand); 98 | bcx.with_block(|bcx| { 99 | match operand.val { 100 | OperandValue::Immediate(ref op) => { 101 | match dest { 102 | LvalueRef::Value(ref lval, _) => { 103 | bcx.spv_block.borrow_mut().emit_instruction( 104 | OpStore(lval.spvid, op.spvid, None)) 105 | } 106 | _ => unimplemented!(), 107 | } 108 | } 109 | OperandValue::Null => { 110 | bug!() 111 | } 112 | } 113 | }); 114 | } 115 | } 116 | -------------------------------------------------------------------------------- /src/rvalue.rs: -------------------------------------------------------------------------------- 1 | 2 | use rustc::mir; 3 | 4 | use {BlockAndBuilder, MirContext}; 5 | use lvalue::LvalueRef; 6 | use operand::OperandValue; 7 | 8 | impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> { 9 | pub fn trans_rvalue(&mut self, 10 | bcx: BlockAndBuilder<'bcx, 'tcx>, 11 | dest: LvalueRef, 12 | rvalue: &mir::Rvalue<'tcx>) 13 | -> BlockAndBuilder<'bcx, 'tcx> 14 | { 15 | println!("trans_rvalue(rvalue={:?})", rvalue); 16 | 17 | match *rvalue { 18 | mir::Rvalue::Use(ref operand) => { 19 | let tr_operand = self.trans_operand(&bcx, operand); 20 | if let Some(tr_operand) = tr_operand { 21 | self.store_operand(&bcx, dest, tr_operand); 22 | } 23 | bcx 24 | } 25 | 26 | mir::Rvalue::Cast(mir::CastKind::Misc, ref source, cast_ty) => { 27 | let cast_ty = bcx.monomorphize(&cast_ty); 28 | 29 | // casting a constant 30 | // just define a new constant with cast type 31 | match *source { 32 | mir::Operand::Constant(_) => { 33 | // TODO: 34 | return bcx; 35 | } 36 | _ => {} 37 | } 38 | 39 | let operand = self.trans_operand(&bcx, source).unwrap(); 40 | bcx.with_block(|bcx| { 41 | match operand.val { 42 | OperandValue::Immediate(ref val) => { 43 | println!("cast_rvalue(cast_ty={:?})", cast_ty); 44 | 45 | // TODO: 46 | } 47 | OperandValue::Null => { 48 | bug!() 49 | } 50 | } 51 | }); 52 | bcx 53 | } 54 | 55 | mir::Rvalue::Ref(_, _, ref lvalue) => { 56 | let tr_lvalue = self.trans_lvalue(&bcx, lvalue); 57 | 58 | println!("Ref {:?}", tr_lvalue); 59 | bcx 60 | } 61 | 62 | mir::Rvalue::Repeat(ref elem, ref count) => { 63 | /* 64 | let tr_elem = self.trans_operand(&bcx, elem); 65 | let size = count.value.as_u64(bcx.tcx().sess.target.uint_type); 66 | let size = C_uint(bcx.ccx(), size); 67 | let base = base::get_dataptr_builder(&bcx, dest.llval); 68 | let bcx = bcx.map_block(|block| { 69 | tvec::slice_for_each(block, base, tr_elem.ty, size, |block, llslot| { 70 | self.store_operand_direct(block, llslot, tr_elem); 71 | block 72 | }) 73 | }); 74 | */ 75 | bcx 76 | } 77 | 78 | mir::Rvalue::Aggregate(ref kind, ref operands) => { 79 | /* 80 | match *kind { 81 | mir::AggregateKind::Adt(adt_def, variant_index, _, active_field_index) => { 82 | let disr = Disr::from(adt_def.variants[variant_index].disr_val); 83 | bcx.with_block(|bcx| { 84 | adt::trans_set_discr(bcx, 85 | dest.ty.to_ty(bcx.tcx()), dest.llval, Disr::from(disr)); 86 | }); 87 | for (i, operand) in operands.iter().enumerate() { 88 | let op = self.trans_operand(&bcx, operand); 89 | // Do not generate stores and GEPis for zero-sized fields. 90 | if !common::type_is_zero_size(bcx.ccx(), op.ty) { 91 | let val = adt::MaybeSizedValue::sized(dest.llval); 92 | let field_index = active_field_index.unwrap_or(i); 93 | let lldest_i = adt::trans_field_ptr_builder(&bcx, 94 | dest.ty.to_ty(bcx.tcx()), 95 | val, disr, field_index); 96 | self.store_operand(&bcx, lldest_i, op); 97 | } 98 | } 99 | }, 100 | _ => { 101 | for (i, operand) in operands.iter().enumerate() { 102 | let op = self.trans_operand(&bcx, operand); 103 | // Do not generate stores and GEPis for zero-sized fields. 104 | if !common::type_is_zero_size(bcx.ccx(), op.ty) { 105 | // Note: perhaps this should be StructGep, but 106 | // note that in some cases the values here will 107 | // not be structs but arrays. 108 | let dest = bcx.gepi(dest.llval, &[0, i]); 109 | self.store_operand(&bcx, dest, op); 110 | } 111 | } 112 | } 113 | } 114 | */ 115 | bcx 116 | } 117 | 118 | mir::Rvalue::Box(..) => { 119 | bug!("Invalid box rvalue") 120 | } 121 | 122 | _ => { 123 | /* 124 | assert!(rvalue_creates_operand(&self.mir, &bcx, rvalue)); 125 | let (bcx, temp) = self.trans_rvalue_operand(bcx, rvalue, debug_loc); 126 | self.store_operand(&bcx, dest.llval, temp); 127 | */ 128 | bcx 129 | } 130 | } 131 | } 132 | } -------------------------------------------------------------------------------- /src/statement.rs: -------------------------------------------------------------------------------- 1 | 2 | use {MirContext, BlockAndBuilder}; 3 | use adt; 4 | 5 | use rustc::mir; 6 | use rustc_trans::Disr; 7 | 8 | impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> { 9 | pub fn trans_statement(&mut self, 10 | bcx: BlockAndBuilder<'bcx, 'tcx>, 11 | statement: &mir::Statement<'tcx>) 12 | -> BlockAndBuilder<'bcx, 'tcx> { 13 | println!("trans_statement(statement={:?})", statement); 14 | 15 | match statement.kind { 16 | mir::StatementKind::Assign(ref lvalue, ref rvalue) => { 17 | let tr_dest = self.trans_lvalue(&bcx, lvalue); 18 | self.trans_rvalue(bcx, tr_dest, rvalue) 19 | } 20 | mir::StatementKind::SetDiscriminant{ref lvalue, variant_index} => { 21 | /* 22 | let ty = self.monomorphized_lvalue_ty(lvalue); 23 | let lvalue_transed = self.trans_lvalue(&bcx, lvalue); 24 | bcx.with_block(|bcx| 25 | adt::trans_set_discr(bcx, 26 | ty, 27 | lvalue_transed.spvid, 28 | Disr::from(variant_index)) 29 | ); 30 | */ 31 | bcx 32 | } 33 | mir::StatementKind::InlineAsm { .. } => { 34 | bug!("unsupported inline asm") 35 | } 36 | mir::StatementKind::StorageLive(..) | 37 | mir::StatementKind::StorageDead(..) | 38 | mir::StatementKind::Nop => bcx, 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/trans_item.rs: -------------------------------------------------------------------------------- 1 | 2 | use arena::TypedArena; 3 | use rustc::dep_graph::DepNode; 4 | use rustc_const_eval::fatal_const_eval_err; 5 | use rustc::hir; 6 | use rustc::hir::def_id::DefId; 7 | use rustc::hir::map::DefPathData; 8 | use rustc::ty::{self, Ty, TyCtxt}; 9 | use rustc::ty::TypeFoldable; 10 | use rustc::ty::subst::Substs; 11 | use syntax::ast::{self, NodeId}; 12 | use inspirv::core::enumeration::*; 13 | use inspirv_builder::function::Function; 14 | use inspirv_builder::module::{Type}; 15 | use monomorphize::{self, Instance}; 16 | use context::{CrateContext, SharedCrateContext}; 17 | use {FunctionContext}; 18 | use {trans_function, trans_static}; 19 | use type_of; 20 | 21 | use std::fmt::Write; 22 | use std::iter; 23 | use std::cell::RefCell; 24 | 25 | #[derive(PartialEq, Eq, Clone, Copy, Debug, Hash)] 26 | pub enum TransItem<'tcx> { 27 | Fn(Instance<'tcx>), 28 | Static(NodeId) 29 | } 30 | 31 | impl<'a, 'tcx> TransItem<'tcx> { 32 | pub fn predefine(&self, ccx: &CrateContext<'a, 'tcx>) { 33 | match *self { 34 | TransItem::Static(node_id) => { 35 | let def_id = ccx.tcx().hir.local_def_id(node_id); 36 | let ty = ccx.tcx().item_type(def_id); 37 | let spv_ty = type_of::spv_type_of(ccx, ty); 38 | 39 | /* 40 | let g = declare::define_global(ccx, symbol_name, llty).unwrap_or_else(|| { 41 | ccx.sess().span_fatal(ccx.tcx().hir.span(node_id), 42 | &format!("symbol `{}` is already defined", symbol_name)) 43 | }); 44 | 45 | unsafe { llvm::LLVMRustSetLinkage(g, linkage) }; 46 | 47 | let instance = Instance::mono(ccx.shared(), def_id); 48 | ccx.instances().borrow_mut().insert(instance, g); 49 | */ 50 | } 51 | TransItem::Fn(instance) => { 52 | assert!(!instance.substs.needs_infer() && 53 | !instance.substs.has_param_types()); 54 | 55 | let item_ty = ccx.tcx().item_type(instance.def); 56 | let item_ty = ccx.tcx().erase_regions(&item_ty); 57 | let mono_ty = monomorphize::apply_param_substs(ccx.shared(), instance.substs, &item_ty); 58 | 59 | let spv_fn = ccx.spv().borrow_mut().define_function_named(&instance.symbol_name(ccx.shared())); 60 | 61 | ccx.instances().borrow_mut().insert(instance, spv_fn.id); 62 | } 63 | } 64 | } 65 | 66 | pub fn define(&self, ccx: &CrateContext<'a, 'tcx>) { 67 | match *self { 68 | TransItem::Static(node_id) => { 69 | let def_id = ccx.tcx().hir.local_def_id(node_id); 70 | let _task = ccx.tcx().dep_graph.in_task(DepNode::TransCrateItem(def_id)); 71 | let item = ccx.tcx().hir.expect_item(node_id); 72 | if let hir::ItemStatic(_, m, _) = item.node { 73 | match trans_static(&ccx, m, item.id, &item.attrs) { 74 | Ok(_) => { /* Cool, everything's alright. */ }, 75 | Err(err) => { 76 | // FIXME: shouldn't this be a `span_err`? 77 | fatal_const_eval_err( 78 | ccx.tcx(), &err, item.span, "static"); 79 | } 80 | }; 81 | } else { 82 | span_bug!(item.span, "Mismatch between hir::Item type and TransItem type") 83 | } 84 | } 85 | TransItem::Fn(instance) => { 86 | let _task = ccx.tcx().dep_graph.in_task( 87 | DepNode::TransCrateItem(instance.def)); 88 | 89 | trans_instance(&ccx, instance); 90 | } 91 | } 92 | } 93 | 94 | /// Returns true if there has to be a local copy of this TransItem in every 95 | /// codegen unit that references it (as with inlined functions, for example) 96 | pub fn needs_local_copy(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> bool { 97 | // Currently everything that is instantiated only on demand is done so 98 | // with "internal" linkage, so we need a copy to be present in every 99 | // codegen unit. 100 | // This is coincidental: We could also instantiate something only if it 101 | // is referenced (e.g. a regular, private function) but place it in its 102 | // own codegen unit with "external" linkage. 103 | self.is_instantiated_only_on_demand(tcx) 104 | } 105 | 106 | pub fn is_instantiated_only_on_demand(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> bool { 107 | match *self { 108 | TransItem::Fn(ref instance) => { 109 | !instance.def.is_local() || 110 | instance.substs.types().next().is_some() || 111 | is_closure(tcx, instance.def) 112 | } 113 | TransItem::Static(..) => false, 114 | } 115 | } 116 | 117 | pub fn to_string(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> String { 118 | let hir_map = &tcx.hir; 119 | 120 | return match *self { 121 | TransItem::Fn(instance) => { 122 | to_string_internal(tcx, "fn ", instance) 123 | }, 124 | TransItem::Static(node_id) => { 125 | let def_id = hir_map.local_def_id(node_id); 126 | let instance = Instance::new(def_id, tcx.intern_substs(&[])); 127 | to_string_internal(tcx, "static ", instance) 128 | }, 129 | }; 130 | 131 | fn to_string_internal<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, 132 | prefix: &str, 133 | instance: Instance<'tcx>) 134 | -> String { 135 | let mut result = String::with_capacity(32); 136 | result.push_str(prefix); 137 | let printer = DefPathBasedNames::new(tcx, false, false); 138 | printer.push_instance_as_string(instance, &mut result); 139 | result 140 | } 141 | } 142 | 143 | pub fn is_generic_fn(&self) -> bool { 144 | match *self { 145 | TransItem::Fn(ref instance) => { 146 | instance.substs.types().next().is_some() 147 | } 148 | TransItem::Static(..) => false, 149 | } 150 | } 151 | } 152 | 153 | //=----------------------------------------------------------------------------- 154 | // TransItem String Keys 155 | //=----------------------------------------------------------------------------- 156 | 157 | // The code below allows for producing a unique string key for a trans item. 158 | // These keys are used by the handwritten auto-tests, so they need to be 159 | // predictable and human-readable. 160 | // 161 | // Note: A lot of this could looks very similar to what's already in the 162 | // ppaux module. It would be good to refactor things so we only have one 163 | // parameterizable implementation for printing types. 164 | 165 | /// Same as `unique_type_name()` but with the result pushed onto the given 166 | /// `output` parameter. 167 | pub struct DefPathBasedNames<'a, 'tcx: 'a> { 168 | tcx: TyCtxt<'a, 'tcx, 'tcx>, 169 | omit_disambiguators: bool, 170 | omit_local_crate_name: bool, 171 | } 172 | 173 | impl<'a, 'tcx> DefPathBasedNames<'a, 'tcx> { 174 | pub fn new(tcx: TyCtxt<'a, 'tcx, 'tcx>, 175 | omit_disambiguators: bool, 176 | omit_local_crate_name: bool) 177 | -> Self { 178 | DefPathBasedNames { 179 | tcx: tcx, 180 | omit_disambiguators: omit_disambiguators, 181 | omit_local_crate_name: omit_local_crate_name, 182 | } 183 | } 184 | 185 | pub fn push_type_name(&self, t: Ty<'tcx>, output: &mut String) { 186 | match t.sty { 187 | ty::TyBool => output.push_str("bool"), 188 | ty::TyChar => output.push_str("char"), 189 | ty::TyStr => output.push_str("str"), 190 | ty::TyNever => output.push_str("!"), 191 | ty::TyInt(ast::IntTy::Is) => output.push_str("isize"), 192 | ty::TyInt(ast::IntTy::I8) => output.push_str("i8"), 193 | ty::TyInt(ast::IntTy::I16) => output.push_str("i16"), 194 | ty::TyInt(ast::IntTy::I32) => output.push_str("i32"), 195 | ty::TyInt(ast::IntTy::I64) => output.push_str("i64"), 196 | ty::TyInt(ast::IntTy::I128) => output.push_str("i128"), 197 | ty::TyUint(ast::UintTy::Us) => output.push_str("usize"), 198 | ty::TyUint(ast::UintTy::U8) => output.push_str("u8"), 199 | ty::TyUint(ast::UintTy::U16) => output.push_str("u16"), 200 | ty::TyUint(ast::UintTy::U32) => output.push_str("u32"), 201 | ty::TyUint(ast::UintTy::U64) => output.push_str("u64"), 202 | ty::TyUint(ast::UintTy::U128) => output.push_str("u128"), 203 | ty::TyFloat(ast::FloatTy::F32) => output.push_str("f32"), 204 | ty::TyFloat(ast::FloatTy::F64) => output.push_str("f64"), 205 | ty::TyAdt(adt_def, substs) => { 206 | self.push_def_path(adt_def.did, output); 207 | self.push_type_params(substs, iter::empty(), output); 208 | }, 209 | ty::TyTuple(component_types, _) => { 210 | output.push('('); 211 | for &component_type in component_types { 212 | self.push_type_name(component_type, output); 213 | output.push_str(", "); 214 | } 215 | if !component_types.is_empty() { 216 | output.pop(); 217 | output.pop(); 218 | } 219 | output.push(')'); 220 | }, 221 | ty::TyRawPtr(ty::TypeAndMut { ty: inner_type, mutbl } ) => { 222 | output.push('*'); 223 | match mutbl { 224 | hir::MutImmutable => output.push_str("const "), 225 | hir::MutMutable => output.push_str("mut "), 226 | } 227 | 228 | self.push_type_name(inner_type, output); 229 | }, 230 | ty::TyRef(_, ty::TypeAndMut { ty: inner_type, mutbl }) => { 231 | output.push('&'); 232 | if mutbl == hir::MutMutable { 233 | output.push_str("mut "); 234 | } 235 | 236 | self.push_type_name(inner_type, output); 237 | }, 238 | ty::TyArray(inner_type, len) => { 239 | output.push('['); 240 | self.push_type_name(inner_type, output); 241 | write!(output, "; {}", len).unwrap(); 242 | output.push(']'); 243 | }, 244 | ty::TySlice(inner_type) => { 245 | output.push('['); 246 | self.push_type_name(inner_type, output); 247 | output.push(']'); 248 | }, 249 | ty::TyDynamic(ref trait_data, ..) => { 250 | if let Some(principal) = trait_data.principal() { 251 | self.push_def_path(principal.def_id(), output); 252 | self.push_type_params(principal.skip_binder().substs, 253 | trait_data.projection_bounds(), 254 | output); 255 | } 256 | }, 257 | ty::TyFnDef(.., &ty::BareFnTy{ unsafety, abi, ref sig } ) | 258 | ty::TyFnPtr(&ty::BareFnTy{ unsafety, abi, ref sig } ) => { 259 | if unsafety == hir::Unsafety::Unsafe { 260 | output.push_str("unsafe "); 261 | } 262 | 263 | output.push_str("fn("); 264 | 265 | let sig = self.tcx.erase_late_bound_regions_and_normalize(sig); 266 | 267 | if !sig.inputs().is_empty() { 268 | for ¶meter_type in sig.inputs() { 269 | self.push_type_name(parameter_type, output); 270 | output.push_str(", "); 271 | } 272 | output.pop(); 273 | output.pop(); 274 | } 275 | 276 | if sig.variadic { 277 | if !sig.inputs().is_empty() { 278 | output.push_str(", ..."); 279 | } else { 280 | output.push_str("..."); 281 | } 282 | } 283 | 284 | output.push(')'); 285 | 286 | if !sig.output().is_nil() { 287 | output.push_str(" -> "); 288 | self.push_type_name(sig.output(), output); 289 | } 290 | }, 291 | ty::TyClosure(def_id, ref closure_substs) => { 292 | self.push_def_path(def_id, output); 293 | let generics = self.tcx.item_generics(self.tcx.closure_base_def_id(def_id)); 294 | let substs = closure_substs.substs.truncate_to(self.tcx, generics); 295 | self.push_type_params(substs, iter::empty(), output); 296 | } 297 | ty::TyError | 298 | ty::TyInfer(_) | 299 | ty::TyProjection(..) | 300 | ty::TyParam(_) | 301 | ty::TyAnon(..) => { 302 | bug!("DefPathBasedNames: Trying to create type name for \ 303 | unexpected type: {:?}", t); 304 | } 305 | } 306 | } 307 | 308 | pub fn push_def_path(&self, 309 | def_id: DefId, 310 | output: &mut String) { 311 | let def_path = self.tcx.def_path(def_id); 312 | 313 | // some_crate:: 314 | if !(self.omit_local_crate_name && def_id.is_local()) { 315 | output.push_str(&self.tcx.crate_name(def_path.krate).as_str()); 316 | output.push_str("::"); 317 | } 318 | 319 | // foo::bar::ItemName:: 320 | for part in self.tcx.def_path(def_id).data { 321 | if self.omit_disambiguators { 322 | write!(output, "{}::", part.data.as_interned_str()).unwrap(); 323 | } else { 324 | write!(output, "{}[{}]::", 325 | part.data.as_interned_str(), 326 | part.disambiguator).unwrap(); 327 | } 328 | } 329 | 330 | // remove final "::" 331 | output.pop(); 332 | output.pop(); 333 | } 334 | 335 | fn push_type_params(&self, 336 | substs: &Substs<'tcx>, 337 | projections: I, 338 | output: &mut String) 339 | where I: Iterator> 340 | { 341 | let mut projections = projections.peekable(); 342 | if substs.types().next().is_none() && projections.peek().is_none() { 343 | return; 344 | } 345 | 346 | output.push('<'); 347 | 348 | for type_parameter in substs.types() { 349 | self.push_type_name(type_parameter, output); 350 | output.push_str(", "); 351 | } 352 | 353 | for projection in projections { 354 | let projection = projection.skip_binder(); 355 | let name = &projection.item_name.as_str(); 356 | output.push_str(name); 357 | output.push_str("="); 358 | self.push_type_name(projection.ty, output); 359 | output.push_str(", "); 360 | } 361 | 362 | output.pop(); 363 | output.pop(); 364 | 365 | output.push('>'); 366 | } 367 | 368 | pub fn push_instance_as_string(&self, 369 | instance: Instance<'tcx>, 370 | output: &mut String) { 371 | self.push_def_path(instance.def, output); 372 | self.push_type_params(instance.substs, iter::empty(), output); 373 | } 374 | } 375 | 376 | pub fn is_closure(tcx: TyCtxt, def_id: DefId) -> bool { 377 | tcx.def_key(def_id).disambiguated_data.data == DefPathData::ClosureExpr 378 | } 379 | 380 | pub fn trans_instance<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, instance: Instance<'tcx>) { 381 | println!("trans_instance({})", instance); 382 | 383 | let fn_ty = ccx.tcx().item_type(instance.def); 384 | let fn_ty = ccx.tcx().erase_regions(&fn_ty); 385 | let fn_ty = monomorphize::apply_param_substs(ccx.shared(), instance.substs, &fn_ty); 386 | 387 | let spv_fn_decl = match ccx.instances().borrow().get(&instance) { 388 | Some(&id) => Function { 389 | id: id, 390 | params: Vec::new(), 391 | ret_ty: Type::Void, // Temp value only 392 | interfaces: Vec::new(), 393 | variables: Vec::new(), 394 | control: FunctionControlNone, 395 | blocks: Vec::new(), 396 | }, 397 | None => bug!("Instance `{:?}` not already declared", instance) 398 | }; 399 | 400 | let (arena, mut fcx): (TypedArena<_>, FunctionContext); 401 | arena = TypedArena::new(); 402 | fcx = FunctionContext::new(ccx, 403 | spv_fn_decl, 404 | Some(instance), 405 | &arena); 406 | 407 | if fcx.mir.is_none() { 408 | bug!("attempted translation of `{}` w/o MIR", instance); 409 | } 410 | 411 | if trans_function(&fcx) { 412 | fcx.spv().borrow_mut().push_function(fcx.spv_fn_decl.borrow_mut().clone()); // hmm.. clone .. 413 | } 414 | } 415 | -------------------------------------------------------------------------------- /src/type_of.rs: -------------------------------------------------------------------------------- 1 | 2 | use rustc::hir; 3 | use rustc::ty::{self, Ty, TypeFoldable}; 4 | 5 | use syntax::ast::{IntTy, UintTy, FloatTy}; 6 | 7 | use inspirv::types::*; 8 | use inspirv_builder::Type; 9 | 10 | use context::CrateContext; 11 | use attributes::{self, Attribute}; 12 | 13 | pub enum SpvType { 14 | NoRef(Type), 15 | Ref { 16 | ty: Type, 17 | mutable: bool, 18 | referent: Option, 19 | } 20 | } 21 | 22 | impl SpvType { 23 | pub fn no_ref(self) -> Option { 24 | match self { 25 | SpvType::NoRef(t) => Some(t), 26 | _ => None, 27 | } 28 | } 29 | pub fn expect_no_ref(self) -> Type { 30 | self.no_ref().expect("Unexpected reference type") 31 | } 32 | 33 | pub fn ty(&self) -> &Type { 34 | match *self { 35 | SpvType::NoRef(ref ty) | 36 | SpvType::Ref { ref ty, .. } => ty, 37 | } 38 | } 39 | } 40 | 41 | pub fn spv_type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) -> SpvType { 42 | use self::SpvType::*; 43 | let tcx = cx.tcx(); 44 | match t.sty { 45 | ty::TyBool => NoRef(Type::Bool), 46 | ty::TyInt(IntTy::I8) => NoRef(Type::Int(8, true)), 47 | ty::TyInt(IntTy::I16) => NoRef(Type::Int(16, true)), 48 | ty::TyInt(IntTy::Is) | 49 | ty::TyInt(IntTy::I32) => NoRef(Type::Int(32, true)), // isize 50 | ty::TyInt(IntTy::I64) => NoRef(Type::Int(64, true)), 51 | ty::TyChar | 52 | ty::TyUint(UintTy::U8) => NoRef(Type::Int(8, false)), 53 | ty::TyUint(UintTy::U16) => NoRef(Type::Int(16, false)), 54 | ty::TyUint(UintTy::Us) | 55 | ty::TyUint(UintTy::U32) => NoRef(Type::Int(32, false)), // usize 56 | ty::TyUint(UintTy::U64) => NoRef(Type::Int(64, false)), 57 | ty::TyFloat(FloatTy::F32) => NoRef(Type::Float(32)), 58 | ty::TyFloat(FloatTy::F64) => NoRef(Type::Float(64)), 59 | ty::TyArray(_ty, _len) => unimplemented!(), 60 | 61 | // TyNever: 62 | // Some weird case, appearing sometimes in the code for whatever reason 63 | // Often as supposed temporary variables, which are never really used 64 | // TyTuple(&[]): 65 | // Rust seems to emit () instead of void for function return types 66 | ty::TyNever => NoRef(Type::Void), 67 | ty::TyTuple(_, true) => NoRef(Type::Void), 68 | ty::TyTuple(tys, _) if tys.is_empty() => NoRef(Type::Void), 69 | ty::TyTuple(tys, _) => NoRef(Type::Struct( 70 | tys.iter().map(|ty| spv_type_of(cx, ty).no_ref().unwrap()).collect::>())), 71 | 72 | ty::TyRef(_, ty_mut) => { 73 | Ref { 74 | ty: spv_type_of(cx, ty_mut.ty).no_ref().unwrap(), 75 | mutable: ty_mut.mutbl == hir::Mutability::MutMutable, 76 | referent: None, 77 | } 78 | } 79 | 80 | ty::TyAdt(adt, subs) if adt.is_struct() => { 81 | let attrs = attributes::attributes(cx, adt.did); 82 | let internal_type = attrs.iter().find(|attr| match **attr { 83 | Attribute::Vector { .. } | 84 | Attribute::Matrix { .. } => true, 85 | _ => false, 86 | }); 87 | let wrapper_type = attrs.iter().any(|attr| match *attr { 88 | Attribute::ConstBuffer | 89 | Attribute::Interface => true, 90 | _ => false, 91 | }); 92 | if let Some(internal_type) = internal_type { 93 | match *internal_type { 94 | Attribute::Vector { components } => { 95 | let base = spv_type_of(cx, adt.struct_variant().fields[0].ty(tcx, subs)).no_ref().unwrap(); 96 | NoRef(Type::Vector { 97 | base: Box::new(base), 98 | components: components as u32, 99 | }) 100 | } 101 | Attribute::Matrix { rows, cols } => { 102 | let base = spv_type_of(cx, adt.struct_variant().fields[0].ty(tcx, subs)).no_ref().unwrap(); 103 | if let Type::Vector { base, .. } = base { 104 | NoRef(Type::Matrix { 105 | base: base, 106 | rows: rows as u32, 107 | cols: cols as u32, 108 | }) 109 | } else { 110 | bug!("Unexpected matrix base type ({:?})", base) 111 | } 112 | } 113 | _ => bug!("Unhandled internal type ({:?})", *internal_type), 114 | } 115 | } else if wrapper_type { 116 | spv_type_of(cx, adt.struct_variant().fields[0].ty(tcx, subs)) 117 | } else { 118 | // an actual struct! 119 | // TODO: handle names 120 | NoRef(Type::Struct( 121 | adt.struct_variant() 122 | .fields 123 | .iter() 124 | .map(|field| 125 | spv_type_of(cx, 126 | field.ty(tcx, subs)) 127 | .no_ref().unwrap()) 128 | .collect::>())) 129 | } 130 | } 131 | 132 | _ => { println!("{:?}", t.sty); unimplemented!() }, 133 | } 134 | } 135 | -------------------------------------------------------------------------------- /tests/compile-fail/hello.rs: -------------------------------------------------------------------------------- 1 | 2 | fn main() { 3 | testing //~ ERROR unresolved name 4 | } 5 | -------------------------------------------------------------------------------- /tests/tests.rs: -------------------------------------------------------------------------------- 1 | extern crate compiletest_rs as compiletest; 2 | 3 | use std::path::PathBuf; 4 | 5 | fn run_mode(mode: &'static str) { 6 | let mut config = compiletest::default_config(); 7 | let cfg_mode = mode.parse().ok().expect("Invalid mode"); 8 | 9 | config.mode = cfg_mode; 10 | config.src_base = PathBuf::from(format!("tests/{}", mode)); 11 | 12 | compiletest::run_tests(&config); 13 | } 14 | 15 | #[test] 16 | fn compile_test() { 17 | run_mode("compile-fail"); 18 | } 19 | --------------------------------------------------------------------------------